From: Yap Zhi Heng <[email protected]>
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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/32622b71b867ab153371db1e31bae6abfa7b5c2f
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4342
gcc/rust/backend/rust-compile-expr.cc | 20 ++++++-
.../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(-)
create mode 100644 gcc/testsuite/rust/compile/issue-4163-2.rs
create mode 100644 gcc/testsuite/rust/compile/issue-4163.rs
diff --git a/gcc/rust/backend/rust-compile-expr.cc
b/gcc/rust/backend/rust-compile-expr.cc
index 7c4cc4a1d..40bd2829f 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 089a40627..327144f3f 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 4f7beb70c..161c15e78 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 000000000..c36b66967
--- /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 000000000..fde5bccef
--- /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
base-commit: 0d89970b7f65bebd5d8409e9614a881757dbf5ba
--
2.52.0