@@ -20,6 +20,7 @@ use crate::sys_common::rwlock::RWLock;
2020use crate :: sys_common:: { thread_info, util} ;
2121use crate :: sys_common:: backtrace:: { self , RustBacktrace } ;
2222use crate :: thread;
23+ use crate :: process;
2324
2425#[ cfg( not( test) ) ]
2526use crate :: io:: set_panic;
@@ -46,6 +47,8 @@ extern {
4647 vtable_ptr : * mut usize ) -> u32 ;
4748
4849 /// `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`.
4952 #[ unwind( allowed) ]
5053 fn __rust_start_panic ( payload : usize ) -> u32 ;
5154}
@@ -296,14 +299,6 @@ pub fn panicking() -> bool {
296299 update_panic_count ( 0 ) != 0
297300}
298301
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-
307302/// The entry point for panicking with a formatted message.
308303///
309304/// 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<'_>,
324319 unsafe { intrinsics:: abort ( ) }
325320 }
326321
322+ // Just package everything into a `PanicInfo` and continue like libcore panics.
327323 let ( file, line, col) = * file_line_col;
328324 let location = Location :: internal_constructor ( file, line, col) ;
329325 let info = PanicInfo :: internal_constructor ( Some ( msg) , & location) ;
330- continue_panic_fmt ( & info)
326+ begin_panic_handler ( & info)
331327}
332328
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 < ' _ > ) -> ! {
334333 struct PanicPayload < ' a > {
335334 inner : & ' a fmt:: Arguments < ' a > ,
336335 string : Option < String > ,
@@ -345,6 +344,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
345344 use crate :: fmt:: Write ;
346345
347346 let inner = self . inner ;
347+ // Lazily, the first time this gets called, run the actual string formatting.
348348 self . string . get_or_insert_with ( || {
349349 let mut s = String :: new ( ) ;
350350 drop ( s. write_fmt ( * inner) ) ;
@@ -354,7 +354,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
354354 }
355355
356356 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 ) {
358358 let contents = mem:: take ( self . fill ( ) ) ;
359359 Box :: into_raw ( Box :: new ( contents) )
360360 }
@@ -378,7 +378,9 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
378378 & file_line_col) ;
379379}
380380
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.
382384#[ unstable( feature = "libstd_sys_internals" ,
383385 reason = "used by the panic! macro" ,
384386 issue = "0" ) ]
@@ -412,18 +414,18 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
412414 }
413415
414416 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 ) {
416418 let data = match self . inner . take ( ) {
417419 Some ( a) => Box :: new ( a) as Box < dyn Any + Send > ,
418- None => Box :: new ( ( ) ) ,
420+ None => process :: abort ( ) ,
419421 } ;
420422 Box :: into_raw ( data)
421423 }
422424
423425 fn get ( & mut self ) -> & ( dyn Any + Send ) {
424426 match self . inner {
425427 Some ( ref a) => a,
426- None => & ( ) ,
428+ None => process :: abort ( ) ,
427429 }
428430 }
429431 }
@@ -457,9 +459,12 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
457459 let mut info = PanicInfo :: internal_constructor ( message, & location) ;
458460 HOOK_LOCK . read ( ) ;
459461 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
461463 // 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.)
463468 Hook :: Default if panic_output ( ) . is_none ( ) => { }
464469 Hook :: Default => {
465470 info. set_payload ( payload. get ( ) ) ;
@@ -486,14 +491,15 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
486491 rust_panic ( payload)
487492}
488493
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 > ) -> ! {
491497 update_panic_count ( 1 ) ;
492498
493499 struct RewrapBox ( Box < dyn Any + Send > ) ;
494500
495501 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 ) {
497503 Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
498504 }
499505
@@ -502,7 +508,7 @@ pub fn update_count_then_panic(msg: Box<dyn Any + Send>) -> ! {
502508 }
503509 }
504510
505- rust_panic ( & mut RewrapBox ( msg ) )
511+ rust_panic ( & mut RewrapBox ( payload ) )
506512}
507513
508514/// An unmangled function (through `rustc_std_internal_symbol`) on which to slap
0 commit comments