aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-01-18 22:21:14 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-01-20 09:59:22 +0000
commitcb44a8feb815ee31946b33e713c62ac2d333d7be (patch)
tree97b64ada54fcedd0dca0d99943ebaf699c2a0eba /gcc
parent4f6f18fe296d4729648eec0b77c8610f0b43445c (diff)
downloadgcc-cb44a8feb815ee31946b33e713c62ac2d333d7be.zip
gcc-cb44a8feb815ee31946b33e713c62ac2d333d7be.tar.gz
gcc-cb44a8feb815ee31946b33e713c62ac2d333d7be.tar.bz2
When we construct the fields can be in any order.
The gimple interface requires us to have the fields in order as to the Algebraic Data Type which it references.
Diffstat (limited to 'gcc')
-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 };
+}