@@ -165,12 +165,6 @@ fn default_hook(info: &PanicInfo) {
165165 #[ cfg( feature = "backtrace" ) ]
166166 use sys_common:: backtrace;
167167
168- // Some platforms know that printing to stderr won't ever actually print
169- // anything, and if that's the case we can skip everything below.
170- if stderr_prints_nothing ( ) {
171- return
172- }
173-
174168 // If this is a double panic, make sure that we print a backtrace
175169 // for this panic. Otherwise only print it if logging is enabled.
176170 #[ cfg( feature = "backtrace" ) ]
@@ -185,9 +179,6 @@ fn default_hook(info: &PanicInfo) {
185179 } ;
186180
187181 let location = info. location ( ) . unwrap ( ) ; // The current implementation always returns Some
188- let file = location. file ( ) ;
189- let line = location. line ( ) ;
190- let col = location. column ( ) ;
191182
192183 let msg = match info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
193184 Some ( s) => * s,
@@ -201,8 +192,8 @@ fn default_hook(info: &PanicInfo) {
201192 let name = thread. as_ref ( ) . and_then ( |t| t. name ( ) ) . unwrap_or ( "<unnamed>" ) ;
202193
203194 let write = |err : & mut :: io:: Write | {
204- let _ = writeln ! ( err, "thread '{}' panicked at '{}', {}:{}:{} " ,
205- name, msg, file , line , col ) ;
195+ let _ = writeln ! ( err, "thread '{}' panicked at '{}', {}" ,
196+ name, msg, location ) ;
206197
207198 #[ cfg( feature = "backtrace" ) ]
208199 {
@@ -350,9 +341,38 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
350341 // panic + OOM properly anyway (see comment in begin_panic
351342 // below).
352343
353- let mut s = String :: new ( ) ;
354- let _ = s. write_fmt ( * msg) ;
355- rust_panic_with_hook ( & mut PanicPayload :: new ( s) , Some ( msg) , file_line_col)
344+ rust_panic_with_hook ( & mut PanicPayload :: new ( msg) , Some ( msg) , file_line_col) ;
345+
346+ struct PanicPayload < ' a > {
347+ inner : & ' a fmt:: Arguments < ' a > ,
348+ string : Option < String > ,
349+ }
350+
351+ impl < ' a > PanicPayload < ' a > {
352+ fn new ( inner : & ' a fmt:: Arguments < ' a > ) -> PanicPayload < ' a > {
353+ PanicPayload { inner, string : None }
354+ }
355+
356+ fn fill ( & mut self ) -> & mut String {
357+ let inner = self . inner ;
358+ self . string . get_or_insert_with ( || {
359+ let mut s = String :: new ( ) ;
360+ drop ( s. write_fmt ( * inner) ) ;
361+ s
362+ } )
363+ }
364+ }
365+
366+ unsafe impl < ' a > BoxMeUp for PanicPayload < ' a > {
367+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
368+ let contents = mem:: replace ( self . fill ( ) , String :: new ( ) ) ;
369+ Box :: into_raw ( Box :: new ( contents) )
370+ }
371+
372+ fn get ( & mut self ) -> & ( Any + Send ) {
373+ self . fill ( )
374+ }
375+ }
356376}
357377
358378/// This is the entry point of panicking for panic!() and assert!().
@@ -368,42 +388,41 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
368388 // be performed in the parent of this thread instead of the thread that's
369389 // panicking.
370390
371- rust_panic_with_hook ( & mut PanicPayload :: new ( msg) , None , file_line_col)
372- }
373-
374- struct PanicPayload < A > {
375- inner : Option < A > ,
376- }
391+ rust_panic_with_hook ( & mut PanicPayload :: new ( msg) , None , file_line_col) ;
377392
378- impl < A : Send + ' static > PanicPayload < A > {
379- fn new ( inner : A ) -> PanicPayload < A > {
380- PanicPayload { inner : Some ( inner) }
393+ struct PanicPayload < A > {
394+ inner : Option < A > ,
381395 }
382- }
383396
384- unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
385- fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
386- let data = match self . inner . take ( ) {
387- Some ( a) => Box :: new ( a) as Box < Any + Send > ,
388- None => Box :: new ( ( ) ) ,
389- } ;
390- Box :: into_raw ( data)
397+ impl < A : Send + ' static > PanicPayload < A > {
398+ fn new ( inner : A ) -> PanicPayload < A > {
399+ PanicPayload { inner : Some ( inner) }
400+ }
391401 }
392402
393- fn get ( & self ) -> & ( Any + Send ) {
394- match self . inner {
395- Some ( ref a) => a,
396- None => & ( ) ,
403+ unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
404+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
405+ let data = match self . inner . take ( ) {
406+ Some ( a) => Box :: new ( a) as Box < Any + Send > ,
407+ None => Box :: new ( ( ) ) ,
408+ } ;
409+ Box :: into_raw ( data)
410+ }
411+
412+ fn get ( & mut self ) -> & ( Any + Send ) {
413+ match self . inner {
414+ Some ( ref a) => a,
415+ None => & ( ) ,
416+ }
397417 }
398418 }
399419}
400420
401- /// Executes the primary logic for a panic, including checking for recursive
402- /// panics and panic hooks.
421+ /// Central point for dispatching panics.
403422///
404- /// This is the entry point or panics from libcore, formatted panics, and
405- /// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
406- /// run panic hooks, and then delegate to the actual implementation of panics .
423+ /// Executes the primary logic for a panic, including checking for recursive
424+ /// panics, panic hooks, and finally dispatching to the panic runtime to either
425+ /// abort or unwind .
407426fn rust_panic_with_hook ( payload : & mut BoxMeUp ,
408427 message : Option < & fmt:: Arguments > ,
409428 file_line_col : & ( & ' static str , u32 , u32 ) ) -> ! {
@@ -423,15 +442,24 @@ fn rust_panic_with_hook(payload: &mut BoxMeUp,
423442 }
424443
425444 unsafe {
426- let info = PanicInfo :: internal_constructor (
427- payload. get ( ) ,
445+ let mut info = PanicInfo :: internal_constructor (
428446 message,
429447 Location :: internal_constructor ( file, line, col) ,
430448 ) ;
431449 HOOK_LOCK . read ( ) ;
432450 match HOOK {
433- Hook :: Default => default_hook ( & info) ,
434- Hook :: Custom ( ptr) => ( * ptr) ( & info) ,
451+ // Some platforms know that printing to stderr won't ever actually
452+ // print anything, and if that's the case we can skip the default
453+ // hook.
454+ Hook :: Default if stderr_prints_nothing ( ) => { }
455+ Hook :: Default => {
456+ info. set_payload ( payload. get ( ) ) ;
457+ default_hook ( & info) ;
458+ }
459+ Hook :: Custom ( ptr) => {
460+ info. set_payload ( payload. get ( ) ) ;
461+ ( * ptr) ( & info) ;
462+ }
435463 }
436464 HOOK_LOCK . read_unlock ( ) ;
437465 }
@@ -460,7 +488,7 @@ pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
460488 Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
461489 }
462490
463- fn get ( & self ) -> & ( Any + Send ) {
491+ fn get ( & mut self ) -> & ( Any + Send ) {
464492 & * self . 0
465493 }
466494 }
0 commit comments