diff --git a/core/src/panic.rs b/core/src/panic.rs index 8771f40f9b42b..c9f3702e17889 100644 --- a/core/src/panic.rs +++ b/core/src/panic.rs @@ -144,7 +144,7 @@ pub macro unreachable_2021 { /// use. #[unstable(feature = "std_internals", issue = "none")] #[doc(hidden)] -pub unsafe trait PanicPayload { +pub unsafe trait PanicPayload: crate::fmt::Display { /// Take full ownership of the contents. /// The return type is actually `Box`, but we cannot use `Box` in core. /// diff --git a/std/src/panicking.rs b/std/src/panicking.rs index a460f41b93d3d..362aa8d06f33b 100644 --- a/std/src/panicking.rs +++ b/std/src/panicking.rs @@ -625,6 +625,12 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { } } + impl fmt::Display for FormatStringPayload<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(s) = &self.string { f.write_str(s) } else { f.write_fmt(*self.inner) } + } + } + struct StaticStrPayload(&'static str); unsafe impl PanicPayload for StaticStrPayload { @@ -637,13 +643,18 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { } } + impl fmt::Display for StaticStrPayload { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } + } + let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message(); crate::sys_common::backtrace::__rust_end_short_backtrace(move || { if let Some(s) = msg.as_str() { rust_panic_with_hook( &mut StaticStrPayload(s), - Some(msg), loc, info.can_unwind(), info.force_no_backtrace(), @@ -651,7 +662,6 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { } else { rust_panic_with_hook( &mut FormatStringPayload { inner: &msg, string: None }, - Some(msg), loc, info.can_unwind(), info.force_no_backtrace(), @@ -681,7 +691,6 @@ pub const fn begin_panic(msg: M) -> ! { return crate::sys_common::backtrace::__rust_end_short_backtrace(move || { rust_panic_with_hook( &mut Payload::new(msg), - None, loc, /* can_unwind */ true, /* force_no_backtrace */ false, @@ -719,6 +728,15 @@ pub const fn begin_panic(msg: M) -> ! { } } } + + impl fmt::Display for Payload { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.inner { + Some(a) => f.write_str(payload_as_str(a)), + None => process::abort(), + } + } + } } fn payload_as_str(payload: &dyn Any) -> &str { @@ -738,7 +756,6 @@ fn payload_as_str(payload: &dyn Any) -> &str { /// abort or unwind. fn rust_panic_with_hook( payload: &mut dyn PanicPayload, - message: Option>, location: &Location<'_>, can_unwind: bool, force_no_backtrace: bool, @@ -765,11 +782,7 @@ fn rust_panic_with_hook( panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating // a `Backtrace` will allocate, which we must avoid here. - if let Some(message) = message { - rtprintpanic!("aborting due to panic at {location}:\n{message}\n"); - } else { - rtprintpanic!("aborting due to panic at {location}\n"); - } + rtprintpanic!("aborting due to panic at {location}:\n{payload}\n"); } } crate::sys::abort_internal(); @@ -825,6 +838,12 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { } } + impl fmt::Display for RewrapBox { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(payload_as_str(&self.0)) + } + } + rust_panic(&mut RewrapBox(payload)) }