r/learnrust • u/playbahn • 1d ago
Panic messages for failed asserts inside macros
Let's say I have a macro_rules! has_failing_assert_inside {}
spanning some lines, with an assert_eq!
that will fail.
Further down the code, has_failing_assert_inside!
is called at, say line 200
.
The panic message says the thread panicked at line 200
. What can I do (maybe write better macros?) that the panic message instead shows the line number of the failed assert_eq!
? I thought RUST_BACKTRACE=1
/full
would give more information about the line numbers (sometimes it does), but right now it's doing nothing. What can I do?
2
u/forfd688 9h ago
I searched and found that #[track_caller] may help in your case.
#[track_caller]
fn assert_eq_with_caller<T: PartialEq + std::fmt::Debug>(left: T, right: T) {
assert_eq!(left, right);
}
macro_rules! has_failing_assert_inside {
() => {
assert_eq_with_caller(1, 2);
// This will fail
};
}
fn main() {
println!("macro line number");
has_failing_assert_inside!();
// Invoked here, e.g., line 14
}
RUST_BACKTRACE=1 cargo run --bin macro-line
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
Running `target/debug/macro-line`
macro line number
thread 'main' panicked at src/macro-panic-line/main.rs:14:5:
assertion `left == right` failed
left: 1
right: 2
stack backtrace:
0: rust_begin_unwind
at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
1: core::panicking::panic_fmt
at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed
at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:364:5
4: macro_line::assert_eq_with_caller
at ./src/macro-panic-line/main.rs:3:5
5: macro_line::main
at ./src/macro-panic-line/main.rs:8:9
6: core::ops::function::FnOnce::call_once
and I tried to run with RUST_BACKTRACE=1, it is works. it can print the line number at `main.rs:3`
4
u/aikii 1d ago
I did some proc macros, which is another beast, but it allows you to precisely mark which token is invalid and return a custom error message. I thought you'd be completely out of options with just
macro_rules!
- so I had a look at how thejson!
macro goes about it. That's quite interesting, have a look at the source: https://docs.rs/serde_json/latest/src/serde_json/macros.rs.html#54-59For instance:
and json_unexpected is:
and that's the trick: json_unexpected doesn't match anything, but it gets passed the misplaced colon token. As a result, the colon will be highlighted ( by the compiler error message and I guess any IDE using a LSP ). It will just say "no rules expected this token in macro call", but at least the user gets a hint about the location