Skip to content

Commit 35e4800

Browse files
committed
ast: Add reconstruct() logic for PathInExpression
This patch implements the `reconstruct` pattern for `PathInExpression` and its constituents (segments, generic args), following the architectural pattern established in PR Rust-GCC#3799 for Types. 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 35e4800

2 files changed

Lines changed: 68 additions & 4 deletions

File tree

gcc/rust/ast/rust-path.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ struct GenericArgsBinding
8383
return type == nullptr;
8484
// and also identifier is empty, but cheaper computation
8585
}
86+
Identifier get_identifier () const { return identifier; }
87+
88+
GenericArgsBinding reconstruct () const
89+
{
90+
std::unique_ptr<Type> new_type = nullptr;
91+
if (type)
92+
new_type = type->reconstruct ();
93+
94+
return GenericArgsBinding (identifier, std::move (new_type), locus);
95+
}
8696

8797
// Creates an error state generic args binding.
8898
static GenericArgsBinding create_error ()
@@ -189,6 +199,24 @@ class GenericArg
189199
{
190200
return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
191201
}
202+
Kind get_kind () const { return kind; }
203+
location_t get_locus () const { return locus; }
204+
205+
GenericArg reconstruct () const
206+
{
207+
switch (kind)
208+
{
209+
case Kind::Type:
210+
return create_type (type->reconstruct ());
211+
case Kind::Const:
212+
// FIXME: Use reconstruct_expr when available
213+
return create_const (expression->clone_expr ());
214+
case Kind::Either:
215+
default:
216+
// For ambiguous or error states, copy constructs are sufficient
217+
return GenericArg (*this);
218+
}
219+
}
192220

193221
GenericArg (const GenericArg &other)
194222
: path (other.path), kind (other.kind), locus (other.locus)
@@ -460,6 +488,23 @@ struct GenericArgs
460488

461489
~GenericArgs () = default;
462490

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

564609
NodeId get_node_id () const { return node_id; }
565610

611+
PathExprSegment reconstruct () const
612+
{
613+
return PathExprSegment (segment_name, locus, generic_args.reconstruct ());
614+
}
615+
566616
bool is_super_path_seg () const
567617
{
568618
return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
@@ -705,6 +755,20 @@ class PathInExpression : public Path, public ExprWithoutBlock
705755
return convert_to_simple_path (has_opening_scope_resolution);
706756
}
707757

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

710774
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)