Rust带泛型的自定义宏报错:expected one of @ or |, found : 求解
Rust自定义宏编译错误:
expected one of @ or |, found : 的原因与解决方法 问题描述
我尝试在Rust中编写如下自定义宏:
macro_rules! custom_macro { ($gen: ident) => { let value: MyCustomType<$gen> = Deserialize::deserialize(data)?; // 此处为其他代码 }; }
但编译时let ...行抛出错误:error: expected one of @ or |, found :。以下是更贴近实际场景的完整示例:
macro_rules! custom_macro { ($gen: ident) => { let value: MyCustomType<$gen> = todo!(); Ok(()) }; } struct MyCustomType<T>(T); struct Inner; struct Outer; pub async fn my_func(flag: bool) -> Result<(), std::error::Error> { match flag { true => custom_macro!(Inner), false => custom_macro!(Outer), } } fn main() -> Result<(), Box<dyn std::error::Error>> { my_func(true) }
原因分析
这是macro_rules!宏的解析机制导致的问题:当宏展开体中出现<时,宏处理器会默认将其视为宏模式语法的一部分(比如用于重复匹配的$(...)*结构),而非普通Rust代码中用于类型参数的括号。此时处理器会按照宏模式的规则解析后续内容,当它遇到类型注解的:时,就会触发语法错误——因为宏模式里<之后只允许出现@(绑定模式)或|(分支模式)。
解决方法
有两种可靠的方式让宏处理器正确识别<>是普通代码的类型参数语法:
方法1:使用Turbofish语法
通过::<>明确标记类型参数,避免宏处理器混淆:
macro_rules! custom_macro { ($gen: ident) => { let value: MyCustomType::<$gen> = todo!(); Ok(()) }; }
方法2:用大括号包裹类型
将类型部分放在大括号中,强制宏处理器按普通Rust代码解析内部内容:
macro_rules! custom_macro { ($gen: ident) => { let value: { MyCustomType<$gen> } = todo!(); Ok(()) }; }
完整修正代码
同时修复原示例中main函数无法直接调用async函数的问题:
macro_rules! custom_macro { ($gen: ident) => { let value: MyCustomType::<$gen> = todo!(); Ok(()) }; } struct MyCustomType<T>(T); struct Inner; struct Outer; pub async fn my_func(flag: bool) -> Result<(), std::error::Error> { match flag { true => custom_macro!(Inner), false => custom_macro!(Outer), } } fn main() -> Result<(), Box<dyn std::error::Error>> { // 使用Runtime阻塞执行async函数 tokio::runtime::Runtime::new()?.block_on(my_func(true))?; Ok(()) }
内容的提问来源于stack exchange,提问作者terett
相关产品推荐
相关产品推荐

