Reputation: 157
I can build structs and enums using macros but not traits. Is this a bug or something about how traits work that I am missing? Here is a simple example that fails to build:
macro_rules! fun{
() => { fn hello(); }
}
macro_rules! full_fun{
() => { fn hello(){} }
}
// Fails with:
// <anon>:13:8: 13:11 error: expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `fun`
// <anon>:13 fun!();
macro_rules! trait_macro{
($name:ident) => {
pub trait $name {
fun!();
}
};
}
macro_rules! struct_macro{
($name:ident) => {
pub struct $name;
impl $name {
full_fun!();
}
};
}
// I can add functions to a Impl
struct_macro!{Monster}
// But I cannot add functions to a trait
trait_macro!{Monster}
fn main() {
}
Upvotes: 0
Views: 1252
Reputation: 14021
According to the Rust documentation on macros, a macro can be expanded as:
Your full_fun
becomes a method, but I think a declaration inside a trait doesn't count. (I haven't found an exact reference, though).
Even if it were, it wouldn't help: due to the macro hygiene rules, the hello
defined couldn't be referenced elsewhere, as it would effectively be a unique identifier different from any other - ie your fun!()
macro would not be declaring the same function as is implemented by full_fun!()
.
Upvotes: 1
Reputation: 157
Macro inside trait expansion is currently not supported. The relevant AST code:
pub enum TraitItemKind {
Const(P<Ty>, Option<P<Expr>>),
Method(MethodSig, Option<P<Block>>),
Type(TyParamBounds, Option<P<Ty>>),
}
As the error message states only one of const
, extern
, fn
, type
, or unsafe
are expected as next token in a Trait.
Upvotes: 0