0

我有一个结构和一个特征:

struct Foo {
    i: i32,
}

trait FooTrait {
    fn foo(&self);
}

我想为生成 impl 的结构创建一个派生宏:

impl FooTrait for Foo {
    fn foo(&self) {
        println!("generated code: {}", self.i);
    }
}

当我试图实现这一点时,我面临一个障碍,即我的派生宏似乎没有办法知道 的令牌流FooTrait,我需要遍历 的方法FooTrait,并为每个特征方法生成实现基于Foo

我怎样才能做到这一点?

这个问题不是关于如何使用quote!引用特征 impl 并foo直接拼写出来 - 困难的部分是我想在程序上迭代 的方法FooTrait,并为每个特征方法生成一些样板代码。

4

2 回答 2

1

你没有。

通过构造,宏只提供了它们所附加的项目的源代码。如果将宏附加到结构,则看不到特征。

类似的派生宏包含有关正在实现的特征的知识。它们还可以解析允许用户配置有关生成代码的详细信息的自定义属性。您的宏可能会做同样的事情。

也可以看看:

于 2021-11-30T17:44:41.113 回答
0

一种可能的解决方法:不是FooTrait直接定义,而是将您需要的有关它的信息编码到某种结构中,将其存储在 a 中const,并从派生宏和另一个生成FooTrait.

编辑:如果你想要“的”令牌流FooTrait,你不需要const(这只是一个骨架,未经测试):

宏箱:

#[proc_macro]
pub fn foo_trait_definition(_input: TokenStream) -> TokenStream {
    TokenStream::from(quote!(
        trait FooTrait {
            ... // actual definition goes here
        }
    ))
}

#[proc_macro_derive(FooTrait)]
pub fn foo_trait_derivation(input: TokenStream) -> TokenStream {
    let foo_trait_tokens: TokenStream = foo_trait_definition(TokenStream::from(quote!()));

    // you can parse foo_trait_tokens and use them just like input

    TokenStream::from(quote!(
        impl foo_mod::FooTrait for #name {
            ...
        }
    ))
}

特质箱:

mod foo_mod {
    foo_trait_definition!();
}

#[derive(FooTrait)]
struct Foo {
    i: i32,
}

但我希望在大多数情况下,宏箱可以看起来像这样,而不是解析foo_trait_tokens

// lists method names here, if they are all (&self)
// but probably you want something more complex
const foo_trait_data = ["foo"];

#[proc_macro]
pub fn foo_trait_definition(_input: TokenStream) -> TokenStream {
    // use foo_trait_data here
 
    TokenStream::from(quote!(
        trait FooTrait {
            ... // actual definition goes here
        }
    ))
}

#[proc_macro_derive(FooTrait)]
pub fn foo_trait_derivation(input: TokenStream) -> TokenStream {
    // use foo_trait_data here too

    TokenStream::from(quote!(
        impl foo_mod::FooTrait for #name {
            ...
        }
    ))
}
于 2021-11-30T19:56:43.400 回答