尝试在宏扩展中实现特征时出现宏错误

时间:2017-06-08 03:32:49

标签: rust rust-macros

fn a() {}似乎满足了预期fn的解析规则,然后是其他一些东西。 item应该可以是函数定义,对吗?所以他们应该工作,对吗?

macro_rules! multi_impl {
    (for $base:ty :
        $($t:ty {
            $($i:item);*
        }),+) =>
    {
        $(
            impl $t for $base
            {
                $( $i )*
            }
        )+
    }
}

trait A {
    fn a();
}

trait B {
    fn b();
}

struct S;

multi_impl! {
    for S:
    A {
        fn a() {}
    }, B {
        fn b() {}
    }
}

fn main() {
    S::a();
    S::b();
}

playground

有问题的错误:

error: expected one of `const`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `fn a() { }`
  --> <anon>:11:20
   |
11 |                 $( $i )*
   |                    ^^

使$( fn $i)*仅更改错误以抱怨在fn之后预期标识符,这是有道理的,但初始错误不会(至少对我而言)。

解析器中有关源代码中的代码与宏放入源代码的代码有什么不同吗?

1 个答案:

答案 0 :(得分:3)

问题不是fn不是一个项目,而impl 的主体不包含项目。它包含&#34; impl items&#34;。他们抱怨的是你试图将一个方形块放入一个圆孔中,而不是该块是错误的颜色。

是的,这是两件不同的事情。不,你无法捕获&#34; impl items&#34;在一个宏。不,您无法将项目转换为impl项目。因为宏捕获AST节点,而不是令牌。嗯,方法可以有self个参数,而常规函数也没有。{0}}。我不知道,当时这似乎是一个好主意。

将假设的来回放在一边,在这种情况下的解决方案是不要试图匹配特定中的任何内容,只是匹配任何

macro_rules! multi_impl
{
    (for $base:ty :
        $($t:ty {
            $($body:tt)*
        }),+) =>
    {
        $(
            impl $t for $base
            {
                $($body)*
            }
        )+
    }
}