我正在创建一个名为 throw_error
的宏。我希望它能编译,但它失败了:
// Util structs + types
...
// Util macros
#[macro_export]
macro_rules! throw_error {
() => {
RaptorexError {
message: String::new(),
line: line!(),
file: file!().to_owned(),
}
};
($($msg:tt),*) => {
let mut final_msg = String::new();
$(
final_msg.push_str(&format!("{} ", $msg));
)*
// remove trailing whitespace
final_msg.pop();
RaptorexError {
message: final_msg,
line: line!(),
file: file!(),
}
}
}
// Util functions
...
我在其他代码中使用宏时遇到了几个错误。
错误:
error: macro expansion ignores token `final_msg` and any following
--> /Users/henryboisdequin/Desktop/raptorex/raptorex_util/src/lib.rs:30:13
|
30 | final_msg.push_str(&format!("{} ", $msg));
| ^^^^^^^^^
|
::: compiler/src/parser/parser.rs:44:29
|
44 | _ => return Err(throw_error!("Unexpected token:", current_token)),
| ------------------------------------------------- help: you might be missing a semicolon here: `;`
| |
| caused by the macro expansion here
|
= note: the usage of `throw_error!` is likely invalid in expression context
error[E0658]: `let` expressions in this position are experimental
--> compiler/src/parser/parser.rs:44:29
|
44 | _ => return Err(throw_error!("Unexpected token:", current_token)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
= help: add `#![feature(let_chains)]` to the crate attributes to enable
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `let` expressions are not supported here
--> compiler/src/parser/parser.rs:44:29
|
44 | _ => return Err(throw_error!("Unexpected token:", current_token)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: only supported directly in conditions of `if`- and `while`-expressions
= note: as well as when nested within `&&` and parenthesis in those conditions
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: unused imports: `DATA_TYPES`, `KEYWORDS`
--> compiler/src/parser/parser.rs:3:28
|
3 | lexer::tokens::{Token, DATA_TYPES, KEYWORDS},
| ^^^^^^^^^^ ^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0308]: mismatched types
--> compiler/src/parser/parser.rs:44:29
|
44 | _ => return Err(throw_error!("Unexpected token:", current_token)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `raptorex_util::RaptorexError`, found `bool`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors; 1 warning emitted
这些错误的原因是什么,我该如何解决?
最佳答案
您需要另一组 {}
,以便宏创建一个包含语句而不是单个语句本身的 block :
#[macro_export]
macro_rules! throw_error {
() => {
RaptorexError {
message: String::new(),
line: line!(),
file: file!().to_owned(),
}
};
($($msg:tt),*) => {
{ // <------------------
let mut final_msg = String::new();
$(
final_msg.push_str(&format!("{} ", $msg));
)*
// remove trailing whitespace
final_msg.pop();
RaptorexError {
message: final_msg,
line: line!(),
file: file!(),
}
} // <-------------------
}
}
(...) => {}
中的 {}
是宏语法的一部分,而不是生成代码的一部分。
关于rust - 如何在 `macro_rules!` 中声明一个变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66240468/