Skip to content

Commit cf88af9

Browse files
committed
expand: Add handling for macro expansion in pattern context
gcc/rust/ChangeLog: * ast/rust-ast-fragment.cc (Fragment::is_pattern_fragment): New function. (Fragment::take_pattern_fragment): Likewise. (Fragment::assert_single_fragment): Likewise. * ast/rust-ast-fragment.h: Declare them. * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Add new constructor for pattern single AST nodes. (SingleASTNode::operator=): Handle patterns. (SingleASTNode::accept_vis): Likewise. (SingleASTNode::is_error): Likewise. (SingleASTNode::as_string): Likewise. * ast/rust-ast.h: Add get_pattern_ptr() functions. * ast/rust-expr.h: Likewise. * ast/rust-item.h: Likewise. * ast/rust-pattern.h: Likewise. * ast/rust-stmt.h: Likewise. * expand/rust-expand-visitor.cc (derive_item): Use new API enum values. (expand_item_attribute): Likewise. (expand_stmt_attribute): Likewise. (ExpandVisitor::maybe_expand_pattern): New function. (ExpandVisitor::expand_closure_params): Handle patterns. (ExpandVisitor::visit): Add new visitors for patterns and missed exprs. * expand/rust-expand-visitor.h: Declare them. * expand/rust-macro-expand.cc (transcribe_pattern): New function. (transcribe_context): Call it. * expand/rust-macro-expand.h (struct MacroExpander): New Context type. gcc/testsuite/ChangeLog: * rust/compile/issue-3726.rs: New test. * rust/compile/issue-3898.rs: New test.
1 parent 25adf16 commit cf88af9

14 files changed

+340
-17
lines changed

gcc/rust/ast/rust-ast-fragment.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ Fragment::is_type_fragment () const
116116
return is_single_fragment_of_kind (SingleASTNode::Kind::Type);
117117
}
118118

119+
bool
120+
Fragment::is_pattern_fragment () const
121+
{
122+
return is_single_fragment_of_kind (SingleASTNode::Kind::Pattern);
123+
}
124+
119125
std::unique_ptr<Expr>
120126
Fragment::take_expression_fragment ()
121127
{
@@ -130,6 +136,13 @@ Fragment::take_type_fragment ()
130136
return nodes[0].take_type ();
131137
}
132138

139+
std::unique_ptr<Pattern>
140+
Fragment::take_pattern_fragment ()
141+
{
142+
assert_single_fragment (SingleASTNode::Kind::Pattern);
143+
return nodes[0].take_pattern ();
144+
}
145+
133146
void
134147
Fragment::accept_vis (ASTVisitor &vis)
135148
{
@@ -159,6 +172,7 @@ Fragment::assert_single_fragment (SingleASTNode::Kind expected) const
159172
{SingleASTNode::Kind::Expr, "expr"},
160173
{SingleASTNode::Kind::Stmt, "stmt"},
161174
{SingleASTNode::Kind::Extern, "extern"},
175+
{SingleASTNode::Kind::Pattern, "pattern"},
162176
};
163177

164178
auto actual = nodes[0].get_kind ();

gcc/rust/ast/rust-ast-fragment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ class Fragment
8686

8787
bool is_expression_fragment () const;
8888
bool is_type_fragment () const;
89+
bool is_pattern_fragment () const;
8990

9091
std::unique_ptr<Expr> take_expression_fragment ();
9192
std::unique_ptr<Type> take_type_fragment ();
93+
std::unique_ptr<Pattern> take_pattern_fragment ();
9294

9395
void accept_vis (ASTVisitor &vis);
9496

gcc/rust/ast/rust-ast.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other)
7171
case Kind::Type:
7272
type = other.type->clone_type ();
7373
break;
74+
75+
case Kind::Pattern:
76+
pattern = other.pattern->clone_pattern ();
77+
break;
7478
}
7579
}
7680

