diff options
| author | Stein Somers <git@steinsomers.be> | 2019-02-18 00:31:41 +0100 |
|---|---|---|
| committer | Stein Somers <git@steinsomers.be> | 2019-02-18 00:31:41 +0100 |
| commit | 01bebdf19321a1597f35c2fc2130f1627e944bcf (patch) | |
| tree | 2c71bc6a77545eacabdc67b1fcaa5f52dd22878c /src/libstd/error.rs | |
| parent | 0b9ad6e6fd017837647eed8e5ae824d1f6e278b2 (diff) | |
| parent | 9a3392e174a432a5f06c1157befc1ce0fae74bec (diff) | |
| download | rust-01bebdf19321a1597f35c2fc2130f1627e944bcf.tar.gz rust-01bebdf19321a1597f35c2fc2130f1627e944bcf.zip | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/libstd/error.rs')
| -rw-r--r-- | src/libstd/error.rs | 156 |
1 files changed, 154 insertions, 2 deletions
diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 50415d9aeb9..ef8c97bebdf 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -195,7 +195,7 @@ pub trait Error: Debug + Display { #[stable(feature = "error_source", since = "1.30.0")] fn source(&self) -> Option<&(dyn Error + 'static)> { None } - /// Get the `TypeId` of `self` + /// Gets the `TypeId` of `self` #[doc(hidden)] #[stable(feature = "error_type_id", since = "1.34.0")] fn type_id(&self) -> TypeId where Self: 'static { @@ -564,7 +564,7 @@ impl Error for char::ParseCharError { // copied from any.rs impl dyn Error + 'static { - /// Returns true if the boxed type is the same as `T` + /// Returns `true` if the boxed type is the same as `T` #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is<T: Error + 'static>(&self) -> bool { @@ -667,6 +667,158 @@ impl dyn Error { Err(self) } } + + /// Returns an iterator starting with the current error and continuing with + /// recursively calling [`source`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(error_iter)] + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct A; + /// + /// #[derive(Debug)] + /// struct B(Option<Box<dyn Error + 'static>>); + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "A") + /// } + /// } + /// + /// impl fmt::Display for B { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "B") + /// } + /// } + /// + /// impl Error for A {} + /// + /// impl Error for B { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// self.0.as_ref().map(|e| e.as_ref()) + /// } + /// } + /// + /// let b = B(Some(Box::new(A))); + /// + /// // let err : Box<Error> = b.into(); // or + /// let err = &b as &(dyn Error); + /// + /// let mut iter = err.iter_chain(); + /// + /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); + /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); + /// assert!(iter.next().is_none()); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`source`]: trait.Error.html#method.source + #[unstable(feature = "error_iter", issue = "58520")] + #[inline] + pub fn iter_chain(&self) -> ErrorIter { + ErrorIter { + current: Some(self), + } + } + + /// Returns an iterator starting with the [`source`] of this error + /// and continuing with recursively calling [`source`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(error_iter)] + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct A; + /// + /// #[derive(Debug)] + /// struct B(Option<Box<dyn Error + 'static>>); + /// + /// #[derive(Debug)] + /// struct C(Option<Box<dyn Error + 'static>>); + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "A") + /// } + /// } + /// + /// impl fmt::Display for B { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "B") + /// } + /// } + /// + /// impl fmt::Display for C { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "C") + /// } + /// } + /// + /// impl Error for A {} + /// + /// impl Error for B { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// self.0.as_ref().map(|e| e.as_ref()) + /// } + /// } + /// + /// impl Error for C { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// self.0.as_ref().map(|e| e.as_ref()) + /// } + /// } + /// + /// let b = B(Some(Box::new(A))); + /// let c = C(Some(Box::new(b))); + /// + /// // let err : Box<Error> = c.into(); // or + /// let err = &c as &(dyn Error); + /// + /// let mut iter = err.iter_sources(); + /// + /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); + /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); + /// assert!(iter.next().is_none()); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`source`]: trait.Error.html#method.source + #[inline] + #[unstable(feature = "error_iter", issue = "58520")] + pub fn iter_sources(&self) -> ErrorIter { + ErrorIter { + current: self.source(), + } + } +} + +/// An iterator over [`Error`] +/// +/// [`Error`]: trait.Error.html +#[unstable(feature = "error_iter", issue = "58520")] +#[derive(Copy, Clone, Debug)] +pub struct ErrorIter<'a> { + current: Option<&'a (dyn Error + 'static)>, +} + +#[unstable(feature = "error_iter", issue = "58520")] +impl<'a> Iterator for ErrorIter<'a> { + type Item = &'a (dyn Error + 'static); + + fn next(&mut self) -> Option<Self::Item> { + let current = self.current; + self.current = self.current.and_then(Error::source); + current + } } impl dyn Error + Send { |
