macros: Allow macro calls in trait implementations

Just like inherent implementation blocks, trait implementation blocks
(`impl Trait for Type`) can also contain macro invocations.
This commit is contained in:
Arthur Cohen 2022-03-16 16:57:17 +01:00
parent 935b561e7f
commit a7ef6f98be
6 changed files with 75 additions and 4 deletions

View File

@ -1514,6 +1514,7 @@ public:
EXTERN,
TRAIT,
IMPL,
TRAIT_IMPL,
};
private:
@ -1526,6 +1527,7 @@ private:
std::unique_ptr<ExternalItem> external_item;
std::unique_ptr<TraitItem> trait_item;
std::unique_ptr<InherentImplItem> impl_item;
std::unique_ptr<TraitImplItem> trait_impl_item;
public:
SingleASTNode (std::unique_ptr<Expr> expr)
@ -1552,6 +1554,10 @@ public:
: kind (IMPL), impl_item (std::move (item))
{}
SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item)
: kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item))
{}
SingleASTNode (SingleASTNode const &other)
{
kind = other.kind;
@ -1580,6 +1586,10 @@ public:
case IMPL:
impl_item = other.impl_item->clone_inherent_impl_item ();
break;
case TRAIT_IMPL:
trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
break;
}
}
@ -1611,6 +1621,10 @@ public:
case IMPL:
impl_item = other.impl_item->clone_inherent_impl_item ();
break;
case TRAIT_IMPL:
trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
break;
}
return *this;
}
@ -1679,6 +1693,12 @@ public:
return std::move (impl_item);
}
std::unique_ptr<TraitImplItem> take_trait_impl_item ()
{
rust_assert (!is_error ());
return std::move (trait_impl_item);
}
void accept_vis (ASTVisitor &vis)
{
switch (kind)
@ -1706,6 +1726,10 @@ public:
case IMPL:
impl_item->accept_vis (vis);
break;
case TRAIT_IMPL:
trait_impl_item->accept_vis (vis);
break;
}
}
@ -1725,6 +1749,8 @@ public:
return trait_item == nullptr;
case IMPL:
return impl_item == nullptr;
case TRAIT_IMPL:
return trait_impl_item == nullptr;
}
gcc_unreachable ();
@ -1747,6 +1773,8 @@ public:
return "Trait Item: " + trait_item->as_string ();
case IMPL:
return "Impl Item: " + impl_item->as_string ();
case TRAIT_IMPL:
return "Trait Impl Item: " + impl_item->as_string ();
}
gcc_unreachable ();

View File

@ -2549,8 +2549,12 @@ AttrVisitor::visit (AST::TraitImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
// strip trait impl items if required
expand_pointer_allow_strip (impl.get_impl_items ());
std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)>
extractor
= [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); };
expand_macro_children (MacroExpander::TRAIT_IMPL, impl.get_impl_items (),
extractor);
}
void
AttrVisitor::visit (AST::ExternalStaticItem &item)

View File

@ -859,6 +859,22 @@ transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
});
}
/**
* Transcribe 0 or more trait impl items from a macro invocation
*
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
static std::vector<AST::SingleASTNode>
transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
auto item = parser.parse_trait_impl_item ();
return AST::SingleASTNode (std::move (item));
});
}
/**
* Transcribe 0 or more statements from a macro invocation
*
@ -932,6 +948,9 @@ transcribe_context (MacroExpander::ContextType ctx,
case MacroExpander::ContextType::IMPL:
return transcribe_many_impl_items (parser, last_token_id);
break;
case MacroExpander::ContextType::TRAIT_IMPL:
return transcribe_many_trait_impl_items (parser, last_token_id);
break;
case MacroExpander::ContextType::EXTERN:
return transcribe_many_ext (parser, last_token_id);
break;

View File

@ -187,9 +187,10 @@ struct MacroExpander
{
ITEM,
BLOCK,
EXTERN,
TRAIT,
IMPL,
EXTERN,
TRAIT_IMPL,
};
ExpansionCfg cfg;

View File

@ -138,6 +138,7 @@ public:
std::unique_ptr<AST::ExternalItem> parse_external_item ();
std::unique_ptr<AST::TraitItem> parse_trait_item ();
std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
AST::PathInExpression parse_path_in_expression ();
std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params ();
AST::Visibility parse_visibility ();
@ -298,7 +299,6 @@ private:
std::unique_ptr<AST::InherentImplItem>
parse_inherent_impl_function_or_method (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
std::unique_ptr<AST::TraitImplItem>
parse_trait_impl_function_or_method (AST::Visibility vis,
AST::AttrVec outer_attrs);

View File

@ -0,0 +1,19 @@
trait Valuable {
const VALUE: i32;
}
struct Something;
macro_rules! implement {
() => {
const VALUE: i32 = 18;
};
}
impl Valuable for Something {
implement!();
}
fn main() -> i32 {
Something::VALUE - 18
}