如何匹配宏中的方法?

Fre*_*ios 5 macros rust

item片段可以匹配函数,但是如果函数的第一个参数是的变体self如果它是方法,则不能将其识别为item

macro_rules! test {
    ( $fn:item ) => {}
}

// Ok
test! {
    fn foo() -> bool {
        true
    }
}

// Not ok
test! {
    fn foo(self) -> bool {
        true
    }
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

如何搭配方法?

Pet*_*all 4

接受的函数不是一个项目,因为如果没有一个块来为 提供类型,self它就不能存在于顶层。implself

不过,周围的impl一个项目。

为了匹配该功能,您必须将其分解,也许像这样:

macro_rules! test {
    ( fn $fn:ident ( self ) -> $ret:ty $body:block ) => {};
}
Run Code Online (Sandbox Code Playgroud)

但你必须在块使用宏impl

impl Foo {
    test! {
        fn foo(self) -> bool {
            true
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

不过,您还必须在这里处理相当多可能类型的函数的排列,这最终可能会变得非常重复:

// enables the ? operator for optional parts
#![feature(macro_at_most_once_rep)]

macro_rules! test {
    ( fn $fn:ident ( $($name:ident : $type:ty),* ) $( -> $ret:ty )? 
        $body:block 
    ) => {};
    ( fn $fn:ident ( self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )? 
        $body:block 
    ) => {};
    ( fn $fn:ident ( &self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )? 
        $body:block 
    ) => {};
    ( fn $fn:ident ( &mut self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )? 
        $body:block
    ) => {};
}
Run Code Online (Sandbox Code Playgroud)

这些甚至不考虑生命周期或类型参数。

通过将这些情况委托给另一个宏来实现代码重用可能会很棘手,因为您没有 self宏内部的类型,因此不幸的是,您可能无法摆脱重复。