Skip to content

Commit ca458ba

Browse files
committed
Add PanicMessage type for PanicInfo::message().
1 parent 8cd20cb commit ca458ba

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

core/src/panic.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use crate::any::Any;
1212
pub use self::location::Location;
1313
#[stable(feature = "panic_hooks", since = "1.10.0")]
1414
pub use self::panic_info::PanicInfo;
15+
#[unstable(feature = "panic_info_message", issue = "66745")]
16+
pub use self::panic_info::PanicMessage;
1517
#[stable(feature = "catch_unwind", since = "1.9.0")]
1618
pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
1719

core/src/panic/panic_info.rs

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::fmt;
1+
use crate::fmt::{self, Display};
22
use crate::panic::Location;
33

44
/// A struct providing information about a panic.
@@ -18,6 +18,17 @@ pub struct PanicInfo<'a> {
1818
force_no_backtrace: bool,
1919
}
2020

21+
/// A message that was given to the `panic!()` macro.
22+
///
23+
/// The [`Display`] implementation of this type will format the message with the arguments
24+
/// that were given to the `panic!()` macro.
25+
///
26+
/// See [`PanicInfo::message`].
27+
#[unstable(feature = "panic_info_message", issue = "66745")]
28+
pub struct PanicMessage<'a> {
29+
message: fmt::Arguments<'a>,
30+
}
31+
2132
impl<'a> PanicInfo<'a> {
2233
#[inline]
2334
pub(crate) fn new(
@@ -29,12 +40,26 @@ impl<'a> PanicInfo<'a> {
2940
PanicInfo { location, message, can_unwind, force_no_backtrace }
3041
}
3142

32-
/// The message that was given to the `panic!` macro,
33-
/// ready to be formatted with e.g. [`fmt::write`].
43+
/// The message that was given to the `panic!` macro.
44+
///
45+
/// # Example
46+
///
47+
/// The type returned by this method implements `Display`, so it can
48+
/// be passed directly to [`write!()`] and similar macros.
49+
///
50+
/// [`write!()`]: core::write
51+
///
52+
/// ```ignore (no_std)
53+
/// #[panic_handler]
54+
/// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! {
55+
/// write!(DEBUG_OUTPUT, "panicked: {}", panic_info.message());
56+
/// loop {}
57+
/// }
58+
/// ```
3459
#[must_use]
3560
#[unstable(feature = "panic_info_message", issue = "66745")]
36-
pub fn message(&self) -> fmt::Arguments<'_> {
37-
self.message
61+
pub fn message(&self) -> PanicMessage<'_> {
62+
PanicMessage { message: self.message }
3863
}
3964

4065
/// Returns information about the location from which the panic originated,
@@ -116,7 +141,7 @@ impl<'a> PanicInfo<'a> {
116141
}
117142

118143
#[stable(feature = "panic_hook_display", since = "1.26.0")]
119-
impl fmt::Display for PanicInfo<'_> {
144+
impl Display for PanicInfo<'_> {
120145
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
121146
formatter.write_str("panicked at ")?;
122147
self.location.fmt(formatter)?;
@@ -125,3 +150,41 @@ impl fmt::Display for PanicInfo<'_> {
125150
Ok(())
126151
}
127152
}
153+
154+
impl<'a> PanicMessage<'a> {
155+
/// Get the formatted message, if it has no arguments to be formatted at runtime.
156+
///
157+
/// This can be used to avoid allocations in some cases.
158+
///
159+
/// # Guarantees
160+
///
161+
/// For `panic!("just a literal")`, this function is guaranteed to
162+
/// return `Some("just a literal")`.
163+
///
164+
/// For most cases with placeholders, this function will return `None`.
165+
///
166+
/// See [`fmt::Arguments::as_str`] for details.
167+
#[unstable(feature = "panic_info_message", issue = "66745")]
168+
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
169+
#[must_use]
170+
#[inline]
171+
pub const fn as_str(&self) -> Option<&'static str> {
172+
self.message.as_str()
173+
}
174+
}
175+
176+
#[unstable(feature = "panic_info_message", issue = "66745")]
177+
impl Display for PanicMessage<'_> {
178+
#[inline]
179+
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
180+
formatter.write_fmt(self.message)
181+
}
182+
}
183+
184+
#[unstable(feature = "panic_info_message", issue = "66745")]
185+
impl fmt::Debug for PanicMessage<'_> {
186+
#[inline]
187+
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
188+
formatter.write_fmt(self.message)
189+
}
190+
}

std/src/panicking.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -593,19 +593,18 @@ pub fn panicking() -> bool {
593593
#[panic_handler]
594594
pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
595595
struct FormatStringPayload<'a> {
596-
inner: &'a fmt::Arguments<'a>,
596+
inner: &'a core::panic::PanicMessage<'a>,
597597
string: Option<String>,
598598
}
599599

600600
impl FormatStringPayload<'_> {
601601
fn fill(&mut self) -> &mut String {
602-
use crate::fmt::Write;
603-
604602
let inner = self.inner;
605603
// Lazily, the first time this gets called, run the actual string formatting.
606604
self.string.get_or_insert_with(|| {
607605
let mut s = String::new();
608-
let _err = s.write_fmt(*inner);
606+
let mut fmt = fmt::Formatter::new(&mut s);
607+
let _err = fmt::Display::fmt(&inner, &mut fmt);
609608
s
610609
})
611610
}
@@ -627,7 +626,11 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
627626

628627
impl fmt::Display for FormatStringPayload<'_> {
629628
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
630-
if let Some(s) = &self.string { f.write_str(s) } else { f.write_fmt(*self.inner) }
629+
if let Some(s) = &self.string {
630+
f.write_str(s)
631+
} else {
632+
fmt::Display::fmt(&self.inner, f)
633+
}
631634
}
632635
}
633636

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy