我编写了一个小宏来帮助我探索事物被解析为什么.砍掉几只胳膊后,看起来就像:
macro_rules! show_me{
($l : literal $($tail : tt)*) => {
println!("{} is a literal and then I see {}", stringify!($l), stringify!($($tail)*));
show_me!($($tail)*)
};
(- $($tail : tt)*) => {
println!("{} is a - and then I see {}", stringify!(-), stringify!($($tail)*));
show_me!($($tail)*)
};
($i : ident $($tail : tt)*) => {
println!("{} is an ident and then I see {}", stringify!($i), stringify!($($tail)*));
show_me!($($tail)*)
};
($token : tt $($tail : tt)*) => {
println!("{} is a mystery and then I see {}", stringify!($token), stringify!($($tail)*));
show_me!($($tail)*)
};
() => {}
}
这在使用Rustc 1.66.0(69f9c33d7 2022-12-12)的某些输入上表现出预期的行为:
show_me!(x + 1);
# x is an ident and then I see + 1
# + is a mystery and then I see 1
# 1 is a literal and then I see
但如果我try 一个负数,我会(有点)惊讶:
show_me!(-4);
# -4 is a literal and then I see
这将是完全有意义的,除了https://doc.rust-lang.org/reference/procedural-macros.html说(在声明性宏的描述下):
字面值("字符串",1等)
注意,否定(例如-1)从来不是这种字面标记的一部分, 而是一个单独的操作员令牌.
让我感到奇怪的是,如果我试着跑show_me!(-x)
米:
error: unexpected token: `x`
--> src/main.rs:54:15
|
54 | show_me!(-x);
| ^
|
::: src/utils/macros.rs:27:6
|
27 | ($l : literal $($tail : tt)*) => {
| ------------ while parsing argument for this `literal` macro fragment
请注意,如果我注释掉show_me
的literal
个手臂,或者只是将其移动到匹配器的底部,其他手臂对此非常满意:
show_me!(-x);
# - is a - and then I see x
# x is an ident and then I see
我的预期是,匹配的手臂要么匹配成功,要么进入下一种模式.相反,它引发了编译错误.在这种情况下发生了什么?
另外,我是误读了文档还是它是不正确的?对我来说,它似乎清楚地表明,-
永远不应该是声明性宏中文字表达式的一部分(尽管它可能是过程性宏中的一部分).