Skip to content

Commit 7b27b33

Browse files
committed
ast: Implement reconstruct() logic for Path hierarchy
This patch implements the `reconstruct` pattern for the `Path` hierarchy and its constituents (segments, generic args, qualified paths). Previously, derive expansion macros (like `derive(PartialEq)`) had to manually rebuild paths field-by-field to ensure fresh NodeIDs. This change moves that logic into the AST classes themselves, allowing paths to be deeply reconstructed uniformly. This ensures that expanded code has unique NodeIDs, which is critical for correct name resolution. 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. (TypePathSegmentGeneric::reconstruct_impl): New method. (TypePathFunction::reconstruct): New method. (TypePathSegmentFunction::reconstruct_impl): New method. (QualifiedPathType::reconstruct): New method. (QualifiedPathInExpression::reconstruct): New method. (QualifiedPathInType::reconstruct_impl): New method. * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): Use path.reconstruct(). (EnumMatchBuilder::strukt): Use path.reconstruct(). Signed-off-by: Jayant Chauhan <0001jayant@gmail.com>
1 parent 23de527 commit 7b27b33

2 files changed

Lines changed: 125 additions & 7 deletions

File tree

gcc/rust/ast/rust-path.h

Lines changed: 121 additions & 1 deletion
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;
@@ -1004,6 +1065,14 @@ class TypePathSegmentGeneric : public TypePathSegment
10041065
{
10051066
return new TypePathSegmentGeneric (*this);
10061067
}
1068+
1069+
TypePathSegmentGeneric *reconstruct_impl () const override
1070+
{
1071+
return new TypePathSegmentGeneric (get_ident_segment (),
1072+
has_separating_scope_resolution,
1073+
generic_args.reconstruct (),
1074+
get_locus ());
1075+
}
10071076
};
10081077

10091078
// A function as represented in a type path
@@ -1112,6 +1181,21 @@ struct TypePathFunction
11121181
return return_type;
11131182
}
11141183

1184+
TypePathFunction reconstruct () const
1185+
{
1186+
std::vector<std::unique_ptr<Type>> new_inputs;
1187+
new_inputs.reserve (inputs.size ());
1188+
for (const auto &e : inputs)
1189+
new_inputs.push_back (e->reconstruct ());
1190+
1191+
std::unique_ptr<Type> new_ret = nullptr;
1192+
if (return_type)
1193+
new_ret = return_type->reconstruct ();
1194+
1195+
return TypePathFunction (std::move (new_inputs), locus,
1196+
std::move (new_ret));
1197+
}
1198+
11151199
location_t get_locus () const { return locus; }
11161200
};
11171201

@@ -1159,6 +1243,14 @@ class TypePathSegmentFunction : public TypePathSegment
11591243
{
11601244
return new TypePathSegmentFunction (*this);
11611245
}
1246+
1247+
TypePathSegmentFunction *reconstruct_impl () const override
1248+
{
1249+
return new TypePathSegmentFunction (get_ident_segment (),
1250+
has_separating_scope_resolution,
1251+
function_path.reconstruct (),
1252+
get_locus ());
1253+
}
11621254
};
11631255

11641256
class TypePath : public TypeNoBounds
@@ -1327,6 +1419,20 @@ struct QualifiedPathType
13271419
QualifiedPathType (QualifiedPathType &&other) = default;
13281420
QualifiedPathType &operator= (QualifiedPathType &&other) = default;
13291421

1422+
QualifiedPathType reconstruct () const
1423+
{
1424+
auto new_type = type_to_invoke_on->reconstruct ();
1425+
1426+
// trait_path is stored by value, but reconstruct returns a unique_ptr.
1427+
// We must dereference it to pass to the constructor.
1428+
// This is safe because the constructor makes its own copy/move.
1429+
auto new_trait_path_ptr = trait_path.reconstruct ();
1430+
TypePath *concrete_ptr
1431+
= static_cast<TypePath *> (new_trait_path_ptr.get ());
1432+
1433+
return QualifiedPathType (std::move (new_type), locus, *concrete_ptr);
1434+
}
1435+
13301436
// Returns whether the qualified path type has a rebind as clause.
13311437
bool has_as_clause () const { return !trait_path.is_error (); }
13321438

@@ -1433,6 +1539,20 @@ class QualifiedPathInExpression : public Path, public ExprWithoutBlock
14331539
return Expr::Kind::QualifiedPathInExpression;
14341540
}
14351541

1542+
std::unique_ptr<QualifiedPathInExpression> reconstruct () const
1543+
{
1544+
std::vector<PathExprSegment> new_segments;
1545+
new_segments.reserve (segments.size ());
1546+
for (const auto &seg : segments)
1547+
new_segments.push_back (seg.reconstruct ());
1548+
1549+
auto *new_path = new QualifiedPathInExpression (path_type.reconstruct (),
1550+
std::move (new_segments),
1551+
outer_attrs, locus);
1552+
1553+
return std::unique_ptr<QualifiedPathInExpression> (new_path);
1554+
}
1555+
14361556
protected:
14371557
/* Use covariance to implement clone function as returning this object
14381558
* rather than base */
@@ -1474,7 +1594,7 @@ class QualifiedPathInType : public TypeNoBounds
14741594
}
14751595
QualifiedPathInType *reconstruct_impl () const override
14761596
{
1477-
return new QualifiedPathInType (path_type,
1597+
return new QualifiedPathInType (path_type.reconstruct (),
14781598
associated_segment->reconstruct (),
14791599
reconstruct_vec (segments), locus);
14801600
}

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,8 @@ 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+
auto other_variant_path = self_variant_path.reconstruct ();
102101

103102
auto self_pattern_items = std::unique_ptr<TupleStructItems> (
104103
new TupleStructItemsNoRest (std::move (self_patterns)));
@@ -111,7 +110,7 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw)
111110
false, false, builder.loc));
112111
auto other_pattern = std::unique_ptr<Pattern> (new ReferencePattern (
113112
std::unique_ptr<Pattern> (new TupleStructPattern (
114-
other_variant_path, std::move (other_pattern_items))),
113+
*other_variant_path, std::move (other_pattern_items))),
115114
false, false, builder.loc));
116115

117116
auto tuple_items = std::make_unique<TuplePatternItemsNoRest> (
@@ -159,9 +158,8 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw)
159158
});
160159
}
161160

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

166164
auto self_elts = StructPatternElements (std::move (self_fields));
167165
auto other_elts = StructPatternElements (std::move (other_fields));
@@ -172,7 +170,7 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw)
172170
false, false, builder.loc));
173171
auto other_pattern = std::unique_ptr<Pattern> (
174172
new ReferencePattern (std::unique_ptr<Pattern> (
175-
new StructPattern (other_variant_path, builder.loc,
173+
new StructPattern (*other_variant_path, builder.loc,
176174
std::move (other_elts))),
177175
false, false, builder.loc));
178176

0 commit comments

Comments
 (0)