Skip to content
Merged
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
122 changes: 121 additions & 1 deletion gcc/rust/ast/rust-path.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ struct GenericArgsBinding
// and also identifier is empty, but cheaper computation
}

GenericArgsBinding reconstruct () const
{
std::unique_ptr<Type> new_type = nullptr;
if (type)
new_type = type->reconstruct ();

return GenericArgsBinding (identifier, std::move (new_type), locus);
}

// Creates an error state generic args binding.
static GenericArgsBinding create_error ()
{
Expand Down Expand Up @@ -190,6 +199,22 @@ class GenericArg
return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
}

GenericArg reconstruct () const
{
switch (kind)
{
case Kind::Type:
return create_type (type->reconstruct ());
case Kind::Const:
// FIXME: Use reconstruct_expr when available
return create_const (expression->clone_expr ());
case Kind::Either:
default:
// For ambiguous or error states, copy constructs are sufficient
return GenericArg (*this);
}
}

GenericArg (const GenericArg &other)
: path (other.path), kind (other.kind), locus (other.locus)
{
Expand Down Expand Up @@ -460,6 +485,23 @@ struct GenericArgs

~GenericArgs () = default;

GenericArgs reconstruct () const
{
std::vector<GenericArg> new_args;
new_args.reserve (generic_args.size ());
for (const auto &arg : generic_args)
new_args.push_back (arg.reconstruct ());

std::vector<GenericArgsBinding> new_bindings;
new_bindings.reserve (binding_args.size ());
for (const auto &binding : binding_args)
new_bindings.push_back (binding.reconstruct ());

// Lifetimes are values, so they can be copied directly
return GenericArgs (lifetime_args, std::move (new_args),
std::move (new_bindings), locus);
}

// overloaded assignment operator to vector clone
GenericArgs &operator= (GenericArgs const &other)
{
Expand Down Expand Up @@ -563,6 +605,11 @@ class PathExprSegment

NodeId get_node_id () const { return node_id; }

PathExprSegment reconstruct () const
{
return PathExprSegment (segment_name, locus, generic_args.reconstruct ());
}

bool is_super_path_seg () const
{
return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
Expand Down Expand Up @@ -705,6 +752,20 @@ class PathInExpression : public Path, public ExprWithoutBlock
return convert_to_simple_path (has_opening_scope_resolution);
}

std::unique_ptr<PathInExpression> reconstruct () const
{
std::vector<PathExprSegment> new_segments;
new_segments.reserve (segments.size ());
for (const auto &seg : segments)
new_segments.push_back (seg.reconstruct ());

auto *new_path
= new PathInExpression (std::move (new_segments), outer_attrs, locus,
has_opening_scope_resolution);

return std::unique_ptr<PathInExpression> (new_path);
}

location_t get_locus () const override final { return locus; }

void accept_vis (ASTVisitor &vis) override;
Expand Down Expand Up @@ -1004,6 +1065,14 @@ class TypePathSegmentGeneric : public TypePathSegment
{
return new TypePathSegmentGeneric (*this);
}

TypePathSegmentGeneric *reconstruct_impl () const override
{
return new TypePathSegmentGeneric (get_ident_segment (),
has_separating_scope_resolution,
generic_args.reconstruct (),
get_locus ());
}
};

// A function as represented in a type path
Expand Down Expand Up @@ -1112,6 +1181,21 @@ struct TypePathFunction
return return_type;
}

TypePathFunction reconstruct () const
{
std::vector<std::unique_ptr<Type>> new_inputs;
new_inputs.reserve (inputs.size ());
for (const auto &e : inputs)
new_inputs.push_back (e->reconstruct ());

std::unique_ptr<Type> new_ret = nullptr;
if (return_type)
new_ret = return_type->reconstruct ();

return TypePathFunction (std::move (new_inputs), locus,
std::move (new_ret));
}

location_t get_locus () const { return locus; }
};

Expand Down Expand Up @@ -1159,6 +1243,14 @@ class TypePathSegmentFunction : public TypePathSegment
{
return new TypePathSegmentFunction (*this);
}

