Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 50 additions & 9 deletions gcc/rust/backend/rust-compile-expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -559,10 +559,8 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
rust_assert (ok);
}

// compile it
tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);

std::vector<tree> arguments;

if (adt->is_union ())
{
rust_assert (struct_expr.get_fields ().size () == 1);
Expand Down Expand Up @@ -595,17 +593,44 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
}
else
{
// this assumes all fields are in order from type resolution and if a
// base struct was specified those fields are filed via accessors
std::vector<TyTy::StructFieldType *> ordered_variant_fields;

for (size_t i = 0; i < struct_expr.get_fields ().size (); i++)
{
std::string field_name;
const auto &argument = struct_expr.get_fields ().at (i);
switch (argument->get_kind ())
{
case HIR::StructExprField::StructExprFieldKind::IDENTIFIER:
field_name
= (static_cast<HIR::StructExprFieldIdentifier &> (*argument))
.get_field_name ();
break;

case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE:
field_name = (static_cast<HIR::StructExprFieldIdentifierValue &> (
*argument))
.get_field_name ();
break;

case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE:
field_name = std::to_string (
(static_cast<HIR::StructExprFieldIndexValue &> (*argument))
.get_tuple_index ());
break;
}
// assignments are coercion sites so lets convert the rvalue if
// necessary
auto respective_field = variant->get_field_at_index (i);
TyTy::StructFieldType *respective_field = nullptr;
auto _ok
= variant->lookup_field (field_name, &respective_field, nullptr);
rust_assert (_ok);

if (adt->is_struct_struct () || adt->is_tuple_struct ())
ordered_variant_fields.push_back (respective_field);

auto expected = respective_field->get_field_type ();

// process arguments
auto &argument = struct_expr.get_fields ().at (i);
auto lvalue_locus
= ctx->get_mappings ().lookup_location (expected->get_ty_ref ());
auto rvalue_locus = argument->get_locus ();
Expand All @@ -616,7 +641,7 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
argument->get_mappings ().get_hirid (), &actual);

// coerce it if required/possible see
// compile/torture/struct_base_init_1.rs
// compile/torture/struct_base_init.rs
if (ok)
{
rvalue
Expand All @@ -627,8 +652,24 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
// add it to the list
arguments.push_back (rvalue);
}
// We evaluate field expressions in the order they are found, not in the
// order of their declaration, so we reorder the field types according to
// their values and use this correspondence to compile field expressions
// and the ADT type itself. Note that we do not overwrite the fields in
// the original ADT variant type because if the struct fields have a base
// struct, they will be evaluated in the order of the base struct's
// evaluation, which is incorrect.
if (adt->is_struct_struct () || adt->is_tuple_struct ())
{
auto _adt = static_cast<TyTy::ADTType *> (adt->clone ());
_adt->get_variants ()[0]->get_fields () = ordered_variant_fields;
tyty = _adt;
}
}

// compile it
tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);

if (!adt->is_enum ())
{
translated
Expand Down
17 changes: 0 additions & 17 deletions gcc/rust/typecheck/rust-hir-type-check-struct.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,23 +235,6 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
}
rust_assert (struct_expr.union_index != -1);
}
else
{
// everything is ok, now we need to ensure all field values are ordered
// correctly. The GIMPLE backend uses a simple algorithm that assumes each
// assigned field in the constructor is in the same order as the field in
// the type
for (auto &field : struct_expr.get_fields ())
field.release ();

std::vector<std::unique_ptr<HIR::StructExprField> > ordered_fields;
ordered_fields.reserve (adtFieldIndexToField.size ());

for (size_t i = 0; i < adtFieldIndexToField.size (); i++)
ordered_fields.emplace_back (adtFieldIndexToField[i]);

struct_expr.set_fields_as_owner (std::move (ordered_fields));
}

resolved = struct_def;
}
Expand Down
Loading