Skip to content

Commit 9011184

Browse files
Merge #1071
1071: Allow transcribing of zero nodes in certain cases r=CohenArthur a=CohenArthur When expanding AST fragments containing multiple nodes, we must be aware that some cases allow expanding zero or more nodes. Any macro transcription that gets parsed as many nodes (ie any transcriber function that calls `parse_many`) needs to be able to parse zero of those nodes and still get expanded properly (basically, removed). Previously, this would cause a failure to lower the macro invocation which would remain as a child instead of getting stripped/erased. Co-authored-by: Arthur Cohen <[email protected]>
2 parents f9c1a14 + 7353281 commit 9011184

File tree

6 files changed

+37
-25
lines changed

6 files changed

+37
-25
lines changed

gcc/rust/ast/rust-ast.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,13 +1871,12 @@ class ASTFragment
18711871
return *this;
18721872
}
18731873

1874-
static ASTFragment create_empty () { return ASTFragment ({}); }
18751874
static ASTFragment create_error () { return ASTFragment ({}, true); }
18761875

18771876
std::vector<SingleASTNode> &get_nodes () { return nodes; }
18781877
bool is_error () const { return fragment_is_error; }
18791878

1880-
bool should_expand () const { return !is_error () && !nodes.empty (); }
1879+
bool should_expand () const { return !is_error (); }
18811880

18821881
std::unique_ptr<Expr> take_expression_fragment ()
18831882
{

gcc/rust/ast/rust-macro.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class MacroRulesDefinition : public MacroItem
469469
static ASTFragment dummy_builtin (Location, MacroInvocData &)
470470
{
471471
gcc_unreachable ();
472-
return ASTFragment::create_empty ();
472+
return ASTFragment::create_error ();
473473
}
474474

475475
/* NOTE: in rustc, macro definitions are considered (and parsed as) a type

gcc/rust/expand/rust-macro-builtins.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ MacroBuiltin::assert (Location invoc_locus, AST::MacroInvocData &invoc)
141141
{
142142
rust_debug ("assert!() called");
143143

144-
return AST::ASTFragment::create_empty ();
144+
return AST::ASTFragment::create_error ();
145145
}
146146

147147
AST::ASTFragment

gcc/rust/expand/rust-macro-expand.cc

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
195195
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
196196
rust_assert (ok);
197197

198-
auto fragment = AST::ASTFragment::create_empty ();
198+
auto fragment = AST::ASTFragment::create_error ();
199199

200200
if (rules_def->is_builtin ())
201201
fragment
@@ -236,7 +236,7 @@ MacroExpander::expand_invoc_semi (AST::MacroInvocation &invoc)
236236
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
237237
rust_assert (ok);
238238

239-
auto fragment = AST::ASTFragment::create_empty ();
239+
auto fragment = AST::ASTFragment::create_error ();
240240

241241
if (rules_def->is_builtin ())
242242
fragment
@@ -781,7 +781,7 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
781781
/**
782782
* Helper function to refactor calling a parsing function 0 or more times
783783
*/
784-
static std::vector<AST::SingleASTNode>
784+
static AST::ASTFragment
785785
parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
786786
std::function<AST::SingleASTNode ()> parse_fn)
787787
{
@@ -795,7 +795,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
795795
nodes.emplace_back (std::move (node));
796796
}
797797

798-
return nodes;
798+
return AST::ASTFragment (std::move (nodes));
799799
}
800800

