https://gcc.gnu.org/g:e77b7c22ab159f967fc2e0bca59468d0df08a023
commit e77b7c22ab159f967fc2e0bca59468d0df08a023 Author: Philip Herron <herron.phi...@googlemail.com> Date: Thu Apr 17 14:38:04 2025 +0100 gccrs: Fix ICE in struct expressions The error handling here was done long ago when we didnt know how to do any error handling very well. This removed bad fatal_errors and adds in some nice rich_location error diagnostics instead. Fixes Rust-GCC#3628 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-struct-field.h: keep reference to parent expression * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::TypeCheckStructExpr): update ctor (TypeCheckStructExpr::resolve): remove bad rust_fatal_errors (TypeCheckStructExpr::visit): cleanup errors gcc/testsuite/ChangeLog: * rust/compile/macros/mbe/macro-issue2983_2984.rs: cleanup error diagnotics * rust/compile/struct_init1.rs: likewise * rust/compile/issue-3628.rs: New test. Signed-off-by: Philip Herron <herron.phi...@googlemail.com> Diff: --- .../typecheck/rust-hir-type-check-struct-field.h | 3 ++ gcc/rust/typecheck/rust-hir-type-check-struct.cc | 54 +++++++++++----------- gcc/testsuite/rust/compile/issue-3628.rs | 10 ++++ .../compile/macros/mbe/macro-issue2983_2984.rs | 5 +- gcc/testsuite/rust/compile/struct_init1.rs | 6 +-- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 1d4d1fa5e147..9d0ee7ada6ef 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -60,6 +60,9 @@ private: TyTy::BaseType *resolved_field_value_expr; std::set<std::string> fields_assigned; std::map<size_t, HIR::StructExprField *> adtFieldIndexToField; + + // parent + HIR::Expr &parent; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 1931f08ff4d2..d8aabc37da26 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -28,7 +28,7 @@ TypeCheckStructExpr::TypeCheckStructExpr (HIR::Expr &e) : TypeCheckBase (), resolved (new TyTy::ErrorType (e.get_mappings ().get_hirid ())), struct_path_resolved (nullptr), - variant (&TyTy::VariantDef::get_error_node ()) + variant (&TyTy::VariantDef::get_error_node ()), parent (e) {} TyTy::BaseType * @@ -65,7 +65,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) if (base_unify->get_kind () != struct_path_ty->get_kind ()) { - rust_fatal_error ( + rust_error_at ( struct_expr.get_struct_base ().get_base ().get_locus (), "incompatible types for base struct reference"); return; @@ -82,7 +82,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) bool ok = context->lookup_variant_definition ( struct_expr.get_struct_name ().get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); + if (!ok) + { + 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", + struct_path_resolved->get_name ().c_str ()); + return; + } ok = struct_path_resolved->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); @@ -118,29 +127,14 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) break; } - if (!ok) - { - return; - } - - if (resolved_field_value_expr == nullptr) - { - rust_fatal_error (field->get_locus (), - "failed to resolve type for field"); - ok = false; - break; - } - - context->insert_type (field->get_mappings (), resolved_field_value_expr); + if (ok) + context->insert_type (field->get_mappings (), + resolved_field_value_expr); } - // something failed setting up the fields + // something failed setting up the fields and error's emitted if (!ok) - { - rust_error_at (struct_expr.get_locus (), - "constructor type resolution failure"); - return; - } + return; // check the arguments are all assigned and fix up the ordering std::vector<std::string> missing_field_names; @@ -271,8 +265,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) &field_index); if (!ok) { - rust_error_at (field.get_locus (), "unknown field"); - return true; + rich_location r (line_table, parent.get_locus ()); + r.add_range (field.get_locus ()); + rust_error_at (r, ErrorCode::E0560, "unknown field %qs", + field.field_name.as_string ().c_str ()); + return false; } auto it = adtFieldIndexToField.find (field_index); @@ -317,8 +314,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) bool ok = variant->lookup_field (field_name, &field_type, &field_index); if (!ok) { - rust_error_at (field.get_locus (), "unknown field"); - return true; + rich_location r (line_table, parent.get_locus ()); + r.add_range (field.get_locus ()); + rust_error_at (r, ErrorCode::E0560, "unknown field %qs", + field_name.c_str ()); + return false; } auto it = adtFieldIndexToField.find (field_index); diff --git a/gcc/testsuite/rust/compile/issue-3628.rs b/gcc/testsuite/rust/compile/issue-3628.rs new file mode 100644 index 000000000000..5f5978918e4e --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3628.rs @@ -0,0 +1,10 @@ +pub enum Enum { + Variant1(isize), +} + +impl Enum { + fn static_meth_enum() -> Enum { + Enum { x: 1 } + // { dg-error "expected a struct, variant or union type, found enum .Enum. .E0574." "" { target *-*-* } .-1 } + } +} diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue2983_2984.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue2983_2984.rs index 637d5728c507..eeae6ebb9a5d 100644 --- a/gcc/testsuite/rust/compile/macros/mbe/macro-issue2983_2984.rs +++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue2983_2984.rs @@ -18,10 +18,9 @@ fn main() { // Error let _ = ReadDir { + // { dg-error "unknown field .end_of_stream_but_different. .E0560." "" { target *-*-* } .-1 } inner: 14, end_of_stream: false, - end_of_stream_but_different: false, // { dg-error "failed to resolve type for field" } - // { dg-error "unknown field" "" { target *-*-* } .-1 } - // { dg-prune-output "compilation terminated" } + end_of_stream_but_different: false, }; } diff --git a/gcc/testsuite/rust/compile/struct_init1.rs b/gcc/testsuite/rust/compile/struct_init1.rs index 1875fb4f33ee..38f6f3802a9e 100644 --- a/gcc/testsuite/rust/compile/struct_init1.rs +++ b/gcc/testsuite/rust/compile/struct_init1.rs @@ -4,7 +4,7 @@ struct Foo { } fn main() { - let a = Foo { 0: 10.0, 1: 20.0 }; // { dg-error "failed to resolve type for field" } - // { dg-error "unknown field" "" { target *-*-* } .-1 } - // { dg-prune-output "compilation terminated" } + let a = Foo { 0: 10.0, 1: 20.0 }; + // { dg-error "unknown field .0. .E0560." "" { target *-*-* } .-1 } + // { dg-error "unknown field .1. .E0560." "" { target *-*-* } .-2 } }