12
12
//! consistent way - `From` conversion behavior is never specified
13
13
//! explicitly.
14
14
//! * Errors implement Send.
15
- //! * Errors carry backtraces.
15
+ //! * Errors can carry backtraces.
16
16
//!
17
17
//! Similar to other libraries like [error-type] and [quick-error], this
18
18
//! library defines a macro, `error_chain!` that declares the types
40
40
//! errors.
41
41
//! * It provides automatic `From` conversions between any other error
42
42
//! type that hides the type of the other error in the `cause` box.
43
- //! * It collects a single backtrace at the earliest opportunity and
44
- //! propagates it down the stack through `From` and `ChainErr`
45
- //! conversions.
43
+ //! * If `RUST_BACKTRACE` is enabled, it collects a single backtrace at
44
+ //! the earliest opportunity and propagates it down the stack through
45
+ //! `From` and `ChainErr` conversions.
46
46
//!
47
47
//! To accomplish its goals it makes some tradeoffs:
48
48
//!
175
175
//! #[derive(Debug)]
176
176
//! pub struct Error(pub ErrorKind,
177
177
//! pub Option<Box<StdError + Send>>,
178
- //! pub Arc<error_chain::Backtrace>);
178
+ //! pub Option< Arc<error_chain::Backtrace> >);
179
179
//!
180
180
//! impl Error {
181
181
//! pub fn kind(&self) -> &ErrorKind { ... }
182
182
//! pub fn into_kind(self) -> ErrorKind { ... }
183
183
//! pub fn iter(&self) -> error_chain::ErrorChainIter { ... }
184
- //! pub fn backtrace(&self) -> &error_chain::Backtrace { ... }
184
+ //! pub fn backtrace(&self) -> Option< &error_chain::Backtrace> { ... }
185
185
//! }
186
186
//!
187
187
//! impl StdError for Error { ... }
293
293
//!
294
294
//! ## Backtraces
295
295
//!
296
- //! The earliest non-foreign error to be generated creates a single
297
- //! backtrace, which is passed through all `From` conversions and
298
- //! `chain_err` invocations of compatible types. To read the backtrace
299
- //! just call the `backtrace()` method.
296
+ //! If the `RUST_BACKTRACE` environment variable is set to anything
297
+ //! but ``0``, the earliest non-foreign error to be generated creates
298
+ //! a single backtrace, which is passed through all `From` conversions
299
+ //! and `chain_err` invocations of compatible types. To read the
300
+ //! backtrace just call the `backtrace()` method.
300
301
//!
301
302
//! ## Iteration
302
303
//!
@@ -343,7 +344,7 @@ macro_rules! error_chain {
343
344
#[ derive( Debug ) ]
344
345
pub struct $error_name( pub $error_kind_name,
345
346
pub ( Option <Box <:: std:: error:: Error + Send >>,
346
- :: std:: sync:: Arc <$crate:: Backtrace >) ) ;
347
+ Option < :: std:: sync:: Arc <$crate:: Backtrace > >) ) ;
347
348
348
349
#[ allow( unused) ]
349
350
impl $error_name {
@@ -359,8 +360,8 @@ macro_rules! error_chain {
359
360
$crate:: ErrorChainIter ( Some ( self ) )
360
361
}
361
362
362
- pub fn backtrace( & self ) -> & $crate:: Backtrace {
363
- & ( self . 1 ) . 1
363
+ pub fn backtrace( & self ) -> Option < & $crate:: Backtrace > {
364
+ ( self . 1 ) . 1 . as_ref ( ) . map ( |v| & * * v )
364
365
}
365
366
}
366
367
@@ -402,29 +403,29 @@ macro_rules! error_chain {
402
403
fn from( e: $foreign_link_error_path) -> Self {
403
404
$error_name(
404
405
$error_kind_name:: $foreign_link_variant( e) ,
405
- ( None , :: std :: sync :: Arc :: new ( $crate:: Backtrace :: new ( ) ) ) )
406
+ ( None , $crate:: make_backtrace ( ) ) )
406
407
}
407
408
}
408
409
) *
409
410
410
411
impl From <$error_kind_name> for $error_name {
411
412
fn from( e: $error_kind_name) -> Self {
412
413
$error_name( e,
413
- ( None , :: std :: sync :: Arc :: new ( $crate:: Backtrace :: new ( ) ) ) )
414
+ ( None , $crate:: make_backtrace ( ) ) )
414
415
}
415
416
}
416
417
417
418
impl <' a> From <& ' a str > for $error_name {
418
419
fn from( s: & ' a str ) -> Self {
419
420
$error_name( s. into( ) ,
420
- ( None , :: std :: sync :: Arc :: new ( $crate:: Backtrace :: new ( ) ) ) )
421
+ ( None , $crate:: make_backtrace ( ) ) )
421
422
}
422
423
}
423
424
424
425
impl From <String > for $error_name {
425
426
fn from( s: String ) -> Self {
426
427
$error_name( s. into( ) ,
427
- ( None , :: std :: sync :: Arc :: new ( $crate:: Backtrace :: new ( ) ) ) )
428
+ ( None , $crate:: make_backtrace ( ) ) )
428
429
}
429
430
}
430
431
@@ -500,7 +501,7 @@ macro_rules! error_chain {
500
501
let e = Box :: new( e) as Box <:: std:: error:: Error + Send + ' static >;
501
502
let ( e, backtrace) = backtrace_from_box( e) ;
502
503
let backtrace = backtrace. unwrap_or_else(
503
- || :: std :: sync :: Arc :: new ( $crate:: Backtrace :: new ( ) ) ) ;
504
+ || $crate:: make_backtrace ( ) ) ;
504
505
505
506
$error_name( callback( ) . into( ) , ( Some ( e) , backtrace) )
506
507
} )
@@ -513,7 +514,7 @@ macro_rules! error_chain {
513
514
// machinery to make it work.
514
515
fn backtrace_from_box( mut e: Box <:: std:: error:: Error + Send + ' static >)
515
516
-> ( Box <:: std:: error:: Error + Send + ' static >,
516
- Option <:: std:: sync:: Arc <$crate:: Backtrace >>) {
517
+ Option <Option < :: std:: sync:: Arc <$crate:: Backtrace > >>) {
517
518
let mut backtrace = None ;
518
519
519
520
e = match e. downcast:: <$error_name>( ) {
@@ -657,6 +658,7 @@ macro_rules! error_chain {
657
658
658
659
use std:: error:: Error as StdError ;
659
660
use std:: iter:: Iterator ;
661
+ use std:: sync:: Arc ;
660
662
661
663
pub struct ErrorChainIter < ' a > ( pub Option < & ' a StdError > ) ;
662
664
@@ -673,3 +675,13 @@ impl<'a> Iterator for ErrorChainIter<'a> {
673
675
}
674
676
}
675
677
}
678
+
679
+ /// Returns a backtrace of the current call stack if `RUST_BACKTRACE`
680
+ /// is set to anything but ``0``, and `None` otherwise. This is used
681
+ /// in the generated error implementations.
682
+ pub fn make_backtrace ( ) -> Option < Arc < Backtrace > > {
683
+ match std:: env:: var_os ( "RUST_BACKTRACE" ) {
684
+ Some ( ref val) if val != "0" => Some ( Arc :: new ( Backtrace :: new ( ) ) ) ,
685
+ _ => None
686
+ }
687
+ }
0 commit comments