801801
/**
@@ -804,7 +804,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
804804
* @param parser Parser to extract items from
805805
* @param delimiter Id of the token on which parsing should stop
806806
*/
807-
static std::vector<AST::SingleASTNode>
807+
static AST::ASTFragment
808808
transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
809809
{
810810
return parse_many (parser, delimiter, [&parser] () {
@@ -819,7 +819,7 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
819819
* @param parser Parser to extract items from
820820
* @param delimiter Id of the token on which parsing should stop
821821
*/
822-
static std::vector<AST::SingleASTNode>
822+
static AST::ASTFragment
823823
transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
824824
{
825825
return parse_many (parser, delimiter, [&parser] () {
@@ -834,7 +834,7 @@ transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
834834
* @param parser Parser to extract items from
835835
* @param delimiter Id of the token on which parsing should stop
836836
*/
837-
static std::vector<AST::SingleASTNode>
837+
static AST::ASTFragment
838838
transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
839839
TokenId &delimiter)
840840
{
@@ -850,7 +850,7 @@ transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
850850
* @param parser Parser to extract items from
851851
* @param delimiter Id of the token on which parsing should stop
852852
*/
853-
static std::vector<AST::SingleASTNode>
853+
static AST::ASTFragment
854854
transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
855855
{
856856
return parse_many (parser, delimiter, [&parser] () {
@@ -865,7 +865,7 @@ transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
865865
* @param parser Parser to extract items from
866866
* @param delimiter Id of the token on which parsing should stop
867867
*/
868-
static std::vector<AST::SingleASTNode>
868+
static AST::ASTFragment
869869
transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
870870
TokenId &delimiter)
871871
{
@@ -881,7 +881,7 @@ transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
881881
* @param parser Parser to extract statements from
882882
* @param delimiter Id of the token on which parsing should stop
883883
*/
884-
static std::vector<AST::SingleASTNode>
884+
static AST::ASTFragment
885885
transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
886886
{
887887
auto restrictions = ParseRestrictions ();
@@ -901,28 +901,28 @@ transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
901901
*
902902
* @param parser Parser to extract statements from
903903
*/
904-
static std::vector<AST::SingleASTNode>
904+
static AST::ASTFragment
905905
transcribe_expression (Parser<MacroInvocLexer> &parser)
906906
{
907907
auto expr = parser.parse_expr ();
908908

909-
return {AST::SingleASTNode (std::move (expr))};
909+
return AST::ASTFragment ({std::move (expr)});
910910
}
911911

912912
/**
913913
* Transcribe one type from a macro invocation
914914
*
915915
* @param parser Parser to extract statements from
916916
*/
917-
static std::vector<AST::SingleASTNode>
917+
static AST::ASTFragment
918918
transcribe_type (Parser<MacroInvocLexer> &parser)
919919
{
920-
auto expr = parser.parse_type ();
920+
auto type = parser.parse_type ();
921921

922-
return {AST::SingleASTNode (std::move (expr))};
922+
return AST::ASTFragment ({std::move (type)});
923923
}
924924

925-
static std::vector<AST::SingleASTNode>
925+
static AST::ASTFragment
926926
transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
927927
AST::DelimType delimiter, TokenId last_token_id)
928928
{
@@ -932,7 +932,7 @@ transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
932932
return transcribe_expression (parser);
933933
} // namespace Rust
934934

935-
static std::vector<AST::SingleASTNode>
935+
static AST::ASTFragment
936936
transcribe_context (MacroExpander::ContextType ctx,
937937
Parser<MacroInvocLexer> &parser, bool semicolon,
938938
AST::DelimType delimiter, TokenId last_token_id)
@@ -1049,7 +1049,7 @@ MacroExpander::transcribe_rule (
10491049
// as a statement (either via ExpressionStatement or
10501050
// MacroInvocationWithSemi)
10511051

1052-
auto nodes
1052+
auto fragment
10531053
= transcribe_context (ctx, parser, semicolon,
10541054
invoc_token_tree.get_delim_type (), last_token_id);
10551055

@@ -1072,6 +1072,6 @@ MacroExpander::transcribe_rule (
10721072
"tokens here and after are unparsed");
10731073
}
10741074

1075-
return AST::ASTFragment (std::move (nodes));
1075+
return fragment;
10761076
}
10771077
} // namespace Rust

gcc/rust/expand/rust-macro-expand.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ struct MacroExpander
200200
MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session)
201201
: cfg (cfg), crate (crate), session (session),
202202
sub_stack (SubstitutionScope ()),
203-
expanded_fragment (AST::ASTFragment::create_empty ()),
203+
expanded_fragment (AST::ASTFragment::create_error ()),
204204
resolver (Resolver::Resolver::get ()),
205205
mappings (Analysis::Mappings::get ())
206206
{}
@@ -295,7 +295,7 @@ struct MacroExpander
295295
AST::ASTFragment take_expanded_fragment (AST::ASTVisitor &vis)
296296
{
297297
AST::ASTFragment old_fragment = std::move (expanded_fragment);
298-
expanded_fragment = AST::ASTFragment::create_empty ();
298+
expanded_fragment = AST::ASTFragment::create_error ();
299299

300300
for (auto &node : old_fragment.get_nodes ())
301301
{

gcc/testsuite/rust/compile/macro41.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
macro_rules! empty {
2+
($($t:tt)*) => {};
3+
}
4+
5+
empty! {nothing}
6+
empty! {struct OuterItem;}
7+
empty! {}
8+
9+
fn main() {
10+
empty! {as statement};
11+
empty! {any child item};
12+
empty! {};
13+
}

0 commit comments

Comments
 (0)