Rust macro_rules中匹配模块路径+类型名应使用什么元变量片段符?
报错原因
你编写的宏无法正常工作的核心原因是片段符选择不符合Rust宏的语法限制:你使用ty片段符捕获列名后,Rust会将该元变量标记为仅可用于类型上下文,无法直接拼接在$namespace::后作为路径片段使用,path/tt等其他你尝试过的片段符也存在类似的上下文适配问题。
正确实现
由于你传入的列名A、B以及Diesel表中的列本质都是标识符,直接使用ident片段符捕获列名即可,优化后的宏写法如下:
macro_rules! impl_cols { // 匹配规则支持末尾可选逗号,适配不同的调用书写习惯 ( $namespace:path, $($col_name:ident),* $(,)? ) => { pub fn cols() -> ( $( $namespace::$col_name, )* ) { ( $( $namespace::$col_name, )* ) } } }
调用示例
针对你给出的类型定义,按如下方式调用宏即可生成需要的cols函数:
// 传入命名空间路径和对应的列标识符 impl_cols!(crate::foo::bar, A, B); // 调用生成的函数,类型完全符合预期 fn test() { let (a, b) = cols(); // a 类型为 crate::foo::bar::A // b 类型为 crate::foo::bar::B }
Diesel场景适配
该写法完全适配你的Diesel使用场景:只需要将表模块的路径作为第一个参数传入宏,后续跟上对应结构体需要的列名,生成的cols函数返回的列元组可以直接传入.select()方法使用,不需要额外调整。
内容的提问来源于stack exchange,提问作者Shelvacu
相关产品推荐
相关产品推荐

