about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-02-13 05:14:12 +0000
committerbors <bors@rust-lang.org>2019-02-13 05:14:12 +0000
commit827a141466e7bb85eb3c030600878a2c606019e9 (patch)
treecbbbb0b46cf4a3694316b2462ae2dcf7321468e4 /src/libstd
parent0f949c2fcc696d0260a99196d5e5400c59a26a54 (diff)
parent6562c2860730aee4497f58b00c298d054ff2e0b7 (diff)
downloadrust-827a141466e7bb85eb3c030600878a2c606019e9.tar.gz
rust-827a141466e7bb85eb3c030600878a2c606019e9.zip
Auto merge of #58415 - Centril:rollup, r=Centril
Rollup of 12 pull requests

Successful merges:

 - #57693 (Doc rewording)
 - #57815 (Speed up the fast path for assert_eq! and assert_ne!)
 - #58034 (Stabilize the time_checked_add feature)
 - #58057 (Stabilize linker-plugin based LTO (aka cross-language LTO))
 - #58137 (Cleanup: rename node_id_to_type(_opt))
 - #58166 (allow shorthand syntax for deprecation reason)
 - #58200 (fix str mutating through a ptr derived from &self)
 - #58273 (Rename rustc_errors dependency in rust 2018 crates)
 - #58289 (impl iter() for dyn Error)
 - #58387 (Disallow `auto` trait alias syntax)
 - #58404 (use Ubuntu keyserver for CloudABI ports)
 - #58405 (Remove some dead code from libcore)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/error.rs152
-rw-r--r--src/libstd/macros.rs2
-rw-r--r--src/libstd/time.rs16
3 files changed, 161 insertions, 9 deletions
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index f792ff56179..6348b411a4c 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -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 = "58289")]
+    #[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 = "58289")]
+    pub fn iter_sources(&self) -> ErrorIter {
+        ErrorIter {
+            current: self.source(),
+        }
+    }
+}
+
+/// An iterator over [`Error`]
+///
+/// [`Error`]: trait.Error.html
+#[unstable(feature = "error_iter", issue = "58289")]
+#[derive(Copy, Clone, Debug)]
+pub struct ErrorIter<'a> {
+    current: Option<&'a (dyn Error + 'static)>,
+}
+
+#[unstable(feature = "error_iter", issue = "58289")]
+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 {
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index dfe3079bb6c..b9204d27f53 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -8,7 +8,7 @@
 ///
 /// This allows a program to terminate immediately and provide feedback
 /// to the caller of the program. `panic!` should be used when a program reaches
-/// an unrecoverable problem.
+/// an unrecoverable state.
 ///
 /// This macro is the perfect way to assert conditions in example code and in
 /// tests. `panic!` is closely tied with the `unwrap` method of both [`Option`]
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index c258e3f1a55..47a963bcca9 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -245,17 +245,17 @@ impl Instant {
     /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
     /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
     /// otherwise.
-    #[unstable(feature = "time_checked_add", issue = "55940")]
+    #[stable(feature = "time_checked_add", since = "1.34.0")]
     pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
-        self.0.checked_add_duration(&duration).map(|t| Instant(t))
+        self.0.checked_add_duration(&duration).map(Instant)
     }
 
     /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
     /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
     /// otherwise.
-    #[unstable(feature = "time_checked_add", issue = "55940")]
+    #[stable(feature = "time_checked_add", since = "1.34.0")]
     pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
-        self.0.checked_sub_duration(&duration).map(|t| Instant(t))
+        self.0.checked_sub_duration(&duration).map(Instant)
     }
 }
 
@@ -418,17 +418,17 @@ impl SystemTime {
     /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
     /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
     /// otherwise.
-    #[unstable(feature = "time_checked_add", issue = "55940")]
+    #[stable(feature = "time_checked_add", since = "1.34.0")]
     pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
-        self.0.checked_add_duration(&duration).map(|t| SystemTime(t))
+        self.0.checked_add_duration(&duration).map(SystemTime)
     }
 
     /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
     /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
     /// otherwise.
-    #[unstable(feature = "time_checked_add", issue = "55940")]
+    #[stable(feature = "time_checked_add", since = "1.34.0")]
     pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
-        self.0.checked_sub_duration(&duration).map(|t| SystemTime(t))
+        self.0.checked_sub_duration(&duration).map(SystemTime)
     }
 }