Rust 在函数开头插入代码的过程属性宏

Rust 在函数开头插入代码的过程属性宏,rust,rust-macros,rust-proc-macros,Rust,Rust Macros,Rust Proc Macros,我正在尝试构建一个简单的属性,该属性将在函数的开头注入let绑定,因此结果将是: #[foo] fn bar(){ //启动注入代码 设x=0; //端注入代码 ... } 我已经做到了: 使用proc_宏::令牌流; 使用引号::{quote,ToTokens}; 使用syn:{parse_macro_input,ItemFn,Item,Stmt}; #[过程宏属性] pub fn hello(attr:TokenStream,stream:TokenStream)->TokenStream

我正在尝试构建一个简单的属性,该属性将在函数的开头注入let绑定,因此结果将是:

#[foo]
fn bar(){
//启动注入代码
设x=0;
//端注入代码
...
}
我已经做到了:

使用proc_宏::令牌流;
使用引号::{quote,ToTokens};
使用syn:{parse_macro_input,ItemFn,Item,Stmt};
#[过程宏属性]
pub fn hello(attr:TokenStream,stream:TokenStream)->TokenStream{
let input=parse_macro_input!(流为ItemFn);
设block=input.block;
设res=quote!{let x=1;};
//无法工作,无法将TokenStream转换为Stmt
block.stmts.insert(0,res.into());
TokenStream::from(input.into_token_stream())
}
然而,我在处理这些物品时遇到了麻烦。例如,
的类型是
Vec
,现在一个语句是由片段组成的(
本地
Expr,
),当我试图处理这些片段时,我就迷路了。我觉得我缺少了一些关于如何处理这些问题的信息,但是查看提供的示例
trace vars
并没有帮助,而且很多在线资源都过时了

我还尝试了一种非常愚蠢的方法,使用quote创建一个
ItemFn
,对其进行解析,并从中获取
Stmt
,但由于
TokenStream
实际上来自两个不同的板条箱,
proc\u macro
proc\u macro2

#[proc_宏_属性]
pub fn hello(attr:TokenStream,stream:TokenStream)->TokenStream{
let input=parse_macro_input!(流为ItemFn);
let res=quote!{fn(){let x=1;};
让res=parse_macro_input!(res作为ItemFn);
设block=input.block;
block.stmts.insert(0,res.block.stmts[0].clone());
TokenStream::from(input.into_token_stream())
}
错误[E0308]:类型不匹配
-->b sub-procedural/src/lib.rs:13:15
|
13 |让res=parse_macro_输入!(列为第fn项);
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^预期结构为`proc_macro::TokenStream`,找到结构为`proc_macro2::TokenStream``
继续

[dependencies]
syn = { version = "1.0.67", features=["full", "fold", "printing"] }
quote = "1.0.9"
在某些情况下,“愚蠢的方法”实际上是一个相当有效的解决方案。要分析
proc_macro2::TokenStream
,请使用而不是宏

解析肯定是浪费,因为结果会立即再次转换为令牌流。但对于小事情,这是好的。另一种方法是将函数的所有部分分别转换为令牌,例如:

let ItemFn { attrs, vis, sig, block } = input;
let stmts = &block.stmts;
quote! {
    #(#attrs)* #vis #sig {
        let x = 1; // <- your extra code
        #(#stmts)*
    }
}
让ItemFn{attrs,vis,sig,block}=input;
设stmts=&block.stmts;
引用{
#(#属性)*#vis#sig{

让x=1;//谢谢你的回答,愚蠢的方法与
syn::parse2
!关于另一个解决方案,它显然更好,我得到的错误是
特性'quote::to_tokens::tototokens'没有为'std::vec::vec'
实现。我已经导入了
使用quote::tokens
,并且我已经检查了
属性
实现了它,它确实实现了。也许是
vec
部分没有实现?我已经添加了
syn
quote
的版本,如果可能是源代码,它们都是latest@Dominus呜呜,这就是我不测试代码的原因。
#attrs
应该是
#(#attrs)*
。我修正了答案。现在应该可以了。谢谢你的答案!顺便说一句,如果你有任何好的proc宏学习资源,我很乐意阅读!