如何匹配宏中的方法?

时间:2018-07-28 13:15:31

标签: macros rust

item片段可以匹配函数,但是如果函数的第一个参数是self的变体,则 ie (如果它是方法),则无法识别作为item

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

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

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

fn main() {}

如何匹配方法?

1 个答案:

答案 0 :(得分:4)

采用self的函数不是项,因为没有impl块才能为self提供类型,它就不能存在于顶层。

周围的impl 是一个项目。

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

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

但是您必须在impl块内部使用宏

impl Foo {
    test! {
        fn foo(self) -> bool {
            true
        }
    }
}

尽管如此,您还必须在这里处理很多可能的函数排列,最终可能会变得非常重复:

// 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
    ) => {};
}

这些甚至都没有考虑生存期或类型参数。

通过将这些情况委托给另一个宏来获得代码重用可能很棘手,因为您在宏内没有self类型,因此很遗憾,您可能无法摆脱重复