Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 13a31b6

Browse files
committedJun 18, 2024
Auto merge of rust-lang#126330 - m-ou-se:panic-message-type, r=Amanieu
Return opaque type from PanicInfo::message() This changes the return type of the (unstable) PanicInfo::message() method to an opaque type (that implements Display). This allows for a bit more flexibility in the future. See rust-lang#66745
2 parents 2238945 + ca458ba commit 13a31b6

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed
 

‎core/src/panic.rs

+2
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

+69-6
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

+8-5
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)
Failed to load comments.