@@ -99,6 +99,49 @@ pub trait Error: Debug + Display {
99
99
None
100
100
}
101
101
102
+ /// Returns an iterator starting with the `source()` of this error
103
+ /// and continuing with recursively calling `source()`
104
+ ///
105
+ /// If you want to include the current error, use [`Chain::new`].
106
+ ///
107
+ /// # Examples
108
+ ///
109
+ /// ```
110
+ /// #![feature(error_iter)]
111
+ /// use std::error::Error;
112
+ /// use std::fmt;
113
+ ///
114
+ /// #[derive(Debug)]
115
+ /// struct SourceError(&'static str, Option<Box<dyn Error + 'static>>);
116
+ ///
117
+ /// impl fmt::Display for SourceError {
118
+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119
+ /// write!(f, "{}", self.0)
120
+ /// }
121
+ /// }
122
+ ///
123
+ /// impl Error for SourceError {
124
+ /// fn source(&self) -> Option<&(dyn Error + 'static)> {
125
+ /// self.1.as_ref().map(|e| e.as_ref())
126
+ /// }
127
+ /// }
128
+ ///
129
+ /// let a = SourceError("A", None);
130
+ /// let b = SourceError("B", Some(Box::new(a)));
131
+ /// let c = SourceError("C", Some(Box::new(b)));
132
+ ///
133
+ /// let mut iter = c.sources();
134
+ ///
135
+ /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
136
+ /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
137
+ /// assert!(iter.next().is_none());
138
+ /// ```
139
+ #[ unstable( feature = "error_iter" , issue = "58520" ) ]
140
+ #[ inline]
141
+ fn sources ( & self ) -> Chain < ' _ > {
142
+ Chain { current : self . source ( ) }
143
+ }
144
+
102
145
/// Gets the `TypeId` of `self`.
103
146
#[ doc( hidden) ]
104
147
#[ unstable(
@@ -651,75 +694,62 @@ impl dyn Error {
651
694
Err ( self )
652
695
}
653
696
}
697
+ }
698
+
699
+ /// An iterator over an [`Error`] and its sources.
700
+ #[ unstable( feature = "error_iter" , issue = "58520" ) ]
701
+ #[ derive( Clone , Debug ) ]
702
+ pub struct Chain < ' a > {
703
+ current : Option < & ' a ( dyn Error + ' static ) > ,
704
+ }
654
705
706
+ impl < ' a > Chain < ' a > {
655
707
/// Returns an iterator starting with the current error and continuing with
656
708
/// recursively calling [`Error::source`].
657
709
///
658
710
/// If you want to omit the current error and only use its sources,
659
- /// use `skip(1)` .
711
+ /// use [`Error::sources`] .
660
712
///
661
713
/// # Examples
662
714
///
663
715
/// ```
664
716
/// #![feature(error_iter)]
665
- /// use std::error::Error;
717
+ /// use std::error::{ Error, Chain} ;
666
718
/// use std::fmt;
667
719
///
668
720
/// #[derive(Debug)]
669
- /// struct A;
670
- ///
671
- /// #[derive(Debug)]
672
- /// struct B(Option<Box<dyn Error + 'static>>);
721
+ /// struct SourceError(&'static str, Option<Box<dyn Error + 'static>>);
673
722
///
674
- /// impl fmt::Display for A {
675
- /// fn fmt(&self, f: &mut fmt::Formatter<'_> ) -> fmt::Result {
676
- /// write!(f, "A" )
723
+ /// impl fmt::Display for SourceError {
724
+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
725
+ /// write!(f, "{}", self.0 )
677
726
/// }
678
727
/// }
679
728
///
680
- /// impl fmt::Display for B {
681
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
682
- /// write!(f, "B")
683
- /// }
684
- /// }
685
- ///
686
- /// impl Error for A {}
687
- ///
688
- /// impl Error for B {
729
+ /// impl Error for SourceError {
689
730
/// fn source(&self) -> Option<&(dyn Error + 'static)> {
690
- /// self.0 .as_ref().map(|e| e.as_ref())
731
+ /// self.1 .as_ref().map(|e| e.as_ref())
691
732
/// }
692
733
/// }
693
734
///
694
- /// let b = B(Some(Box::new(A)));
695
- ///
696
- /// // let err : Box<Error> = b.into(); // or
697
- /// let err = &b as &(dyn Error);
735
+ /// let a = SourceError("A", None);
736
+ /// let b = SourceError("B", Some(Box::new(a)));
737
+ /// let c = SourceError("C", Some(Box::new(b)));
698
738
///
699
- /// let mut iter = err.chain( );
739
+ /// let mut iter = Chain::new(&c );
700
740
///
741
+ /// assert_eq!("C".to_string(), iter.next().unwrap().to_string());
701
742
/// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
702
743
/// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
703
744
/// assert!(iter.next().is_none());
704
- /// assert!(iter.next().is_none());
705
745
/// ```
706
746
#[ unstable( feature = "error_iter" , issue = "58520" ) ]
707
747
#[ inline]
708
- pub fn chain ( & self ) -> Chain < ' _ > {
709
- Chain { current : Some ( self ) }
748
+ pub fn new ( err : & ' a ( dyn Error + ' static ) ) -> Chain < ' a > {
749
+ Chain { current : Some ( err ) }
710
750
}
711
751
}
712
752
713
- /// An iterator over an [`Error`] and its sources.
714
- ///
715
- /// If you want to omit the initial error and only process
716
- /// its sources, use `skip(1)`.
717
- #[ unstable( feature = "error_iter" , issue = "58520" ) ]
718
- #[ derive( Clone , Debug ) ]
719
- pub struct Chain < ' a > {
720
- current : Option < & ' a ( dyn Error + ' static ) > ,
721
- }
722
-
723
753
#[ unstable( feature = "error_iter" , issue = "58520" ) ]
724
754
impl < ' a > Iterator for Chain < ' a > {
725
755
type Item = & ' a ( dyn Error + ' static ) ;
0 commit comments