Rust宏编译超时问题排查:自定义Range扩展宏错误分析
你的宏定义存在三个关键问题,导致编译超时或错误
宏无限递归引发编译超时
顶层的range!($($t:tt)*)规则会匹配所有输入,包括带@parse前缀的内部调用。当它执行range!(@parse $($t:tt)*)时,这个新调用会再次匹配顶层规则,而非直接匹配@parse开头的内部规则,进而触发无限递归展开,最终导致编译超时。变量拼写错误
在@parse $range:expr;step:expr规则中,MyRange::from($rage)里的$rage是笔误,正确名称应为$range。片段绑定语法错误
第二个内部规则里的step:expr写法错误,expr片段需要绑定到变量才能使用,应该写成step=$step:expr,否则$step变量无法被识别。
修正后的代码
方案一:移除内部转发规则,直接匹配
use std::ops::Range; use std::convert::From; #[derive(Debug)] struct MyRange<Idx> { start: Idx, end: Idx, step: Idx } impl<Idx> From<Range<Idx>> for MyRange<Idx> { fn from(range: Range<Idx>) -> MyRange<Idx> { MyRange { start: range.start, end: range.end, step: 0 } } } macro_rules! range { // 匹配不带step的范围表达式 ($range:expr) => { MyRange::from($range) }; // 匹配带step参数的情况 ($range:expr; step=$step:expr) => { let mut r = MyRange::from($range); r.step = $step; r }; } fn main() { let range1 = range!(0..3); println!("{:?}", range1); let range2 = range!(0..10; step=2); println!("{:?}", range2); }
方案二:保留内部转发规则,调整匹配顺序
如果想保留@parse内部规则,需要调整规则顺序让内部规则优先匹配:
use std::ops::Range; use std::convert::From; #[derive(Debug)] struct MyRange<Idx> { start: Idx, end: Idx, step: Idx } impl<Idx> From<Range<Idx>> for MyRange<Idx> { fn from(range: Range<Idx>) -> MyRange<Idx> { MyRange { start: range.start, end: range.end, step: 0 } } } macro_rules! range { // 优先匹配内部@parse规则 (@parse $range:expr) => { MyRange::from($range) }; (@parse $range:expr; step=$step:expr) => { let mut r = MyRange::from($range); r.step = $step; r }; // 最后匹配顶层调用,转发到内部规则 ($($t:tt)*) => { range!(@parse $($t:tt)*) }; } fn main() { let range1 = range!(0..3); println!("{:?}", range1); let range2 = range!(0..10; step=2); println!("{:?}", range2); }
内容的提问来源于stack exchange,提问作者musako
相关产品推荐
相关产品推荐

