Skip to content

Commit 84223c7

Browse files
committed
ast: Add reconstruct() logic for PathInExpression
This patch implements the `reconstruct` pattern for `PathInExpression` and its constituents (segments, generic args). Previously, derive expansion relied on building paths twice or potentially using local helpers. This change moves that logic into the AST, allowing paths to be deeply reconstructed with fresh NodeIDs. gcc/rust/ChangeLog: * ast/rust-path.h (GenericArgsBinding::reconstruct): New method. (GenericArg::reconstruct): New method. (GenericArgs::reconstruct): New method. (PathExprSegment::reconstruct): New method. (PathInExpression::reconstruct): New method. * expand/rust-derive-cmp-common.cc (reconstruct_path): Remove. (EnumMatchBuilder::tuple): Use path.reconstruct(). (EnumMatchBuilder::strukt): Use path.reconstruct(). Signed-off-by: Jayant Chauhan <0001jayant@gmail.com>
1 parent 23de527 commit 84223c7

2 files changed

Lines changed: 65 additions & 4 deletions

File tree

gcc/rust/ast/rust-path.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ struct GenericArgsBinding
8484
// and also identifier is empty, but cheaper computation
8585
}
8686

87+
GenericArgsBinding reconstruct () const
88+
{
89+
std::unique_ptr<Type> new_type = nullptr;
90+
if (type)
91+
new_type = type->reconstruct ();
92+
93+
return GenericArgsBinding (identifier, std::move (new_type), locus);
94+
}
95+
8796
// Creates an error state generic args binding.
8897
static GenericArgsBinding create_error ()
8998
{
@@ -190,6 +199,22 @@ class GenericArg
190199
return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
191200
}
192201

202+
GenericArg reconstruct () const
203+
{
204+
switch (kind)
205+
{
206+
case Kind::Type:
207+
return create_type (type->reconstruct ());
208+
case Kind::Const:
209+
// FIXME: Use reconstruct_expr when available
210+
return create_const (expression->clone_expr ());
211+
case Kind::Either:
212+
default:
213+
// For ambiguous or error states, copy constructs are sufficient
214+
return GenericArg (*this);
215+
}
216+
}
217+
193218
GenericArg (const GenericArg &other)
194219
: path (other.path), kind (other.kind), locus (other.locus)
195220
{
@@ -460,6 +485,23 @@ struct GenericArgs
460485

461486
~GenericArgs () = default;
462487

488+
GenericArgs reconstruct () const
489+
{
490+
std::vector<GenericArg> new_args;
491+
new_args.reserve (generic_args.size ());
492+
for (const auto &arg : generic_args)
493+
new_args.push_back (arg.reconstruct ());
494+
495+
std::vector<GenericArgsBinding> new_bindings;
496+
new_bindings.reserve (binding_args.size ());
497+
for (const auto &binding : binding_args)
498+
new_bindings.push_back (binding.reconstruct ());
499+
500+
// Lifetimes are values, so they can be copied directly
501+
return GenericArgs (lifetime_args, std::move (new_args),
502+
std::move (new_bindings), locus);
503+
}
504+
463505
// overloaded assignment operator to vector clone
464506
GenericArgs &operator= (GenericArgs const &other)
465507
{
@@ -563,6 +605,11 @@ class PathExprSegment
563605

564606
NodeId get_node_id () const { return node_id; }
565607

608+
PathExprSegment reconstruct () const
609+
{
610+
return PathExprSegment (segment_name, locus, generic_args.reconstruct ());
611+
}
612+
566613
bool is_super_path_seg () const
567614
{
568615
return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
@@ -705,6 +752,20 @@ class PathInExpression : public Path, public ExprWithoutBlock
705752
return convert_to_simple_path (has_opening_scope_resolution);
706753
}
707754

755+
std::unique_ptr<PathInExpression> reconstruct () const
756+
{
757+
std::vector<PathExprSegment> new_segments;
758+
new_segments.reserve (segments.size ());
759+
for (const auto &seg : segments)
760+
new_segments.push_back (seg.reconstruct ());
761+
762+
auto *new_path
763+
= new PathInExpression (std::move (new_segments), outer_attrs, locus,
764+
has_opening_scope_resolution);
765+
766+
return std::unique_ptr<PathInExpression> (new_path);
767+
}
768+
708769
location_t get_locus () const override final { return locus; }
709770

710771
void accept_vis (ASTVisitor &vis) override;

gcc/rust/expand/rust-derive-cmp-common.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,10 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw)
9696
});
9797
}
9898

99-
// TODO: Replace with `reconstruct()` instead of building these twice
10099
auto self_variant_path = builder.variant_path (enum_path, variant_path);
101-
auto other_variant_path = builder.variant_path (enum_path, variant_path);
100+
// Dereference the unique_ptr if you need the object directly,
101+
// or move it if you need ownership.
102+
auto other_variant_path = *self_variant_path.reconstruct ();
102103

103104
auto self_pattern_items = std::unique_ptr<TupleStructItems> (
104105
new TupleStructItemsNoRest (std::move (self_patterns)));
@@ -159,9 +160,8 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw)
159160
});
160161
}
161162

162-
// TODO: Replace with `reconstruct()` instead of building these twice
163163
auto self_variant_path = builder.variant_path (enum_path, variant_path);
164-
auto other_variant_path = builder.variant_path (enum_path, variant_path);
164+
auto other_variant_path = *self_variant_path.reconstruct ();
165165

166166
auto self_elts = StructPatternElements (std::move (self_fields));
167167
auto other_elts = StructPatternElements (std::move (other_fields));

0 commit comments

Comments
 (0)