Skip to content

Commit 32622b7

Browse files
Polygonalrphilberty
authored andcommitted
gccrs: Fix empty struct constructors causing ICE during type checking
gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (visit(StructExprStruct)): Update to properly unwrap enum variants for type checking. * typecheck/rust-tyty.cc (VariantDef::get_fields) : Remove NUM assert. * backend/rust-compile-expr.cc: Update to properly unwrap enum variants for type resolution checking. Signed-off-by: Yap Zhi Heng <[email protected]>
1 parent 0d89970 commit 32622b7

File tree

5 files changed

+78
-17
lines changed

5 files changed

+78
-17
lines changed

gcc/rust/backend/rust-compile-expr.cc

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,25 @@ CompileExpr::visit (HIR::StructExprStruct &struct_expr)
499499
return;
500500
}
501501

502-
rust_assert (tyty->is_unit ());
502+
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
503+
TyTy::VariantDef *variant = nullptr;
504+
if (adt->is_enum ())
505+
{
506+
// unwrap variant and ensure that it can be resolved
507+
HirId variant_id;
508+
bool ok = ctx->get_tyctx ()->lookup_variant_definition (
509+
struct_expr.get_struct_name ().get_mappings ().get_hirid (),
510+
&variant_id);
511+
rust_assert (ok);
512+
513+
ok = adt->lookup_variant_by_id (variant_id, &variant);
514+
rust_assert (ok);
515+
}
516+
else
517+
{
518+
rust_assert (tyty->is_unit ());
519+
}
520+
503521
translated = unit_expression (struct_expr.get_locus ());
504522
}
505523

gcc/rust/typecheck/rust-hir-type-check-expr.cc

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,31 +1187,56 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
11871187
void
11881188
TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr)
11891189
{
1190-
TyTy::BaseType *struct_path_ty
1191-
= TypeCheckExpr::Resolve (struct_expr.get_struct_name ());
1190+
HIR::PathInExpression &path = struct_expr.get_struct_name ();
1191+
1192+
TyTy::BaseType *struct_path_ty = TypeCheckExpr::Resolve (path);
11921193
if (struct_path_ty->get_kind () != TyTy::TypeKind::ADT)
11931194
{
1194-
rust_error_at (struct_expr.get_struct_name ().get_locus (),
1195-
"expected an ADT type for constructor");
1195+
rust_error_at (path.get_locus (), "expected an ADT type for constructor");
11961196
return;
11971197
}
11981198

11991199
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_path_ty);
1200-
for (auto variant : adt->get_variants ())
1200+
TyTy::VariantDef *variant;
1201+
1202+
// unwrap and type check the variant if it's an enum
1203+
if (adt->is_enum ())
12011204
{
1202-
if (!variant->get_fields ().empty ())
1205+
HirId variant_id;
1206+
bool ok = context->lookup_variant_definition (
1207+
struct_expr.get_struct_name ().get_mappings ().get_hirid (),
1208+
&variant_id);
1209+
if (!ok)
12031210
{
1204-
std::vector<std::string> field_names;
1205-
for (auto &field : variant->get_fields ())
1206-
field_names.push_back (field->get_name ());
1207-
Error missing_fields_error
1208-
= TypeCheckStructExpr::make_missing_field_error (
1209-
struct_expr.get_locus (), field_names,
1210-
struct_path_ty->get_name ());
1211-
// We might want to return or handle these in the future emit for now.
1212-
missing_fields_error.emit ();
1211+
rich_location r (line_table, struct_expr.get_locus ());
1212+
r.add_range (struct_expr.get_struct_name ().get_locus ());
1213+
rust_error_at (
1214+
struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574,
1215+
"expected a struct, variant or union type, found enum %qs",
1216+
adt->get_name ().c_str ());
12131217
return;
12141218
}
1219+
1220+
ok = adt->lookup_variant_by_id (variant_id, &variant);
1221+
rust_assert (ok);
1222+
}
1223+
else
1224+
{
1225+
rust_assert (adt->number_of_variants () == 1);
1226+
variant = adt->get_variants ().at (0);
1227+
}
1228+
1229+
if (!variant->get_fields ().empty ())
1230+
{
1231+
std::vector<std::string> field_names;
1232+
for (auto &field : variant->get_fields ())
1233+
field_names.push_back (field->get_name ());
1234+
Error missing_fields_error
1235+
= TypeCheckStructExpr::make_missing_field_error (
1236+
struct_expr.get_locus (), field_names, struct_path_ty->get_name ());
1237+
// We might want to return or handle these in the future emit for now.
1238+
missing_fields_error.emit ();
1239+
return;
12151240
}
12161241

12171242
infered = struct_path_ty;

gcc/rust/typecheck/rust-tyty.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,6 @@ VariantDef::get_field_at_index (size_t index)
16041604
std::vector<StructFieldType *> &
16051605
VariantDef::get_fields ()
16061606
{
1607-
rust_assert (type != NUM);
16081607
return fields;
16091608
}
16101609

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
enum Enum {
2+
NotEmpty {x: i32},
3+
Struct {},
4+
Tuple (),
5+
}
6+
7+
fn main() {
8+
Enum::Struct {};
9+
Enum::Tuple {};
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
enum Enum {
2+
Unit,
3+
Tuple(i32),
4+
Struct { x: i32 },
5+
}
6+
7+
fn main() {
8+
Enum::Unit {};
9+
}

0 commit comments

Comments
 (0)