Skip to content

Commit c85f3df

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 c85f3df

2 files changed

Lines changed: 123 additions & 7 deletions

File tree

gcc/rust/ast/rust-path.h

Lines changed: 119 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,13 @@ 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 (), locus);
1074+
}
10071075
};
10081076

10091077
// A function as represented in a type path
@@ -1112,6 +1180,21 @@ struct TypePathFunction
11121180
return return_type;
11131181
}
11141182

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

@@ -1159,6 +1242,13 @@ class TypePathSegmentFunction : public TypePathSegment
11591242
{
11601243
return new TypePathSegmentFunction (*this);
11611244
}
1245+
1246+
TypePathSegmentFunction *reconstruct_impl () const override
1247+
{
1248+
return new TypePathSegmentFunction (get_ident_segment (),
1249+
has_separating_scope_resolution,
1250+
function_path.reconstruct (), locus);
1251+
}
11621252
};
11631253

11641254
class TypePath : public TypeNoBounds
@@ -1327,6 +1417,20 @@ struct QualifiedPathType
13271417
QualifiedPathType (QualifiedPathType &&other) = default;
13281418
QualifiedPathType &operator= (QualifiedPathType &&other) = default;
13291419

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

@@ -1433,6 +1537,20 @@ class QualifiedPathInExpression : public Path, public ExprWithoutBlock
14331537
return Expr::Kind::QualifiedPathInExpression;
14341538
}
14351539

1540+
std::unique_ptr<QualifiedPathInExpression> reconstruct () const
1541+
{
1542+
std::vector<PathExprSegment> new_segments;
1543+
new_segments.reserve (segments.size ());
1544+
for (const auto &seg : segments)
1545+
new_segments.push_back (seg.reconstruct ());
1546+
1547+
auto *new_path = new QualifiedPathInExpression (path_type.reconstruct (),
1548+
std::move (new_segments),
1549+
outer_attrs, locus);
1550+
1551+
return std::unique_ptr<QualifiedPathInExpression> (new_path);
1552+
}
1553+
14361554
protected:
14371555
/* Use covariance to implement clone function as returning this object
14381556
* rather than base */
@@ -1474,7 +1592,7 @@ class QualifiedPathInType : public TypeNoBounds
14741592
}
14751593
QualifiedPathInType *reconstruct_impl () const override
14761594
{
1477-
return new QualifiedPathInType (path_type,
1595+
return new QualifiedPathInType (path_type.reconstruct (),
14781596
associated_segment->reconstruct (),
14791597
reconstruct_vec (segments), locus);
14801598
}

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)