diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-01-18 22:21:14 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-01-20 09:59:22 +0000 |
commit | cb44a8feb815ee31946b33e713c62ac2d333d7be (patch) | |
tree | 97b64ada54fcedd0dca0d99943ebaf699c2a0eba | |
parent | 4f6f18fe296d4729648eec0b77c8610f0b43445c (diff) | |
download | gcc-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.
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 11 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-struct-field.h | 1 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 42 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/struct_init_7.rs | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/struct_init_8.rs | 6 |
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 }; +} |