Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit abc3d1a

Browse files
committed
Better backtrace feature.
1 parent 1455999 commit abc3d1a

File tree

1 file changed

+98
-44
lines changed

1 file changed

+98
-44
lines changed

src/lib.rs

Lines changed: 98 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,11 @@ extern crate backtrace;
320320

321321
use std::error;
322322
use std::iter::Iterator;
323+
#[cfg(feature = "backtrace")]
323324
use std::sync::Arc;
324325

325326
#[cfg(feature = "backtrace")]
326327
pub use backtrace::Backtrace;
327-
#[cfg(not(feature = "backtrace"))]
328-
#[derive(Debug)]
329-
pub enum Backtrace {}
330328

331329
mod quick_error;
332330

@@ -361,6 +359,8 @@ macro_rules! error_chain {
361359
pub struct $error_name(pub $error_kind_name,
362360
pub $crate::State);
363361

362+
impl_error!($error_name $error_kind_name $($link_error_path)*);
363+
364364
impl $error_name {
365365
/// Returns the kind of the error.
366366
pub fn kind(&self) -> &$error_kind_name {
@@ -371,11 +371,6 @@ macro_rules! error_chain {
371371
pub fn iter(&self) -> $crate::ErrorChainIter {
372372
$crate::ErrorChainIter(Some(self))
373373
}
374-
375-
/// Returns the backtrace associated with this error.
376-
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
377-
self.1.backtrace.as_ref().map(|v| &**v)
378-
}
379374
}
380375

381376
impl ::std::error::Error for $error_name {
@@ -511,29 +506,6 @@ macro_rules! error_chain {
511506
}
512507
}
513508

514-
impl $crate::ChainedError for $error_name {
515-
type ErrorKind = $error_kind_name;
516-
517-
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
518-
$error_name(kind, state)
519-
}
520-
521-
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
522-
-> Option<Option<::std::sync::Arc<$crate::Backtrace>>> {
523-
if let Some(e) = e.downcast_ref::<$error_name>() {
524-
Some(e.1.backtrace.clone())
525-
}
526-
$(
527-
else if let Some(e) = e.downcast_ref::<$link_error_path>() {
528-
Some(e.1.backtrace.clone())
529-
}
530-
) *
531-
else {
532-
None
533-
}
534-
}
535-
}
536-
537509
// The Result type
538510
// ---------------
539511

@@ -649,6 +621,72 @@ macro_rules! error_chain {
649621
);
650622
}
651623

624+
/// Macro used to manage the `backtrace` feature.
625+
///
626+
/// See
627+
/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
628+
/// for more details.
629+
#[macro_export]
630+
#[doc(hidden)]
631+
#[cfg(feature = "backtrace")]
632+
macro_rules! impl_error {
633+
($error_name: ident
634+
$error_kind_name: ident
635+
$($link_error_path: path)*) => {
636+
impl $error_name {
637+
/// Returns the backtrace associated with this error.
638+
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
639+
self.1.backtrace.as_ref().map(|v| &**v)
640+
}
641+
}
642+
643+
impl $crate::ChainedError for $error_name {
644+
type ErrorKind = $error_kind_name;
645+
646+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
647+
$error_name(kind, state)
648+
}
649+
650+
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
651+
-> Option<Option<::std::sync::Arc<$crate::Backtrace>>> {
652+
if let Some(e) = e.downcast_ref::<$error_name>() {
653+
Some(e.1.backtrace.clone())
654+
}
655+
$(
656+
else if let Some(e) = e.downcast_ref::<$link_error_path>() {
657+
Some(e.1.backtrace.clone())
658+
}
659+
) *
660+
else {
661+
None
662+
}
663+
}
664+
}
665+
}
666+
}
667+
668+
/// Macro used to manage the `backtrace` feature.
669+
///
670+
/// See
671+
/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
672+
/// for more details.
673+
#[macro_export]
674+
#[doc(hidden)]
675+
#[cfg(not(feature = "backtrace"))]
676+
macro_rules! impl_error {
677+
($error_name: ident
678+
$error_kind_name: ident
679+
$($link_error_path: path)*) => {
680+
impl $crate::ChainedError for $error_name {
681+
type ErrorKind = $error_kind_name;
682+
683+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
684+
$error_name(kind, state)
685+
}
686+
}
687+
}
688+
}
689+
652690
/// Iterator over the error chain.
653691
pub struct ErrorChainIter<'a>(pub Option<&'a error::Error>);
654692

@@ -678,12 +716,6 @@ pub fn make_backtrace() -> Option<Arc<Backtrace>> {
678716
}
679717
}
680718

681-
#[cfg(not(feature = "backtrace"))]
682-
#[doc(hidden)]
683-
pub fn make_backtrace() -> Option<Arc<Backtrace>> {
684-
None
685-
}
686-
687719
/// This trait is an implementation detail which must be implemented on each
688720
/// ErrorKind. We can't do it globally since each ErrorKind is different.
689721
pub trait ChainedError: error::Error + Send + 'static {
@@ -695,6 +727,7 @@ pub trait ChainedError: error::Error + Send + 'static {
695727
/// to avoid generating a new one. It would be better to not
696728
/// define this in the macro, but types need some additional
697729
/// machinery to make it work.
730+
#[cfg(feature = "backtrace")]
698731
fn extract_backtrace(e: &(error::Error + Send + 'static))
699732
-> Option<Option<Arc<Backtrace>>>;
700733
}
@@ -715,26 +748,38 @@ impl<T, E> ResultExt<T, E> for Result<T, E> where E: ChainedError {
715748
where F: FnOnce() -> EK,
716749
EK: Into<E::ErrorKind> {
717750
self.map_err(move |e| {
718-
let backtrace =
719-
E::extract_backtrace(&e).unwrap_or_else(make_backtrace);
720-
721-
E::new(callback().into(), State {
722-
next_error: Some(Box::new(e)),
723-
backtrace: backtrace,
724-
})
751+
#[cfg(feature = "backtrace")]
752+
let ret = {
753+
let backtrace = E::extract_backtrace(&e)
754+
.unwrap_or_else(make_backtrace);
755+
E::new(callback().into(), State {
756+
next_error: Some(Box::new(e)),
757+
backtrace: backtrace,
758+
})
759+
};
760+
#[cfg(not(feature = "backtrace"))]
761+
let ret = {
762+
E::new(callback().into(), State {
763+
next_error: Some(Box::new(e)),
764+
})
765+
};
766+
ret
725767
})
726768
}
727769
}
728770

771+
729772
/// Common state between errors.
730773
#[derive(Debug)]
731774
pub struct State {
732775
/// Next error in the error chain.
733776
pub next_error: Option<Box<error::Error + Send>>,
734777
/// Backtrace for the current error.
778+
#[cfg(feature = "backtrace")]
735779
pub backtrace: Option<Arc<Backtrace>>,
736780
}
737781

782+
#[cfg(feature = "backtrace")]
738783
impl Default for State {
739784
fn default() -> State {
740785
State {
@@ -743,3 +788,12 @@ impl Default for State {
743788
}
744789
}
745790
}
791+
792+
#[cfg(not(feature = "backtrace"))]
793+
impl Default for State {
794+
fn default() -> State {
795+
State {
796+
next_error: None,
797+
}
798+
}
799+
}

0 commit comments

Comments
 (0)