Skip to content

Commit a7ef6f9

Browse files
committed
macros: Allow macro calls in trait implementations
Just like inherent implementation blocks, trait implementation blocks (`impl Trait for Type`) can also contain macro invocations.
1 parent 935b561 commit a7ef6f9

File tree

6 files changed

+75
-4
lines changed

6 files changed

+75
-4
lines changed

gcc/rust/ast/rust-ast.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,7 @@ class SingleASTNode
15141514
EXTERN,
15151515
TRAIT,
15161516
IMPL,
1517+
TRAIT_IMPL,
15171518
};
15181519

15191520
private:
@@ -1526,6 +1527,7 @@ class SingleASTNode
15261527
std::unique_ptr<ExternalItem> external_item;
15271528
std::unique_ptr<TraitItem> trait_item;
15281529
std::unique_ptr<InherentImplItem> impl_item;
1530+
std::unique_ptr<TraitImplItem> trait_impl_item;
15291531

15301532
public:
15311533
SingleASTNode (std::unique_ptr<Expr> expr)
@@ -1552,6 +1554,10 @@ class SingleASTNode
15521554
: kind (IMPL), impl_item (std::move (item))
15531555
{}
15541556

1557+
SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item)
1558+
: kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item))
1559+
{}
1560+
15551561
SingleASTNode (SingleASTNode const &other)
15561562
{
15571563
kind = other.kind;
@@ -1580,6 +1586,10 @@ class SingleASTNode
15801586
case IMPL:
15811587
impl_item = other.impl_item->clone_inherent_impl_item ();
15821588
break;
1589+
1590+
case TRAIT_IMPL:
1591+
trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
1592+
break;
15831593
}
15841594
}
15851595

@@ -1611,6 +1621,10 @@ class SingleASTNode
16111621
case IMPL:
16121622
impl_item = other.impl_item->clone_inherent_impl_item ();
16131623
break;
1624+
1625+
case TRAIT_IMPL:
1626+
trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
1627+
break;
16141628
}
16151629
return *this;
16161630
}
@@ -1679,6 +1693,12 @@ class SingleASTNode
16791693
return std::move (impl_item);
16801694
}
16811695

1696+
std::unique_ptr<TraitImplItem> take_trait_impl_item ()
1697+
{
1698+
rust_assert (!is_error ());
1699+
return std::move (trait_impl_item);
1700+
}
1701+
16821702
void accept_vis (ASTVisitor &vis)
16831703
{
16841704
switch (kind)
@@ -1706,6 +1726,10 @@ class SingleASTNode
17061726
case IMPL:
17071727
impl_item->accept_vis (vis);
17081728
break;
1729+
1730+
case TRAIT_IMPL:
1731+
trait_impl_item->accept_vis (vis);
1732+
break;
17091733
}
17101734
}
17111735

@@ -1725,6 +1749,8 @@ class SingleASTNode
17251749
return trait_item == nullptr;
17261750
case IMPL:
17271751
return impl_item == nullptr;
1752+
case TRAIT_IMPL:
1753+
return trait_impl_item == nullptr;
17281754
}
17291755

17301756
gcc_unreachable ();
@@ -1747,6 +1773,8 @@ class SingleASTNode
17471773
return "Trait Item: " + trait_item->as_string ();
17481774
case IMPL:
17491775
return "Impl Item: " + impl_item->as_string ();
1776+
case TRAIT_IMPL:
1777+
return "Trait Impl Item: " + impl_item->as_string ();
17501778
}
17511779

17521780
gcc_unreachable ();

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,8 +2549,12 @@ AttrVisitor::visit (AST::TraitImpl &impl)
25492549
if (impl.has_where_clause ())
25502550
expand_where_clause (impl.get_where_clause ());
25512551

2552-
// strip trait impl items if required
2553-
expand_pointer_allow_strip (impl.get_impl_items ());
2552+
std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)>
2553+
extractor
2554+
= [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); };
2555+
2556+
expand_macro_children (MacroExpander::TRAIT_IMPL, impl.get_impl_items (),
2557+
extractor);
25542558
}
25552559
void
25562560
AttrVisitor::visit (AST::ExternalStaticItem &item)

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,22 @@ transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
859859
});
860860
}
861861

862+
/**
863+
* Transcribe 0 or more trait impl items from a macro invocation
864+
*
865+
* @param parser Parser to extract items from
866+
* @param delimiter Id of the token on which parsing should stop
867+
*/
868+
static std::vector<AST::SingleASTNode>
869+
transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
870+
TokenId &delimiter)
871+
{
872+
return parse_many (parser, delimiter, [&parser] () {
873+
auto item = parser.parse_trait_impl_item ();
874+
return AST::SingleASTNode (std::move (item));
875+
});
876+
}
877+
862878
/**
863879
* Transcribe 0 or more statements from a macro invocation
864880
*
@@ -932,6 +948,9 @@ transcribe_context (MacroExpander::ContextType ctx,
932948
case MacroExpander::ContextType::IMPL:
933949
return transcribe_many_impl_items (parser, last_token_id);
934950
break;
951+
case MacroExpander::ContextType::TRAIT_IMPL:
952+
return transcribe_many_trait_impl_items (parser, last_token_id);
953+
break;
935954
case MacroExpander::ContextType::EXTERN:
936955
return transcribe_many_ext (parser, last_token_id);
937956
break;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,10 @@ struct MacroExpander
187187
{
188188
ITEM,
189189
BLOCK,
190+
EXTERN,
190191
TRAIT,
191192
IMPL,
192-
EXTERN,
193+
TRAIT_IMPL,
193194
};
194195

195196
ExpansionCfg cfg;

gcc/rust/parse/rust-parse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ template <typename ManagedTokenSource> class Parser
138138
std::unique_ptr<AST::ExternalItem> parse_external_item ();
139139
std::unique_ptr<AST::TraitItem> parse_trait_item ();
140140
std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
141+
std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
141142
AST::PathInExpression parse_path_in_expression ();
142143
std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params ();
143144
AST::Visibility parse_visibility ();
@@ -298,7 +299,6 @@ template <typename ManagedTokenSource> class Parser
298299
std::unique_ptr<AST::InherentImplItem>
299300
parse_inherent_impl_function_or_method (AST::Visibility vis,
300301
AST::AttrVec outer_attrs);
301-
std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
302302
std::unique_ptr<AST::TraitImplItem>
303303
parse_trait_impl_function_or_method (AST::Visibility vis,
304304
AST::AttrVec outer_attrs);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait Valuable {
2+
const VALUE: i32;
3+
}
4+
5+
struct Something;
6+
7+
macro_rules! implement {
8+
() => {
9+
const VALUE: i32 = 18;
10+
};
11+
}
12+
13+
impl Valuable for Something {
14+
implement!();
15+
}
16+
17+
fn main() -> i32 {
18+
Something::VALUE - 18
19+
}

0 commit comments

Comments
 (0)