https://gcc.gnu.org/g:f0c9201c1f3003f35fa764fa9ebe864f6e123859
commit r16-6846-gf0c9201c1f3003f35fa764fa9ebe864f6e123859 Author: Yap Zhi Heng <[email protected]> Date: Sun Dec 28 21:03:13 2025 +0800 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]> Diff: --- gcc/rust/backend/rust-compile-expr.cc | 20 +++++++++- gcc/rust/typecheck/rust-hir-type-check-expr.cc | 55 +++++++++++++++++++------- gcc/rust/typecheck/rust-tyty.cc | 1 - gcc/testsuite/rust/compile/issue-4163-2.rs | 10 +++++ gcc/testsuite/rust/compile/issue-4163.rs | 9 +++++ 5 files changed, 78 insertions(+), 17 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 7c4cc4a1d213..40bd2829f650 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -499,7 +499,25 @@ CompileExpr::visit (HIR::StructExprStruct &struct_expr) return; } - rust_assert (tyty->is_unit ()); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty); + TyTy::VariantDef *variant = nullptr; + if (adt->is_enum ()) + { + // unwrap variant and ensure that it can be resolved + HirId variant_id; + bool ok = ctx->get_tyctx ()->lookup_variant_definition ( + struct_expr.get_struct_name ().get_mappings ().get_hirid (), + &variant_id); + rust_assert (ok); + + ok = adt->lookup_variant_by_id (variant_id, &variant); + rust_assert (ok); + } + else + { + rust_assert (tyty->is_unit ()); + } + translated = unit_expression (struct_expr.get_locus ()); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 089a40627321..327144f3f9f1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1187,31 +1187,56 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) void TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr) { - TyTy::BaseType *struct_path_ty - = TypeCheckExpr::Resolve (struct_expr.get_struct_name ()); + HIR::PathInExpression &path = struct_expr.get_struct_name (); + + TyTy::BaseType *struct_path_ty = TypeCheckExpr::Resolve (path); if (struct_path_ty->get_kind () != TyTy::TypeKind::ADT) { - rust_error_at (struct_expr.get_struct_name ().get_locus (), - "expected an ADT type for constructor"); + rust_error_at (path.get_locus (), "expected an ADT type for constructor"); return; } TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_path_ty); - for (auto variant : adt->get_variants ()) + TyTy::VariantDef *variant; + + // unwrap and type check the variant if it's an enum + if (adt->is_enum ()) { - if (!variant->get_fields ().empty ()) + HirId variant_id; + bool ok = context->lookup_variant_definition ( + struct_expr.get_struct_name ().get_mappings ().get_hirid (), + &variant_id); + if (!ok) { - std::vector<std::string> field_names; - for (auto &field : variant->get_fields ()) - field_names.push_back (field->get_name ()); - Error missing_fields_error - = TypeCheckStructExpr::make_missing_field_error ( - struct_expr.get_locus (), field_names, - struct_path_ty->get_name ()); - // We might want to return or handle these in the future emit for now. - missing_fields_error.emit (); + rich_location r (line_table, struct_expr.get_locus ()); + r.add_range (struct_expr.get_struct_name ().get_locus ()); + rust_error_at ( + struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574, + "expected a struct, variant or union type, found enum %qs", + adt->get_name ().c_str ()); return; } + + ok = adt->lookup_variant_by_id (variant_id, &variant); + rust_assert (ok); + } + else + { + rust_assert (adt->number_of_variants () == 1); + variant = adt->get_variants ().at (0); + } + + if (!variant->get_fields ().empty ()) + { + std::vector<std::string> field_names; + for (auto &field : variant->get_fields ()) + field_names.push_back (field->get_name ()); + Error missing_fields_error + = TypeCheckStructExpr::make_missing_field_error ( + struct_expr.get_locus (), field_names, struct_path_ty->get_name ()); + // We might want to return or handle these in the future emit for now. + missing_fields_error.emit (); + return; } infered = struct_path_ty; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 4f7beb70c5b8..161c15e78960 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -1604,7 +1604,6 @@ VariantDef::get_field_at_index (size_t index) std::vector<StructFieldType *> & VariantDef::get_fields () { - rust_assert (type != NUM); return fields; } diff --git a/gcc/testsuite/rust/compile/issue-4163-2.rs b/gcc/testsuite/rust/compile/issue-4163-2.rs new file mode 100644 index 000000000000..c36b669679f8 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4163-2.rs @@ -0,0 +1,10 @@ +enum Enum { + NotEmpty {x: i32}, + Struct {}, + Tuple (), +} + +fn main() { + Enum::Struct {}; + Enum::Tuple {}; +} \ No newline at end of file diff --git a/gcc/testsuite/rust/compile/issue-4163.rs b/gcc/testsuite/rust/compile/issue-4163.rs new file mode 100644 index 000000000000..fde5bccef224 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4163.rs @@ -0,0 +1,9 @@ +enum Enum { + Unit, + Tuple(i32), + Struct { x: i32 }, +} + +fn main() { + Enum::Unit {}; +} \ No newline at end of file
