Skip to content

Commit 1d7f717

Browse files
authored
Fix unreachable!() override macro + new tests (rust-lang#1372)
My latest change to handling panic messages actually broke `unreachable` macro. The main issue was the wrong position of a parenthesis and the fact that we didn't have tests that covered that specific case of the macro. One thing I haven't figured out yet is how to trigger an error if the user code uses edition 2021+ and has the following construct: ```rust let msg = "blah"; panic!(msg); ``` This is actually an error in 2021+, but the macro override that we perform accepts that no matter the edition.
1 parent e282561 commit 1d7f717

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

library/std/src/lib.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,25 +140,54 @@ macro_rules! eprintln {
140140

141141
#[macro_export]
142142
macro_rules! unreachable {
143+
// The argument, if present, is a literal that represents the error message, i.e.:
144+
// `unreachable!("Error message")` or `unreachable!()`
143145
($($msg:literal)? $(,)?) => (
144146
kani::panic(concat!("internal error: entered unreachable code: ", $($msg)?))
145147
);
146-
($fmt:expr, $($arg:tt)*) => (
147-
kani::panic(concat!("internal error: entered unreachable code: ", $fmt), stringify!($($arg)*)));
148+
// The argument is an expression, such as a variable.
149+
// ```
150+
// let msg = format!("Error: {}", code);
151+
// unreachable!(msg);
152+
// ```
153+
// This was supported for 2018 and older rust editions.
154+
// TODO: Is it possible to trigger an error if 2021 and above?
155+
// https://github.com/model-checking/kani/issues/1375
156+
($($msg:expr)? $(,)?) => (
157+
kani::panic(concat!("internal error: entered unreachable code: ", stringify!($($msg)?)))
158+
);
159+
// The first argument is the format and the rest contains tokens to be included in the msg.
160+
// `unreachable!("Error: {}", code);`
161+
($fmt:literal, $($arg:tt)*) => (
162+
kani::panic(concat!("internal error: entered unreachable code: ",
163+
stringify!($fmt, $($arg)*))));
148164
}
149165

150166
#[macro_export]
151167
macro_rules! panic {
168+
// No argument is given.
152169
() => (
153170
kani::panic("explicit panic")
154171
);
172+
// The argument is a literal that represents the error message, i.e.:
173+
// `panic!("Error message")`
155174
($msg:literal $(,)?) => ({
156175
kani::panic(concat!($msg));
157176
});
177+
// The argument is an expression, such as a variable.
178+
// ```
179+
// let msg = format!("Error: {}", code);
180+
// panic!(msg);
181+
// ```
182+
// This was supported for 2018 and older rust editions.
183+
// TODO: Is it possible to trigger an error if 2021 and above?
184+
// https://github.com/model-checking/kani/issues/1375
158185
($msg:expr $(,)?) => ({
159186
kani::panic(stringify!($msg));
160187
});
161-
($msg:expr, $($arg:tt)*) => ({
162-
kani::panic(stringify!($msg, $($arg)*));
188+
// The first argument is the format and the rest contains tokens to be included in the msg.
189+
// `panic!("Error: {}", code);`
190+
($msg:literal, $($arg:tt)+) => ({
191+
kani::panic(stringify!($msg, $($arg)+));
163192
});
164193
}

tests/expected/unreachable/expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Failed Checks: internal error: entered unreachable code: msg
2+
Failed Checks: internal error: entered unreachable code:
3+
Failed Checks: internal error: entered unreachable code: Error message
4+
Failed Checks: internal error: entered unreachable code: "Unreachable message with arg {}", "str"
5+
Failed Checks: internal error: entered unreachable code: "{}", msg
6+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that our macro override supports different types of messages.
5+
#[kani::proof]
6+
fn check_unreachable() {
7+
let msg = "Oops.";
8+
match kani::any::<u8>() {
9+
0 => unreachable!(),
10+
1 => unreachable!("Error message"),
11+
2 => unreachable!("Unreachable message with arg {}", "str"),
12+
3 => unreachable!("{}", msg),
13+
_ => unreachable!(msg),
14+
}
15+
}

0 commit comments

Comments
 (0)