递归宏使无限递归
Recursive macro makes infinite recursion
我做了一个简单的宏,returns 获取的参数。
macro_rules! n {
($n:expr) => {{
let val: usize = $n;
match val {
0 => 0,
_ => n!(val - 1),
}
}};
}
当我使用选项 external-macro-backtrace
编译这段代码时,它引发了一个错误:
error: recursion limit reached while expanding the macro `n`
--> src/main.rs:15:18
|
10 | macro_rules! n {
| _-
| |_|
| |
11 | | ($n:expr) => {{
12 | | let val: usize = $n;
13 | | match val {
14 | | 0 => 0,
15 | | _ => n!(val - 1),
| | ^^^^^^^^^^^
| | |
| | in this macro invocation
16 | | }
17 | | }};
18 | | }
| | -
| |_|
| |_in this expansion of `n!`
| in this expansion of `n!`
...
31 | | n!(1);
| | ------ in this macro invocation
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
我将 recursion_limit
更改为 128 或更高,但编译器错误消息也增加了。即使我调用 n!(0)
它也会出现同样的错误。我觉得是无限递归,但是找不到原因
嗯,这确实是一个无限递归。检查您的宏调用 n!(0)
将扩展为:
{
let val: usize = 0;
match val {
0 => 0,
_ => n!(0 - 1),
}
}
...并且由于 n!
的参数无法停止负增长,它会重复(在第二个匹配臂中使用 n!(0 - 1 - 1)
,然后 n!(0 - 1 - 1 - 1)
等.) 无限.
这里的关键点是宏扩展发生在编译时,而你试图用来限制递归的 match
语句只在 运行 时被调用,并且无法阻止任何东西在此之前出现。不幸的是,没有简单的方法来做到这一点,因为 Rust 不会计算宏参数(即使它是一个常量表达式),所以仅仅将 (0) => {0}
分支添加到宏是行不通的,因为宏会被调用为(例如)n!(1 - 1)
.
我做了一个简单的宏,returns 获取的参数。
macro_rules! n {
($n:expr) => {{
let val: usize = $n;
match val {
0 => 0,
_ => n!(val - 1),
}
}};
}
当我使用选项 external-macro-backtrace
编译这段代码时,它引发了一个错误:
error: recursion limit reached while expanding the macro `n`
--> src/main.rs:15:18
|
10 | macro_rules! n {
| _-
| |_|
| |
11 | | ($n:expr) => {{
12 | | let val: usize = $n;
13 | | match val {
14 | | 0 => 0,
15 | | _ => n!(val - 1),
| | ^^^^^^^^^^^
| | |
| | in this macro invocation
16 | | }
17 | | }};
18 | | }
| | -
| |_|
| |_in this expansion of `n!`
| in this expansion of `n!`
...
31 | | n!(1);
| | ------ in this macro invocation
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
我将 recursion_limit
更改为 128 或更高,但编译器错误消息也增加了。即使我调用 n!(0)
它也会出现同样的错误。我觉得是无限递归,但是找不到原因
嗯,这确实是一个无限递归。检查您的宏调用 n!(0)
将扩展为:
{
let val: usize = 0;
match val {
0 => 0,
_ => n!(0 - 1),
}
}
...并且由于 n!
的参数无法停止负增长,它会重复(在第二个匹配臂中使用 n!(0 - 1 - 1)
,然后 n!(0 - 1 - 1 - 1)
等.) 无限.
这里的关键点是宏扩展发生在编译时,而你试图用来限制递归的 match
语句只在 运行 时被调用,并且无法阻止任何东西在此之前出现。不幸的是,没有简单的方法来做到这一点,因为 Rust 不会计算宏参数(即使它是一个常量表达式),所以仅仅将 (0) => {0}
分支添加到宏是行不通的,因为宏会被调用为(例如)n!(1 - 1)
.