Skip to content

Commit 35d75e3

Browse files
committed
Ensure panic! messages are only formatted once
1 parent baf28f4 commit 35d75e3

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

library/std/src/panicking.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -249,20 +249,20 @@ fn default_hook(info: &PanicInfo<'_>) {
249249
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
250250

251251
let write = |err: &mut dyn crate::io::Write| {
252-
// Use the panic message directly if available, otherwise take it from
253-
// the payload.
254-
if let Some(msg) = info.message() {
255-
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
252+
// The std panic runtime always sets a `&str` or `String` payload for `panic!` and related
253+
// macros with the formatted message.
254+
// We try using the payload first to avoid formatting the message twice.
255+
let msg: &dyn fmt::Display = if let Some(s) = info.payload().downcast_ref::<&'static str>()
256+
{
257+
s
258+
} else if let Some(s) = info.payload().downcast_ref::<String>() {
259+
s
260+
} else if let Some(msg) = info.message() {
261+
msg
256262
} else {
257-
let msg = if let Some(s) = info.payload().downcast_ref::<&'static str>() {
258-
*s
259-
} else if let Some(s) = info.payload().downcast_ref::<String>() {
260-
&s[..]
261-
} else {
262-
"Box<dyn Any>"
263-
};
264-
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
265-
}
263+
&"Box<dyn Any>"
264+
};
265+
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");
266266

267267
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
268268

0 commit comments

Comments
 (0)