aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2025-04-17 14:38:04 +0100
committerPhilip Herron <philip.herron@embecosm.com>2025-04-18 09:45:18 +0000
commite77b7c22ab159f967fc2e0bca59468d0df08a023 (patch)
tree6cde3d0cf1238c9f2acea46854bb42285ded8d92
parent5a2d06037c7e0b0f06543db17b8376b6a6fceeb3 (diff)
downloadgcc-e77b7c22ab159f967fc2e0bca59468d0df08a023.zip
gcc-e77b7c22ab159f967fc2e0bca59468d0df08a023.tar.gz
gcc-e77b7c22ab159f967fc2e0bca59468d0df08a023.tar.bz2
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.philip@googlemail.com>
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc54
-rw-r--r--gcc/testsuite/rust/compile/issue-3628.rs10
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/macro-issue2983_2984.rs5
-rw-r--r--gcc/testsuite/rust/compile/struct_init1.rs6
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 1d4d1fa..9d0ee7a 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 1931f08..d8aabc3 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 0000000..5f59789
--- /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 637d572..eeae6eb 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 1875fb4..38f6f38 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 }
}