aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h11
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc42
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_7.rs9
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_8.rs6
5 files changed, 62 insertions, 7 deletions
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 29b5691..0b2b542 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -1679,6 +1679,17 @@ public:
return fields;
};
+ std::vector<std::unique_ptr<StructExprField> > get_fields_as_owner ()
+ {
+ return std::move (fields);
+ };
+
+ void set_fields_as_owner (
+ std::vector<std::unique_ptr<StructExprField> > new_fields)
+ {
+ fields = std::move (new_fields);
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
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 48ab40f..98db278 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -57,6 +57,7 @@ private:
TyTy::ADTType *struct_path_resolved;
TyTy::TyBase *resolved_field;
std::set<std::string> fields_assigned;
+ std::map<size_t, HIR::StructExprField *> adtFieldIndexToField;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 4c09992..a33dad1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -196,6 +196,11 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
struct_expr.struct_base->base_struct->get_locus_slow ());
}
+ size_t field_index;
+ bool ok = struct_path_resolved->get_field (missing, &field_index);
+ rust_assert (ok);
+
+ adtFieldIndexToField[field_index] = implicit_field;
struct_expr.get_fields ().push_back (
std::unique_ptr<HIR::StructExprField> (implicit_field));
}
@@ -207,7 +212,18 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
// assigned field in the constructor is in the same order as the field in the
// type
- // TODO
+ std::vector<std::unique_ptr<HIR::StructExprField> > expr_fields
+ = struct_expr.get_fields_as_owner ();
+ for (auto &f : expr_fields)
+ f.release ();
+
+ std::vector<std::unique_ptr<HIR::StructExprField> > ordered_fields;
+ for (size_t i = 0; i < adtFieldIndexToField.size (); i++)
+ {
+ ordered_fields.push_back (
+ std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i]));
+ }
+ struct_expr.set_fields_as_owner (std::move (ordered_fields));
}
void
@@ -266,9 +282,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
return;
}
+ size_t field_index;
TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ());
TyTy::StructFieldType *field_type
- = struct_path_resolved->get_field (field.field_name);
+ = struct_path_resolved->get_field (field.field_name, &field_index);
if (field_type == nullptr)
{
rust_error_at (field.get_locus (), "unknown field");
@@ -277,7 +294,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
resolved_field = field_type->get_field_type ()->combine (value);
if (resolved_field != nullptr)
- fields_assigned.insert (field.field_name);
+ {
+ fields_assigned.insert (field.field_name);
+ adtFieldIndexToField[field_index] = &field;
+ }
}
void
@@ -291,9 +311,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
return;
}
+ size_t field_index;
TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ());
TyTy::StructFieldType *field_type
- = struct_path_resolved->get_field (field_name);
+ = struct_path_resolved->get_field (field_name, &field_index);
if (field_type == nullptr)
{
rust_error_at (field.get_locus (), "unknown field");
@@ -302,7 +323,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
resolved_field = field_type->get_field_type ()->combine (value);
if (resolved_field != nullptr)
- fields_assigned.insert (field_name);
+ {
+ fields_assigned.insert (field_name);
+ adtFieldIndexToField[field_index] = &field;
+ }
}
void
@@ -315,8 +339,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
return;
}
+ size_t field_index;
TyTy::StructFieldType *field_type
- = struct_path_resolved->get_field (field.get_field_name ());
+ = struct_path_resolved->get_field (field.get_field_name (), &field_index);
if (field_type == nullptr)
{
rust_error_at (field.get_locus (), "unknown field");
@@ -331,7 +356,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
resolved_field = field_type->get_field_type ()->combine (value);
if (resolved_field != nullptr)
- fields_assigned.insert (field.field_name);
+ {
+ fields_assigned.insert (field.field_name);
+ adtFieldIndexToField[field_index] = &field;
+ }
}
} // namespace Resolver
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_7.rs b/gcc/testsuite/rust.test/compilable/struct_init_7.rs
new file mode 100644
index 0000000..615eae7
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_7.rs
@@ -0,0 +1,9 @@
+struct Foo {
+ a: i32,
+ b: f32,
+}
+
+fn main() {
+ let a = Foo { a: 1, b: 2f32 };
+ let b = Foo { b: 4f32, ..a };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_8.rs b/gcc/testsuite/rust.test/compilable/struct_init_8.rs
new file mode 100644
index 0000000..e62f40a
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_8.rs
@@ -0,0 +1,6 @@
+struct Foo(f32, i32);
+
+fn main() {
+ let a = Foo { 1: 1, 0: 2f32 };
+ let b = Foo { ..a };
+}