Rust过程宏解析#[builder(each = "arg")]属性时出错
问题原因与解决方法
核心原因
你遇到的unexpected token错误,本质是**syn::Attribute::parse_args()的默认解析规则不支持=式的键值语法**。
parse_args()默认期望解析的是类似Rust函数参数/结构体字段的语法(用冒号:分隔键值,比如each: "arg"),而你写的each = "arg"属于Rust属性里的赋值式命名参数,这种语法不在它的默认解析范围内,所以会触发语法错误——这也是为什么你换成<这类符号时解析正常,因为那些符号不在默认解析的冲突规则里。
两种解决思路
思路1:修改属性语法(最简单)
直接把属性里的=改成:,符合parse_args()的默认规则:
#[builder(each: "arg")] struct Command { // ... }
这样不用改解析代码,直接就能正常解析。
思路2:自定义解析逻辑(保留=语法)
如果一定要保留each = "arg"的写法,需要基于syn的Parse trait自定义解析规则,显式匹配等号:
use syn::{parse::Parse, parse_macro_input, Ident, LitStr, Token}; // 定义要解析的参数结构 #[derive(Debug)] struct BuilderAttrArgs { each_name: String, } // 实现Parse trait,处理`each = "xxx"`的语法 impl Parse for BuilderAttrArgs { fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { // 解析`each`标识符 let each_ident: Ident = input.parse()?; if each_ident != "each" { return Err(input.error("expected `each`")); } // 匹配等号 let _eq: Token![=] = input.parse()?; // 解析字符串字面量 let lit_str: LitStr = input.parse()?; Ok(Self { each_name: lit_str.value() }) } } // 在派生宏中使用自定义解析 let attr_args = parse_macro_input!(attr.tokens as BuilderAttrArgs);
这种方式可以完全兼容你想要的=式语法,适合需要严格遵循特定属性格式的场景。
内容的提问来源于stack exchange,提问作者dieri
相关产品推荐
相关产品推荐

