aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorRobert Goss <goss.robert@gmail.com>2024-01-14 17:34:22 +0000
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-30 12:36:52 +0100
commitc3ce1d6d8728969997a556e3f8bc59b726aff49a (patch)
treebf5182f884c3dce66af37c4006d4645b49a3a07d /gcc/rust
parentb49afa9ba4ad94fc71a246bceca2fcc277cb0ada (diff)
downloadgcc-c3ce1d6d8728969997a556e3f8bc59b726aff49a.zip
gcc-c3ce1d6d8728969997a556e3f8bc59b726aff49a.tar.gz
gcc-c3ce1d6d8728969997a556e3f8bc59b726aff49a.tar.bz2
gccrs: Add improved error when no fields in initializer
If a struct type with a variant that has fields is initialized with some fields the expression HIR StructExprStructFields is checked that all the fields are assigned. However, if no fields are initialized the HIR StructExprStruct is generated. This doesn't check if the struct is a unit during typechekc and only fails at the compile stage with a ICE. Add a check at the typecheck stage that makes sure the struct does not have a variant with fields and give an error message based on the rustc one. We have also updated the message given in the case where one field was present to list the missing fields and match more closely the new message. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit) Add additional check * typecheck/rust-hir-type-check-struct-field.h: A helper method to make error added * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve) Update message gcc/testsuite/ChangeLog: * rust/compile/missing_constructor_fields.rs: Added case with no initializers Signed-off-by: Robert Goss <goss.robert@gmail.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc18
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc48
3 files changed, 72 insertions, 3 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 030e5f1..43d183f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1017,6 +1017,24 @@ TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr)
return;
}
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_path_ty);
+ for (auto variant : adt->get_variants ())
+ {
+ 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-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
index 31d2896..792eebf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -25,6 +25,9 @@
#include "rust-tyty.h"
namespace Rust {
+
+struct Error;
+
namespace Resolver {
class TypeCheckStructExpr : public TypeCheckBase
@@ -32,6 +35,12 @@ class TypeCheckStructExpr : public TypeCheckBase
public:
static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr);
+ // Helper for making any errors
+ static Error
+ make_missing_field_error (location_t locus,
+ const std::vector<std::string> &missing_field_names,
+ const std::string &struct_name);
+
protected:
void resolve (HIR::StructExprStructFields &struct_expr);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index 56aa3d8..d2977ac 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -142,7 +142,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
}
// check the arguments are all assigned and fix up the ordering
- if (fields_assigned.size () != variant->num_fields ())
+ std::vector<std::string> missing_field_names;
+ for (auto &field : variant->get_fields ())
+ {
+ auto it = fields_assigned.find (field->get_name ());
+ if (it == fields_assigned.end ())
+ {
+ missing_field_names.push_back (field->get_name ());
+ }
+ }
+ if (!missing_field_names.empty ())
{
if (struct_def->is_union ())
{
@@ -156,8 +165,12 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
}
else if (!struct_expr.has_struct_base ())
{
- rust_error_at (struct_expr.get_locus (), ErrorCode::E0063,
- "constructor is missing fields");
+ Error missing_fields_error
+ = make_missing_field_error (struct_expr.get_locus (),
+ missing_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;
}
else
@@ -392,5 +405,34 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
return true;
}
+Error
+TypeCheckStructExpr::make_missing_field_error (
+ location_t locus, const std::vector<std::string> &missing_field_names,
+ const std::string &struct_name)
+{
+ // Message plurality depends on size
+ if (missing_field_names.size () == 1)
+ {
+ return Error (locus, ErrorCode::E0063,
+ "missing field %s in initializer of %qs",
+ missing_field_names[0].c_str (), struct_name.c_str ());
+ }
+ // Make comma separated string for display
+ std::stringstream display_field_names;
+ bool first = true;
+ for (auto &name : missing_field_names)
+ {
+ if (!first)
+ {
+ display_field_names << ", ";
+ }
+ first = false;
+ display_field_names << name;
+ }
+ return Error (locus, ErrorCode::E0063,
+ "missing fields %s in initializer of %qs",
+ display_field_names.str ().c_str (), struct_name.c_str ());
+}
+
} // namespace Resolver
} // namespace Rust