Rust E0277报错:Vec<TokenStream2>未实现ToTokens,如何用quote!拼接该向量?
quote!宏拼接Vec<proc_macro2::TokenStream>的实现方式 错误原因
quote!宏的插值逻辑仅支持实现了quote::ToTokens trait的类型。标准库的Vec<T>本身不会因为元素类型实现了某个trait就自动获得对应trait的实现,因此直接将整个Vec<TokenStream>作为插值片段写入#x的位置时,就会抛出trait绑定不满足的E0277编译错误。
具体解法
- 使用quote内置的序列重复插值语法
这是最符合quote设计逻辑的简洁写法,依靠quote宏内置的#(<插值片段>)*语法,自动遍历可迭代序列完成逐个元素的展开拼接:
修正后的代码如下:
该语法的运行逻辑是:宏展开时会自动识别括号内的可迭代序列,对序列中的每个元素执行一次插值,所有生成的Token会按元素顺序连续拼接,最终组成完整的TokenStream。#[macro_use] extern crate quote; extern crate syn; extern crate proc_macro2; fn main() { let x = vec![ quote! {let x = 1;}, quote! {let x = 2;} ]; // 替换原代码中直接插值#x的写法为#(#x)* println!("{:#?}", quote! { #(#x)* }); } - 手动预合并为单个TokenStream
也可以先遍历Vec,将所有元素合并为单个proc_macro2::TokenStream实例,再传入quote!宏做插值:
由于use proc_macro2::TokenStream; fn main() { let x = vec![ quote! {let x = 1;}, quote! {let x = 2;} ]; let mut combined = TokenStream::new(); // 遍历每个独立的TokenStream,将其携带的Token追加到组合流中 for stream in x { combined.extend(stream); } println!("{:#?}", quote! { #combined }); }TokenStream本身实现了ToTokenstrait,合并完成的实例可以被quote!宏正常识别,不需要额外做类型转换。
内容的提问来源于stack exchange,提问作者Teymour
相关产品推荐
相关产品推荐

