rust 开始使用proc宏时遇到问题(为什么不工作?)

3zwjbxry  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(258)

我正试着跟随这篇文章,用proc宏(Can a procedural macro be debugged as a function?)来打湿我的脚。
我想出来这个只是为了感受一下它是如何工作的:

extern crate proc_macro;
use proc_macro2::TokenStream;
use std::str::FromStr;
use syn;
use quote;

fn main() {
    let ts = TokenStream::from_str("fn foo() {}").unwrap();
    let _ts_str = ts.to_string();
    let parsed = syn::parse_macro_input!(ts);
}

但是当我在Playground中运行时,我收到以下错误:

error[E0308]: mismatched types
   --> src/main.rs:10:18
    |
10  |     let parsed = syn::parse_macro_input!(ts);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
    |                  expected struct `proc_macro::TokenStream`, found struct `TokenStream2`
    |                  arguments to this function are incorrect
    |
note: function defined here
   --> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.103/src/parse_macro_input.rs:138:8
    |
138 | pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
    |        ^^^^^
    = note: this error originates in the macro `$crate::parse_macro_input` which comes from the expansion of the macro `syn::parse_macro_input` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> src/main.rs:10:18
   |
10 |     let parsed = syn::parse_macro_input!(ts);
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `proc_macro::TokenStream`
   |
   = note: this error originates in the macro `$crate::parse_macro_input` which comes from the expansion of the macro `syn::parse_macro_input` (in Nightly builds, run with -Z macro-backtrace for more info)

我在理解发生了什么事情上遇到了困难,我需要一些帮助。我尝试了各种类型转换,但似乎都不起作用。
我知道作为一个Rust的新手,我有点跳进了游泳池的深水区,但这是不可避免的。我遇到了一些小问题,我认为这些问题会阻碍我们接受Rust的申请。我在努力寻找一条摩擦尽可能小的路来说服我们的团队(和我自己)在我们的嵌入式应用程序中远离C/C++。所以我感谢这里的帮助和耐心。

cetgtptt

cetgtptt1#

你有一个proc_macro2::TokenStream,而宏需要的是proc_macro::TokenStream。幸运的是,它们可以通过基本的From/Into特性相互转换。
您没有提供要解析的类型。您至少应该知道您所期望的语法类型。这里您可以使用ItemFn或更一般的Item。但是如果您正在创建#[derive()]宏,您应该使用DeriveInput
parse_macro_input上的说明文件:
此宏必须从返回proc_macro::TokenStream的函数调用。
这是因为宏具有内置的错误处理功能,如果流与预期的输入类型不匹配,则会提前退出,并返回一个包含compile_error!的流。
在像这里这样的独立二进制文件中尝试执行此操作可能会遇到问题,因为proc_macro只能在过程宏调用中使用。如果需要,可以将宏替换为parse2
下面是一个完整的工作示例:

use proc_macro2::TokenStream;
use std::str::FromStr;
use syn::ItemFn;

fn main() {
    let ts = TokenStream::from_str("fn foo() {}").unwrap();
    let parsed = syn::parse2::<ItemFn>(ts).unwrap();

    println!("{:?}", parsed);
}

请看它在playground上的工作情况。

相关问题