@@ -667,6 +667,158 @@ impl dyn Error {
667667 Err ( self )
668668 }
669669 }
670+
671+ /// Returns an iterator starting with the current error and continuing with
672+ /// recursively calling [`source`].
673+ ///
674+ /// # Examples
675+ ///
676+ /// ```
677+ /// #![feature(error_iter)]
678+ /// use std::error::Error;
679+ /// use std::fmt;
680+ ///
681+ /// #[derive(Debug)]
682+ /// struct A;
683+ ///
684+ /// #[derive(Debug)]
685+ /// struct B(Option<Box<dyn Error + 'static>>);
686+ ///
687+ /// impl fmt::Display for A {
688+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
689+ /// write!(f, "A")
690+ /// }
691+ /// }
692+ ///
693+ /// impl fmt::Display for B {
694+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
695+ /// write!(f, "B")
696+ /// }
697+ /// }
698+ ///
699+ /// impl Error for A {}
700+ ///
701+ /// impl Error for B {
702+ /// fn source(&self) -> Option<&(dyn Error + 'static)> {
703+ /// self.0.as_ref().map(|e| e.as_ref())
704+ /// }
705+ /// }
706+ ///
707+ /// let b = B(Some(Box::new(A)));
708+ ///
709+ /// // let err : Box<Error> = b.into(); // or
710+ /// let err = &b as &(dyn Error);
711+ ///
712+ /// let mut iter = err.iter_chain();
713+ ///
714+ /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
715+ /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
716+ /// assert!(iter.next().is_none());
717+ /// assert!(iter.next().is_none());
718+ /// ```
719+ ///
720+ /// [`source`]: trait.Error.html#method.source
721+ #[ unstable( feature = "error_iter" , issue = "58289" ) ]
722+ #[ inline]
723+ pub fn iter_chain ( & self ) -> ErrorIter {
724+ ErrorIter {
725+ current : Some ( self ) ,
726+ }
727+ }
728+
729+ /// Returns an iterator starting with the [`source`] of this error
730+ /// and continuing with recursively calling [`source`].
731+ ///
732+ /// # Examples
733+ ///
734+ /// ```
735+ /// #![feature(error_iter)]
736+ /// use std::error::Error;
737+ /// use std::fmt;
738+ ///
739+ /// #[derive(Debug)]
740+ /// struct A;
741+ ///
742+ /// #[derive(Debug)]
743+ /// struct B(Option<Box<dyn Error + 'static>>);
744+ ///
745+ /// #[derive(Debug)]
746+ /// struct C(Option<Box<dyn Error + 'static>>);
747+ ///
748+ /// impl fmt::Display for A {
749+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
750+ /// write!(f, "A")
751+ /// }
752+ /// }
753+ ///
754+ /// impl fmt::Display for B {
755+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
756+ /// write!(f, "B")
757+ /// }
758+ /// }
759+ ///
760+ /// impl fmt::Display for C {
761+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
762+ /// write!(f, "C")
763+ /// }
764+ /// }
765+ ///
766+ /// impl Error for A {}
767+ ///
768+ /// impl Error for B {
769+ /// fn source(&self) -> Option<&(dyn Error + 'static)> {
770+ /// self.0.as_ref().map(|e| e.as_ref())
771+ /// }
772+ /// }
773+ ///
774+ /// impl Error for C {
775+ /// fn source(&self) -> Option<&(dyn Error + 'static)> {
776+ /// self.0.as_ref().map(|e| e.as_ref())
777+ /// }
778+ /// }
779+ ///
780+ /// let b = B(Some(Box::new(A)));
781+ /// let c = C(Some(Box::new(b)));
782+ ///
783+ /// // let err : Box<Error> = c.into(); // or
784+ /// let err = &c as &(dyn Error);
785+ ///
786+ /// let mut iter = err.iter_sources();
787+ ///
788+ /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
789+ /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
790+ /// assert!(iter.next().is_none());
791+ /// assert!(iter.next().is_none());
792+ /// ```
793+ ///
794+ /// [`source`]: trait.Error.html#method.source
795+ #[ inline]
796+ #[ unstable( feature = "error_iter" , issue = "58289" ) ]
797+ pub fn iter_sources ( & self ) -> ErrorIter {
798+ ErrorIter {
799+ current : self . source ( ) ,
800+ }
801+ }
802+ }
803+
804+ /// An iterator over [`Error`]
805+ ///
806+ /// [`Error`]: trait.Error.html
807+ #[ unstable( feature = "error_iter" , issue = "58289" ) ]
808+ #[ derive( Copy , Clone , Debug ) ]
809+ pub struct ErrorIter < ' a > {
810+ current : Option < & ' a ( dyn Error + ' static ) > ,
811+ }
812+
813+ #[ unstable( feature = "error_iter" , issue = "58289" ) ]
814+ impl < ' a > Iterator for ErrorIter < ' a > {
815+ type Item = & ' a ( dyn Error + ' static ) ;
816+
817+ fn next ( & mut self ) -> Option < Self :: Item > {
818+ let current = self . current ;
819+ self . current = self . current . and_then ( Error :: source) ;
820+ current
821+ }
670822}
671823
672824impl dyn Error + Send {
0 commit comments