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 }
 }

Reply via email to