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 /gcc | |
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.
Diffstat (limited to 'gcc')
-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 }; +} |