@@ -103,6 +107,10 @@ SingleASTNode::operator= (SingleASTNode const &other)
103107
case Kind::Type:
104108
type = other.type->clone_type ();
105109
break;
110+
111+
case Kind::Pattern:
112+
pattern = other.pattern->clone_pattern ();
113+
break;
106114
}
107115
return *this;
108116
}
@@ -135,6 +143,10 @@ SingleASTNode::accept_vis (ASTVisitor &vis)
135143
case Kind::Type:
136144
type->accept_vis (vis);
137145
break;
146+
147+
case Kind::Pattern:
148+
pattern->accept_vis (vis);
149+
break;
138150
}
139151
}
140152

@@ -155,6 +167,8 @@ SingleASTNode::is_error ()
155167
return assoc_item == nullptr;
156168
case Kind::Type:
157169
return type == nullptr;
170+
case Kind::Pattern:
171+
return pattern == nullptr;
158172
}
159173

160174
rust_unreachable ();
@@ -178,6 +192,8 @@ SingleASTNode::as_string () const
178192
return "Associated Item: " + assoc_item->as_string ();
179193
case Kind::Type:
180194
return "Type: " + type->as_string ();
195+
case Kind::Pattern:
196+
return "Pattern: " + pattern->as_string ();
181197
}
182198

183199
rust_unreachable ();

gcc/rust/ast/rust-ast.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,7 @@ class SingleASTNode : public Visitable
19651965
Extern,
19661966
Assoc,
19671967
Type,
1968+
Pattern,
19681969
};
19691970

19701971
private:
@@ -1977,6 +1978,7 @@ class SingleASTNode : public Visitable
19771978
std::unique_ptr<ExternalItem> external_item;
19781979
std::unique_ptr<AssociatedItem> assoc_item;
19791980
std::unique_ptr<Type> type;
1981+
std::unique_ptr<Pattern> pattern;
19801982

19811983
public:
19821984
SingleASTNode (std::unique_ptr<Expr> expr)
@@ -2003,6 +2005,10 @@ class SingleASTNode : public Visitable
20032005
: kind (Kind::Type), type (std::move (type))
20042006
{}
20052007

2008+
SingleASTNode (std::unique_ptr<Pattern> pattern)
2009+
: kind (Kind::Pattern), pattern (std::move (pattern))
2010+
{}
2011+
20062012
SingleASTNode (SingleASTNode const &other);
20072013

20082014
SingleASTNode operator= (SingleASTNode const &other);
@@ -2071,6 +2077,12 @@ class SingleASTNode : public Visitable
20712077
return std::move (type);
20722078
}
20732079

2080+
std::unique_ptr<Pattern> take_pattern ()
2081+
{
2082+
rust_assert (!is_error ());
2083+
return std::move (pattern);
2084+
}
2085+
20742086
void accept_vis (ASTVisitor &vis) override;
20752087

20762088
bool is_error ();

gcc/rust/ast/rust-expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,6 +2480,12 @@ struct ClosureParam
24802480
return *pattern;
24812481
}
24822482

2483+
std::unique_ptr<Pattern> &get_pattern_ptr ()
2484+
{
2485+
rust_assert (pattern != nullptr);
2486+
return pattern;
2487+
}
2488+
24832489
Type &get_type ()
24842490
{
24852491
rust_assert (has_type_given ());

gcc/rust/ast/rust-item.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,12 @@ class VariadicParam : public Param
631631
return *param_name;
632632
}
633633

634+
std::unique_ptr<Pattern> &get_pattern_ptr ()
635+
{
636+
rust_assert (param_name != nullptr);
637+
return param_name;
638+
}
639+
634640
const Pattern &get_pattern () const
635641
{
636642
rust_assert (param_name != nullptr);
@@ -714,6 +720,12 @@ class FunctionParam : public Param
714720
return *param_name;
715721
}
716722

