From: Yap Zhi Heng Date: Sun, 28 Dec 2025 13:03:13 +0000 (+0800) Subject: gccrs: Fix empty struct constructors causing ICE during type checking X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0c9201c1f3003f35fa764fa9ebe864f6e123859;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 7c4cc4a1d21..40bd2829f65 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); + 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 089a4062732..327144f3f9f 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 (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 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 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 4f7beb70c5b..161c15e7896 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 & 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 00000000000..c36b669679f --- /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 00000000000..fde5bccef22 --- /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