Rust 过程宏 proc-macro2 和 proc-macro 主要区别

The proc-macro2 crate is a drop-in replacement for proc_macro except that it is available outside of macros - which makes it testable. Its types are all convertible to and from the proc_macro types and have identical methods.

The usual pattern for writing a nontrivial macro is to use proc_macro only for the entry point, and use proc-macro2 for all of the real work:

extern crate proc_macro;
use proc_macro2::TokenStream;

#[proc_macro]
pub fn my_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let output = transform_stream(TokenStream::from(input));
    proc_macro::TokenStream::from(output)
}

// A testable function!
fn transform_stream(input: TokenStream) -> TokenStream {
    // actual work goes here
}

It's common to import items from proc-macro2 so they can be used unqualified, and just used fully qualified names for proc_macro, since the only time you will use it is in the entry point. It's also usual to put the core components in a separate library crate, which does not have a dependency on proc_macro.

In tests, you can create a TokenStream from a string:

use std::str::FromStr;
let ts = TokenStream::from_str("fn foo() {}").unwrap();

Rust 中,编写过程宏,必须在 Cargo.toml 中设置 [lib]proc-macro = true,这样就导致该库只能用于编写过程宏代码,无法在其他库中编写 proc-macro 代码,比如在其他包中无法使用 use proc_macro::TokenStream;,这样就很难对宏代码进行单元测试。

所以第三方提供了 proc-macro2 这样的包,可以在任何库类型中编写过程宏代码逻辑,而且完全可以进行测试。

比如我们通过 proc-macro2 编写了生成 proc_macro2::TokenStream 代码之后,再通过 proc_macro2::TokenStream::from(proc_macro::TokenStream) 转换成 proc_macro::TokenStream

见上面例子

posted @ 2022-04-26 14:50  Rustln  阅读(1483)  评论(0编辑  收藏  举报