723+
std::unique_ptr<Pattern> &get_pattern_ptr ()
724+
{
725+
rust_assert (param_name != nullptr);
726+
return param_name;
727+
}
728+
717729
bool has_name () const { return param_name != nullptr; }
718730

719731
// TODO: is this better? Or is a "vis_block" better?

gcc/rust/ast/rust-pattern.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,12 @@ class GroupedPattern : public Pattern
15091509
return *pattern_in_parens;
15101510
}
15111511

1512+
std::unique_ptr<Pattern> &get_pattern_in_parens_ptr ()
1513+
{
1514+
rust_assert (pattern_in_parens != nullptr);
1515+
return pattern_in_parens;
1516+
}
1517+
15121518
NodeId get_node_id () const override { return node_id; }
15131519

15141520
Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; }

gcc/rust/ast/rust-stmt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ class LetStmt : public Stmt
201201
return *variables_pattern;
202202
}
203203

204+
std::unique_ptr<Pattern> &get_pattern_ptr ()
205+
{
206+
rust_assert (variables_pattern != nullptr);
207+
return variables_pattern;
208+
}
209+
204210
Type &get_type ()
205211
{
206212
rust_assert (has_type ());

gcc/rust/expand/rust-expand-visitor.cc

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "rust-expand-visitor.h"
2020
#include "rust-ast-fragment.h"
21+
#include "rust-item.h"
2122
#include "rust-proc-macro.h"
2223
#include "rust-attributes.h"
2324
#include "rust-ast.h"
@@ -62,7 +63,7 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive,
6263
{
6364
switch (node.get_kind ())
6465
{
65-
case AST::SingleASTNode::ITEM:
66+
case AST::SingleASTNode::Kind::Item:
6667
result.push_back (node.take_item ());
6768
break;
6869
default:
@@ -85,7 +86,7 @@ expand_item_attribute (AST::Item &item, AST::SimplePath &name,
8586
{
8687
switch (node.get_kind ())
8788
{
88-
case AST::SingleASTNode::ITEM:
89+
case AST::SingleASTNode::Kind::Item:
8990
result.push_back (node.take_item ());
9091
break;
9192
default:
@@ -114,7 +115,7 @@ expand_stmt_attribute (T &statement, AST::SimplePath &attribute,
114115
{
115116
switch (node.get_kind ())
116117
{
117-
case AST::SingleASTNode::STMT:
118+
case AST::SingleASTNode::Kind::Stmt:
118119
result.push_back (node.take_stmt ());
119120
break;
120121
default:
@@ -352,6 +353,19 @@ ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
352353
expander.pop_context ();
353354
}
354355

356+
void
357+
ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
358+
{
359+
expander.push_context (MacroExpander::ContextType::PATTERN);
360+
361+
pattern->accept_vis (*this);
362+
auto final_fragment = expander.take_expanded_fragment ();
363+
if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
364+
pattern = final_fragment.take_pattern_fragment ();
365+
366+
expander.pop_context ();
367+
}
368+
355369
// FIXME: Can this be refactored into a `scoped` method? Which takes a
356370
// ContextType as parameter and a lambda? And maybe just an std::vector<T>&?
357371
void
@@ -424,6 +438,8 @@ ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> &params)
424438
{
425439
for (auto &param : params)
426440
{
441+
maybe_expand_pattern (param.get_pattern_ptr ());
442+
427443
if (param.has_type_given ())
428444
maybe_expand_type (param.get_type_ptr ());
429445
}
@@ -686,7 +702,7 @@ ExpandVisitor::visit (AST::MatchExpr &expr)
686702
auto &arm = match_case.get_arm ();
687703

688704
for (auto &pattern : arm.get_patterns ())
689-
visit (pattern);
705+
maybe_expand_pattern (pattern);
690706

691707
if (arm.has_match_arm_guard ())
692708
maybe_expand_expr (arm.get_guard_expr_ptr ());
@@ -695,6 +711,13 @@ ExpandVisitor::visit (AST::MatchExpr &expr)
695711
}
696712
}
697713

714+
void
715+
ExpandVisitor::visit (AST::TupleExpr &expr)
716+
{
717+
for (auto &sub : expr.get_tuple_elems ())
718+
maybe_expand_expr (sub);
719+
}
720+
698721
void
699722
ExpandVisitor::visit (AST::TypeParam &param)
700723
{
@@ -970,13 +993,70 @@ ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
970993
void
971994
ExpandVisitor::visit (AST::GroupedPattern &pattern)
972995
{
973-
visit (pattern.get_pattern_in_parens ());
996+
maybe_expand_pattern (pattern.get_pattern_in_parens_ptr ());
997+
}
998+
999+
void
1000+
ExpandVisitor::visit (AST::SlicePatternItemsNoRest &items)
1001+
{
1002+
for (auto &sub : items.get_patterns ())
1003+
maybe_expand_pattern (sub);
1004+
}
1005+
1006+
void
1007+
ExpandVisitor::visit (AST::SlicePatternItemsHasRest &items)
1008+
{
1009+
for (auto &sub : items.get_lower_patterns ())
1010+
maybe_expand_pattern (sub);
1011+
for (auto &sub : items.get_upper_patterns ())
1012+
maybe_expand_pattern (sub);
1013+
}
1014+
1015+
void
1016+
ExpandVisitor::visit (AST::AltPattern &pattern)
1017+
{
1018+
for (auto &alt : pattern.get_alts ())
1019+
maybe_expand_pattern (alt);
1020+
}
1021+
1022+
void
1023+
ExpandVisitor::visit (AST::TupleStructItemsNoRange &tuple_items)
1024+
{
1025+
for (auto &sub : tuple_items.get_patterns ())
1026+
maybe_expand_pattern (sub);
1027+
}
1028+
1029+
void
1030+
ExpandVisitor::visit (AST::TupleStructItemsRange &tuple_items)
1031+
{
1032+
for (auto &sub : tuple_items.get_lower_patterns ())
1033+
maybe_expand_pattern (sub);
1034+
1035+
for (auto &sub : tuple_items.get_upper_patterns ())
1036+
maybe_expand_pattern (sub);
1037+
}
1038+
1039+
void
1040+
ExpandVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items)
1041+
{
1042+
for (auto &sub : tuple_items.get_patterns ())
1043+
maybe_expand_pattern (sub);
1044+
}
1045+
1046+
void
1047+
ExpandVisitor::visit (AST::TuplePatternItemsRanged &tuple_items)
1048+
{
1049+
for (auto &sub : tuple_items.get_lower_patterns ())
1050+
maybe_expand_pattern (sub);
1051+
1052+
for (auto &sub : tuple_items.get_upper_patterns ())
1053+
maybe_expand_pattern (sub);
9741054
}
9751055

9761056
void
9771057
ExpandVisitor::visit (AST::LetStmt &stmt)
9781058
{
979-
visit (stmt.get_pattern ());
1059+
maybe_expand_pattern (stmt.get_pattern_ptr ());
9801060

9811061
if (stmt.has_type ())
9821062
maybe_expand_type (stmt.get_type_ptr ());
@@ -1006,9 +1086,17 @@ ExpandVisitor::visit (AST::BareFunctionType &type)
10061086
void
10071087
ExpandVisitor::visit (AST::FunctionParam &param)
10081088
{
1089+
maybe_expand_pattern (param.get_pattern_ptr ());
10091090
maybe_expand_type (param.get_type_ptr ());
10101091
}
10111092

1093+
void
1094+
ExpandVisitor::visit (AST::VariadicParam &param)
1095+
{
1096+
if (param.has_pattern ())
1097+
maybe_expand_pattern (param.get_pattern_ptr ());
1098+
}
1099+
10121100
void
10131101
ExpandVisitor::visit (AST::SelfParam &param)
10141102
{

0 commit comments

Comments
 (0)