TypePathSegmentFunction *reconstruct_impl () const override
{
return new TypePathSegmentFunction (get_ident_segment (),
has_separating_scope_resolution,
function_path.reconstruct (),
get_locus ());
}
};

class TypePath : public TypeNoBounds
Expand Down Expand Up @@ -1327,6 +1419,20 @@ struct QualifiedPathType
QualifiedPathType (QualifiedPathType &&other) = default;
QualifiedPathType &operator= (QualifiedPathType &&other) = default;

QualifiedPathType reconstruct () const
{
auto new_type = type_to_invoke_on->reconstruct ();

// trait_path is stored by value, but reconstruct returns a unique_ptr.
// We must dereference it to pass to the constructor.
// This is safe because the constructor makes its own copy/move.
auto new_trait_path_ptr = trait_path.reconstruct ();
TypePath *concrete_ptr
= static_cast<TypePath *> (new_trait_path_ptr.get ());

return QualifiedPathType (std::move (new_type), locus, *concrete_ptr);
}

// Returns whether the qualified path type has a rebind as clause.
bool has_as_clause () const { return !trait_path.is_error (); }

Expand Down Expand Up @@ -1433,6 +1539,20 @@ class QualifiedPathInExpression : public Path, public ExprWithoutBlock
return Expr::Kind::QualifiedPathInExpression;
}

std::unique_ptr<QualifiedPathInExpression> reconstruct () const
{
std::vector<PathExprSegment> new_segments;
new_segments.reserve (segments.size ());
for (const auto &seg : segments)
new_segments.push_back (seg.reconstruct ());

auto *new_path = new QualifiedPathInExpression (path_type.reconstruct (),
std::move (new_segments),
outer_attrs, locus);

return std::unique_ptr<QualifiedPathInExpression> (new_path);
}

protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Expand Down Expand Up @@ -1474,7 +1594,7 @@ class QualifiedPathInType : public TypeNoBounds
}
QualifiedPathInType *reconstruct_impl () const override
{
return new QualifiedPathInType (path_type,
return new QualifiedPathInType (path_type.reconstruct (),
associated_segment->reconstruct (),
reconstruct_vec (segments), locus);
}
Expand Down
10 changes: 4 additions & 6 deletions gcc/rust/expand/rust-derive-cmp-common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,8 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw)
});
}

// TODO: Replace with `reconstruct()` instead of building these twice
auto self_variant_path = builder.variant_path (enum_path, variant_path);
auto other_variant_path = builder.variant_path (enum_path, variant_path);
auto other_variant_path = self_variant_path.reconstruct ();

auto self_pattern_items = std::unique_ptr<TupleStructItems> (
new TupleStructItemsNoRest (std::move (self_patterns)));
Expand All @@ -111,7 +110,7 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw)
false, false, builder.loc));
auto other_pattern = std::unique_ptr<Pattern> (new ReferencePattern (
std::unique_ptr<Pattern> (new TupleStructPattern (
other_variant_path, std::move (other_pattern_items))),
*other_variant_path, std::move (other_pattern_items))),
false, false, builder.loc));

auto tuple_items = std::make_unique<TuplePatternItemsNoRest> (
Expand Down Expand Up @@ -159,9 +158,8 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw)
});
}

// TODO: Replace with `reconstruct()` instead of building these twice
auto self_variant_path = builder.variant_path (enum_path, variant_path);
auto other_variant_path = builder.variant_path (enum_path, variant_path);
auto other_variant_path = self_variant_path.reconstruct ();

auto self_elts = StructPatternElements (std::move (self_fields));
auto other_elts = StructPatternElements (std::move (other_fields));
Expand All @@ -172,7 +170,7 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw)
false, false, builder.loc));
auto other_pattern = std::unique_ptr<Pattern> (
new ReferencePattern (std::unique_ptr<Pattern> (
new StructPattern (other_variant_path, builder.loc,
new StructPattern (*other_variant_path, builder.loc,
std::move (other_elts))),
false, false, builder.loc));

Expand Down