@@ -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;
}
@@ -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);
@@ -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
@@ -6,5 +6,7 @@ struct Foo {
}
fn main() {
- let x = Foo { x: 0 , y:1 }; // { dg-error "constructor is missing fields" }
-}
\ No newline at end of file
+ let z = Foo { x: 0 , y:1 }; // { dg-error "missing field z in initializer of 'Foo'" }
+ let xz = Foo { y:1 }; // { dg-error "missing fields x, z in initializer of 'Foo'" }
+ let xyz = Foo { }; // { dg-error "missing fields x, y, z in initializer of 'Foo'" }
+}