@@ -248,19 +248,24 @@ fn default_hook(info: &PanicInfo<'_>) {
248
248
249
249
// The current implementation always returns `Some`.
250
250
let location = info. location ( ) . unwrap ( ) ;
251
-
252
- let msg = match info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
253
- Some ( s) => * s,
254
- None => match info. payload ( ) . downcast_ref :: < String > ( ) {
255
- Some ( s) => & s[ ..] ,
256
- None => "Box<dyn Any>" ,
257
- } ,
258
- } ;
259
251
let thread = thread_info:: current_thread ( ) ;
260
252
let name = thread. as_ref ( ) . and_then ( |t| t. name ( ) ) . unwrap_or ( "<unnamed>" ) ;
261
253
262
254
let write = |err : & mut dyn crate :: io:: Write | {
263
- let _ = writeln ! ( err, "thread '{name}' panicked at {location}:\n {msg}" ) ;
255
+ // Use the panic message directly if available, otherwise take it from
256
+ // the payload.
257
+ if let Some ( msg) = info. message ( ) {
258
+ let _ = writeln ! ( err, "thread '{name}' panicked at {location}:\n {msg}" ) ;
259
+ } else {
260
+ let msg = if let Some ( s) = info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
261
+ * s
262
+ } else if let Some ( s) = info. payload ( ) . downcast_ref :: < String > ( ) {
263
+ & s[ ..]
264
+ } else {
265
+ "Box<dyn Any>"
266
+ } ;
267
+ let _ = writeln ! ( err, "thread '{name}' panicked at {location}:\n {msg}" ) ;
268
+ }
264
269
265
270
static FIRST_PANIC : AtomicBool = AtomicBool :: new ( true ) ;
266
271
@@ -543,6 +548,8 @@ pub fn panicking() -> bool {
543
548
#[ cfg( not( test) ) ]
544
549
#[ panic_handler]
545
550
pub fn begin_panic_handler ( info : & PanicInfo < ' _ > ) -> ! {
551
+ use alloc:: alloc:: AllocErrorPanicPayload ;
552
+
546
553
struct FormatStringPayload < ' a > {
547
554
inner : & ' a fmt:: Arguments < ' a > ,
548
555
string : Option < String > ,
@@ -569,8 +576,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
569
576
unsafe impl < ' a > PanicPayload for FormatStringPayload < ' a > {
570
577
fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
571
578
// We do two allocations here, unfortunately. But (a) they're required with the current
572
- // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in
573
- // begin_panic below).
579
+ // scheme, and (b) OOM uses its own separate payload type which doesn't allocate.
574
580
let contents = mem:: take ( self . fill ( ) ) ;
575
581
Box :: into_raw ( Box :: new ( contents) )
576
582
}
@@ -595,9 +601,17 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
595
601
let loc = info. location ( ) . unwrap ( ) ; // The current implementation always returns Some
596
602
let msg = info. message ( ) . unwrap ( ) ; // The current implementation always returns Some
597
603
crate :: sys_common:: backtrace:: __rust_end_short_backtrace ( move || {
598
- // FIXME: can we just pass `info` along rather than taking it apart here, only to have
599
- // `rust_panic_with_hook` construct a new `PanicInfo`?
600
- if let Some ( msg) = msg. as_str ( ) {
604
+ if let Some ( payload) = info. payload ( ) . downcast_ref :: < AllocErrorPanicPayload > ( ) {
605
+ rust_panic_with_hook (
606
+ & mut payload. internal_clone ( ) ,
607
+ info. message ( ) ,
608
+ loc,
609
+ info. can_unwind ( ) ,
610
+ info. force_no_backtrace ( ) ,
611
+ ) ;
612
+ } else if let Some ( msg) = msg. as_str ( ) {
613
+ // FIXME: can we just pass `info` along rather than taking it apart here, only to have
614
+ // `rust_panic_with_hook` construct a new `PanicInfo`?
601
615
rust_panic_with_hook (
602
616
& mut StaticStrPayload ( msg) ,
603
617
info. message ( ) ,
@@ -657,11 +671,7 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
657
671
658
672
unsafe impl < A : Send + ' static > PanicPayload for Payload < A > {
659
673
fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
660
- // Note that this should be the only allocation performed in this code path. Currently
661
- // this means that panic!() on OOM will invoke this code path, but then again we're not
662
- // really ready for panic on OOM anyway. If we do start doing this, then we should
663
- // propagate this allocation to be performed in the parent of this thread instead of the
664
- // thread that's panicking.
674
+ // Note that this should be the only allocation performed in this code path.
665
675
let data = match self . inner . take ( ) {
666
676
Some ( a) => Box :: new ( a) as Box < dyn Any + Send > ,
667
677
None => process:: abort ( ) ,
0 commit comments