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 <arthur.cohen@embecosm.com>
This commit is contained in:
bors[bot] 2022-03-31 09:56:35 +00:00 committed by GitHub
commit 9011184f38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 25 deletions

View File

@ -1871,13 +1871,12 @@ public:
return *this;
}
static ASTFragment create_empty () { return ASTFragment ({}); }
static ASTFragment create_error () { return ASTFragment ({}, true); }
std::vector<SingleASTNode> &get_nodes () { return nodes; }
bool is_error () const { return fragment_is_error; }
bool should_expand () const { return !is_error () && !nodes.empty (); }
bool should_expand () const { return !is_error (); }
std::unique_ptr<Expr> take_expression_fragment ()
{

View File

@ -469,7 +469,7 @@ class MacroRulesDefinition : public MacroItem
static ASTFragment dummy_builtin (Location, MacroInvocData &)
{
gcc_unreachable ();
return ASTFragment::create_empty ();
return ASTFragment::create_error ();
}
/* NOTE: in rustc, macro definitions are considered (and parsed as) a type

View File

@ -141,7 +141,7 @@ MacroBuiltin::assert (Location invoc_locus, AST::MacroInvocData &invoc)
{
rust_debug ("assert!() called");
return AST::ASTFragment::create_empty ();
return AST::ASTFragment::create_error ();
}
AST::ASTFragment

View File

@ -195,7 +195,7 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
auto fragment = AST::ASTFragment::create_empty ();
auto fragment = AST::ASTFragment::create_error ();
if (rules_def->is_builtin ())
fragment
@ -236,7 +236,7 @@ MacroExpander::expand_invoc_semi (AST::MacroInvocation &invoc)
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
auto fragment = AST::ASTFragment::create_empty ();
auto fragment = AST::ASTFragment::create_error ();
if (rules_def->is_builtin ())
fragment
@ -781,7 +781,7 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
/**
* Helper function to refactor calling a parsing function 0 or more times
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
std::function<AST::SingleASTNode ()> parse_fn)
{
@ -795,7 +795,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
nodes.emplace_back (std::move (node));
}
return nodes;
return AST::ASTFragment (std::move (nodes));
}
/**
@ -804,7 +804,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
@ -819,7 +819,7 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
@ -834,7 +834,7 @@ transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
TokenId &delimiter)
{
@ -850,7 +850,7 @@ transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
@ -865,7 +865,7 @@ transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
TokenId &delimiter)
{
@ -881,7 +881,7 @@ transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
* @param parser Parser to extract statements from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
auto restrictions = ParseRestrictions ();
@ -901,12 +901,12 @@ transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
*
* @param parser Parser to extract statements from
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_expression (Parser<MacroInvocLexer> &parser)
{
auto expr = parser.parse_expr ();
return {AST::SingleASTNode (std::move (expr))};
return AST::ASTFragment ({std::move (expr)});
}
/**
@ -914,15 +914,15 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
*
* @param parser Parser to extract statements from
*/
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_type (Parser<MacroInvocLexer> &parser)
{
auto expr = parser.parse_type ();
auto type = parser.parse_type ();
return {AST::SingleASTNode (std::move (expr))};
return AST::ASTFragment ({std::move (type)});
}
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
AST::DelimType delimiter, TokenId last_token_id)
{
@ -932,7 +932,7 @@ transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
return transcribe_expression (parser);
} // namespace Rust
static std::vector<AST::SingleASTNode>
static AST::ASTFragment
transcribe_context (MacroExpander::ContextType ctx,
Parser<MacroInvocLexer> &parser, bool semicolon,
AST::DelimType delimiter, TokenId last_token_id)
@ -1049,7 +1049,7 @@ MacroExpander::transcribe_rule (
// as a statement (either via ExpressionStatement or
// MacroInvocationWithSemi)
auto nodes
auto fragment
= transcribe_context (ctx, parser, semicolon,
invoc_token_tree.get_delim_type (), last_token_id);
@ -1072,6 +1072,6 @@ MacroExpander::transcribe_rule (
"tokens here and after are unparsed");
}
return AST::ASTFragment (std::move (nodes));
return fragment;
}
} // namespace Rust

View File

@ -200,7 +200,7 @@ struct MacroExpander
MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session)
: cfg (cfg), crate (crate), session (session),
sub_stack (SubstitutionScope ()),
expanded_fragment (AST::ASTFragment::create_empty ()),
expanded_fragment (AST::ASTFragment::create_error ()),
resolver (Resolver::Resolver::get ()),
mappings (Analysis::Mappings::get ())
{}
@ -295,7 +295,7 @@ struct MacroExpander
AST::ASTFragment take_expanded_fragment (AST::ASTVisitor &vis)
{
AST::ASTFragment old_fragment = std::move (expanded_fragment);
expanded_fragment = AST::ASTFragment::create_empty ();
expanded_fragment = AST::ASTFragment::create_error ();
for (auto &node : old_fragment.get_nodes ())
{

View File

@ -0,0 +1,13 @@
macro_rules! empty {
($($t:tt)*) => {};
}
empty! {nothing}
empty! {struct OuterItem;}
empty! {}
fn main() {
empty! {as statement};
empty! {any child item};
empty! {};
}