1- use crate :: fmt;
1+ use crate :: fmt:: { self , Display } ;
22use 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+
2132impl < ' 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+ }
0 commit comments