@@ -165,12 +165,6 @@ fn default_hook(info: &PanicInfo) {
165
165
#[ cfg( feature = "backtrace" ) ]
166
166
use sys_common:: backtrace;
167
167
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
-
174
168
// If this is a double panic, make sure that we print a backtrace
175
169
// for this panic. Otherwise only print it if logging is enabled.
176
170
#[ cfg( feature = "backtrace" ) ]
@@ -185,9 +179,6 @@ fn default_hook(info: &PanicInfo) {
185
179
} ;
186
180
187
181
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 ( ) ;
191
182
192
183
let msg = match info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
193
184
Some ( s) => * s,
@@ -201,8 +192,8 @@ fn default_hook(info: &PanicInfo) {
201
192
let name = thread. as_ref ( ) . and_then ( |t| t. name ( ) ) . unwrap_or ( "<unnamed>" ) ;
202
193
203
194
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 ) ;
206
197
207
198
#[ cfg( feature = "backtrace" ) ]
208
199
{
@@ -350,9 +341,38 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
350
341
// panic + OOM properly anyway (see comment in begin_panic
351
342
// below).
352
343
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
+ }
356
376
}
357
377
358
378
/// 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
368
388
// be performed in the parent of this thread instead of the thread that's
369
389
// panicking.
370
390
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) ;
377
392
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 > ,
381
395
}
382
- }
383
396
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
+ }
391
401
}
392
402
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
+ }
397
417
}
398
418
}
399
419
}
400
420
401
- /// Executes the primary logic for a panic, including checking for recursive
402
- /// panics and panic hooks.
421
+ /// Central point for dispatching panics.
403
422
///
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 .
407
426
fn rust_panic_with_hook ( payload : & mut BoxMeUp ,
408
427
message : Option < & fmt:: Arguments > ,
409
428
file_line_col : & ( & ' static str , u32 , u32 ) ) -> ! {
@@ -423,15 +442,24 @@ fn rust_panic_with_hook(payload: &mut BoxMeUp,
423
442
}
424
443
425
444
unsafe {
426
- let info = PanicInfo :: internal_constructor (
427
- payload. get ( ) ,
445
+ let mut info = PanicInfo :: internal_constructor (
428
446
message,
429
447
Location :: internal_constructor ( file, line, col) ,
430
448
) ;
431
449
HOOK_LOCK . read ( ) ;
432
450
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
+ }
435
463
}
436
464
HOOK_LOCK . read_unlock ( ) ;
437
465
}
@@ -460,7 +488,7 @@ pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
460
488
Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
461
489
}
462
490
463
- fn get ( & self ) -> & ( Any + Send ) {
491
+ fn get ( & mut self ) -> & ( Any + Send ) {
464
492
& * self . 0
465
493
}
466
494
}
0 commit comments