@@ -20,6 +20,7 @@ use crate::sys_common::rwlock::RWLock;
20
20
use crate :: sys_common:: { thread_info, util} ;
21
21
use crate :: sys_common:: backtrace:: { self , RustBacktrace } ;
22
22
use crate :: thread;
23
+ use crate :: process;
23
24
24
25
#[ cfg( not( test) ) ]
25
26
use crate :: io:: set_panic;
@@ -46,6 +47,8 @@ extern {
46
47
vtable_ptr : * mut usize ) -> u32 ;
47
48
48
49
/// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
50
+ /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
51
+ /// on liballoc, and thus cannot use `Box`.
49
52
#[ unwind( allowed) ]
50
53
fn __rust_start_panic ( payload : usize ) -> u32 ;
51
54
}
@@ -296,14 +299,6 @@ pub fn panicking() -> bool {
296
299
update_panic_count ( 0 ) != 0
297
300
}
298
301
299
- /// Entry point of panic from the libcore crate (`panic_impl` lang item).
300
- #[ cfg( not( test) ) ]
301
- #[ panic_handler]
302
- #[ unwind( allowed) ]
303
- pub fn rust_begin_panic ( info : & PanicInfo < ' _ > ) -> ! {
304
- continue_panic_fmt ( & info)
305
- }
306
-
307
302
/// The entry point for panicking with a formatted message.
308
303
///
309
304
/// This is designed to reduce the amount of code required at the call
@@ -324,13 +319,17 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>,
324
319
unsafe { intrinsics:: abort ( ) }
325
320
}
326
321
322
+ // Just package everything into a `PanicInfo` and continue like libcore panics.
327
323
let ( file, line, col) = * file_line_col;
328
324
let location = Location :: internal_constructor ( file, line, col) ;
329
325
let info = PanicInfo :: internal_constructor ( Some ( msg) , & location) ;
330
- continue_panic_fmt ( & info)
326
+ begin_panic_handler ( & info)
331
327
}
332
328
333
- fn continue_panic_fmt ( info : & PanicInfo < ' _ > ) -> ! {
329
+ /// Entry point of panics from the libcore crate (`panic_impl` lang item).
330
+ #[ cfg_attr( not( test) , panic_handler) ]
331
+ #[ unwind( allowed) ]
332
+ pub fn begin_panic_handler ( info : & PanicInfo < ' _ > ) -> ! {
334
333
struct PanicPayload < ' a > {
335
334
inner : & ' a fmt:: Arguments < ' a > ,
336
335
string : Option < String > ,
@@ -345,6 +344,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
345
344
use crate :: fmt:: Write ;
346
345
347
346
let inner = self . inner ;
347
+ // Lazily, the first time this gets called, run the actual string formatting.
348
348
self . string . get_or_insert_with ( || {
349
349
let mut s = String :: new ( ) ;
350
350
drop ( s. write_fmt ( * inner) ) ;
@@ -354,7 +354,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
354
354
}
355
355
356
356
unsafe impl < ' a > BoxMeUp for PanicPayload < ' a > {
357
- fn box_me_up ( & mut self ) -> * mut ( dyn Any + Send ) {
357
+ fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
358
358
let contents = mem:: take ( self . fill ( ) ) ;
359
359
Box :: into_raw ( Box :: new ( contents) )
360
360
}
@@ -378,7 +378,9 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
378
378
& file_line_col) ;
379
379
}
380
380
381
- /// This is the entry point of panicking for panic!() and assert!().
381
+ /// This is the entry point of panicking for the non-format-string variants of
382
+ /// panic!() and assert!(). In particular, this is the only entry point that supports
383
+ /// arbitrary payloads, not just format strings.
382
384
#[ unstable( feature = "libstd_sys_internals" ,
383
385
reason = "used by the panic! macro" ,
384
386
issue = "0" ) ]
@@ -412,18 +414,18 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
412
414
}
413
415
414
416
unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
415
- fn box_me_up ( & mut self ) -> * mut ( dyn Any + Send ) {
417
+ fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
416
418
let data = match self . inner . take ( ) {
417
419
Some ( a) => Box :: new ( a) as Box < dyn Any + Send > ,
418
- None => Box :: new ( ( ) ) ,
420
+ None => process :: abort ( ) ,
419
421
} ;
420
422
Box :: into_raw ( data)
421
423
}
422
424
423
425
fn get ( & mut self ) -> & ( dyn Any + Send ) {
424
426
match self . inner {
425
427
Some ( ref a) => a,
426
- None => & ( ) ,
428
+ None => process :: abort ( ) ,
427
429
}
428
430
}
429
431
}
@@ -457,9 +459,12 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
457
459
let mut info = PanicInfo :: internal_constructor ( message, & location) ;
458
460
HOOK_LOCK . read ( ) ;
459
461
match HOOK {
460
- // Some platforms know that printing to stderr won't ever actually
462
+ // Some platforms (like wasm) know that printing to stderr won't ever actually
461
463
// print anything, and if that's the case we can skip the default
462
- // hook.
464
+ // hook. Since string formatting happens lazily when calling `payload`
465
+ // methods, this means we avoid formatting the string at all!
466
+ // (The panic runtime might still call `payload.take_box()` though and trigger
467
+ // formatting.)
463
468
Hook :: Default if panic_output ( ) . is_none ( ) => { }
464
469
Hook :: Default => {
465
470
info. set_payload ( payload. get ( ) ) ;
@@ -486,14 +491,15 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
486
491
rust_panic ( payload)
487
492
}
488
493
489
- /// Shim around rust_panic. Called by resume_unwind.
490
- pub fn update_count_then_panic ( msg : Box < dyn Any + Send > ) -> ! {
494
+ /// This is the entry point for `resume_unwind`.
495
+ /// It just forwards the payload to the panic runtime.
496
+ pub fn rust_panic_without_hook ( payload : Box < dyn Any + Send > ) -> ! {
491
497
update_panic_count ( 1 ) ;
492
498
493
499
struct RewrapBox ( Box < dyn Any + Send > ) ;
494
500
495
501
unsafe impl BoxMeUp for RewrapBox {
496
- fn box_me_up ( & mut self ) -> * mut ( dyn Any + Send ) {
502
+ fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
497
503
Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
498
504
}
499
505
@@ -502,7 +508,7 @@ pub fn update_count_then_panic(msg: Box<dyn Any + Send>) -> ! {
502
508
}
503
509
}
504
510
505
- rust_panic ( & mut RewrapBox ( msg ) )
511
+ rust_panic ( & mut RewrapBox ( payload ) )
506
512
}
507
513
508
514
/// An unmangled function (through `rustc_std_internal_symbol`) on which to slap
0 commit comments