about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-11-23 18:42:20 +0000
committerbors <bors@rust-lang.org>2018-11-23 18:42:20 +0000
commit1f57e4841157d5cbd4c4e22018f93bd1801c98c2 (patch)
tree1c6b53efd2d50c15afb6896ba713bf1bf10f8412 /src/libcore
parent821bad3a5b13862e9fbfae35b446ab91a976a75e (diff)
parent36189a2739f22dd03a8067544c42ebc2288fbeb1 (diff)
downloadrust-1f57e4841157d5cbd4c4e22018f93bd1801c98c2.tar.gz
rust-1f57e4841157d5cbd4c4e22018f93bd1801c98c2.zip
Auto merge of #56186 - kennytm:rollup, r=kennytm
Rollup of 14 pull requests

Successful merges:

 - #55767 (Disable some pretty-printers when gdb is rust-enabled)
 - #55838 (Fix #[cfg] for step impl on ranges)
 - #55869 (Add std::iter::unfold)
 - #55945 (Ensure that the argument to `static_assert` is a `bool`)
 - #56022 (When popping in CTFE, perform validation before jumping to next statement to have a better span for the error)
 - #56048 (Add rustc_codegen_ssa to sysroot)
 - #56091 (Fix json output in the self-profiler)
 - #56097 (Fix invalid bitcast taking bool out of a union represented as a scalar)
 - #56116 (ci: Download clang/lldb from tarballs)
 - #56120 (Add unstable Literal::subspan().)
 - #56154 (Pass additional linker flags when targeting Fuchsia)
 - #56162 (std::str Adapt documentation to reality)
 - #56163 ([master] Backport 1.30.1 release notes)
 - #56168 (Fix the tracking issue for hash_raw_entry)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/iter/mod.rs6
-rw-r--r--src/libcore/iter/range.rs8
-rw-r--r--src/libcore/iter/sources.rs161
-rw-r--r--src/libcore/str/mod.rs6
-rw-r--r--src/libcore/tests/iter.rs11
-rw-r--r--src/libcore/tests/lib.rs1
6 files changed, 183 insertions, 10 deletions
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 509068843d1..62e1f9fcb64 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -112,10 +112,10 @@
 //!
 //!     // next() is the only required method
 //!     fn next(&mut self) -> Option<usize> {
-//!         // increment our count. This is why we started at zero.
+//!         // Increment our count. This is why we started at zero.
 //!         self.count += 1;
 //!
-//!         // check to see if we've finished counting or not.
+//!         // Check to see if we've finished counting or not.
 //!         if self.count < 6 {
 //!             Some(self.count)
 //!         } else {
@@ -339,6 +339,8 @@ pub use self::sources::{RepeatWith, repeat_with};
 pub use self::sources::{Empty, empty};
 #[stable(feature = "iter_once", since = "1.2.0")]
 pub use self::sources::{Once, once};
+#[unstable(feature = "iter_unfold", issue = "55977")]
+pub use self::sources::{Unfold, unfold, Successors, successors};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend};
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index 55addd86bc1..f0fd07b43ca 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -166,14 +166,14 @@ macro_rules! step_impl_no_between {
 }
 
 step_impl_unsigned!(usize u8 u16);
-#[cfg(not(target_pointer_witdth = "16"))]
+#[cfg(not(target_pointer_width = "16"))]
 step_impl_unsigned!(u32);
-#[cfg(target_pointer_witdth = "16")]
+#[cfg(target_pointer_width = "16")]
 step_impl_no_between!(u32);
 step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
-#[cfg(not(target_pointer_witdth = "16"))]
+#[cfg(not(target_pointer_width = "16"))]
 step_impl_signed!([i32: u32]);
-#[cfg(target_pointer_witdth = "16")]
+#[cfg(target_pointer_width = "16")]
 step_impl_no_between!(i32);
 #[cfg(target_pointer_width = "64")]
 step_impl_unsigned!(u64);
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index 7fa3a4bcce7..f6a4a7a6fa8 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -386,3 +386,164 @@ impl<T> FusedIterator for Once<T> {}
 pub fn once<T>(value: T) -> Once<T> {
     Once { inner: Some(value).into_iter() }
 }
+
+/// Creates a new iterator where each iteration calls the provided closure
+/// `F: FnMut(&mut St) -> Option<T>`.
+///
+/// This allows creating a custom iterator with any behavior
+/// without using the more verbose syntax of creating a dedicated type
+/// and implementing the `Iterator` trait for it.
+///
+/// In addition to its captures and environment,
+/// the closure is given a mutable reference to some state
+/// that is preserved across iterations.
+/// That state starts as the given `initial_state` value.
+///
+/// Note that the `Unfold` iterator doesn’t make assumptions about the behavior of the closure,
+/// and therefore conservatively does not implement [`FusedIterator`],
+/// or override [`Iterator::size_hint`] from its default `(0, None)`.
+///
+/// [`FusedIterator`]: trait.FusedIterator.html
+/// [`Iterator::size_hint`]: trait.Iterator.html#method.size_hint
+///
+/// # Examples
+///
+/// Let’s re-implement the counter iterator from [module-level documentation]:
+///
+/// [module-level documentation]: index.html
+///
+/// ```
+/// #![feature(iter_unfold)]
+/// let counter = std::iter::unfold(0, |count| {
+///     // Increment our count. This is why we started at zero.
+///     *count += 1;
+///
+///     // Check to see if we've finished counting or not.
+///     if *count < 6 {
+///         Some(*count)
+///     } else {
+///         None
+///     }
+/// });
+/// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
+/// ```
+#[inline]
+#[unstable(feature = "iter_unfold", issue = "55977")]
+pub fn unfold<St, T, F>(initial_state: St, f: F) -> Unfold<St, F>
+    where F: FnMut(&mut St) -> Option<T>
+{
+    Unfold {
+        state: initial_state,
+        f,
+    }
+}
+
+/// An iterator where each iteration calls the provided closure `F: FnMut(&mut St) -> Option<T>`.
+///
+/// This `struct` is created by the [`unfold`] function.
+/// See its documentation for more.
+///
+/// [`unfold`]: fn.unfold.html
+#[derive(Clone)]
+#[unstable(feature = "iter_unfold", issue = "55977")]
+pub struct Unfold<St, F> {
+    state: St,
+    f: F,
+}
+
+#[unstable(feature = "iter_unfold", issue = "55977")]
+impl<St, T, F> Iterator for Unfold<St, F>
+    where F: FnMut(&mut St) -> Option<T>
+{
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        (self.f)(&mut self.state)
+    }
+}
+
+#[unstable(feature = "iter_unfold", issue = "55977")]
+impl<St: fmt::Debug, F> fmt::Debug for Unfold<St, F> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Unfold")
+            .field("state", &self.state)
+            .finish()
+    }
+}
+
+/// Creates a new iterator where each successive item is computed based on the preceding one.
+///
+/// The iterator starts with the given first item (if any)
+/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
+///
+/// ```
+/// #![feature(iter_unfold)]
+/// use std::iter::successors;
+///
+/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
+/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
+/// ```
+#[unstable(feature = "iter_unfold", issue = "55977")]
+pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
+    where F: FnMut(&T) -> Option<T>
+{
+    // If this function returned `impl Iterator<Item=T>`
+    // it could be based on `unfold` and not need a dedicated type.
+    // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
+    Successors {
+        next: first,
+        succ,
+    }
+}
+
+/// An new iterator where each successive item is computed based on the preceding one.
+///
+/// This `struct` is created by the [`successors`] function.
+/// See its documentation for more.
+///
+/// [`successors`]: fn.successors.html
+#[derive(Clone)]
+#[unstable(feature = "iter_unfold", issue = "55977")]
+pub struct Successors<T, F> {
+    next: Option<T>,
+    succ: F,
+}
+
+#[unstable(feature = "iter_unfold", issue = "55977")]
+impl<T, F> Iterator for Successors<T, F>
+    where F: FnMut(&T) -> Option<T>
+{
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        self.next.take().map(|item| {
+            self.next = (self.succ)(&item);
+            item
+        })
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.next.is_some() {
+            (1, None)
+        } else {
+            (0, Some(0))
+        }
+    }
+}
+
+#[unstable(feature = "iter_unfold", issue = "55977")]
+impl<T, F> FusedIterator for Successors<T, F>
+    where F: FnMut(&T) -> Option<T>
+{}
+
+#[unstable(feature = "iter_unfold", issue = "55977")]
+impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Successors")
+            .field("next", &self.next)
+            .finish()
+    }
+}
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index a316093825a..89efa120a6f 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1424,10 +1424,8 @@ fn contains_nonascii(x: usize) -> bool {
     (x & NONASCII_MASK) != 0
 }
 
-/// Walks through `iter` checking that it's a valid UTF-8 sequence,
-/// returning `true` in that case, or, if it is invalid, `false` with
-/// `iter` reset such that it is pointing at the first byte in the
-/// invalid sequence.
+/// Walks through `v` checking that it's a valid UTF-8 sequence,
+/// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`.
 #[inline]
 fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
     let mut index = 0;
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index ec09071b3d0..495483db555 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1760,6 +1760,17 @@ fn test_repeat_with_take_collect() {
 }
 
 #[test]
+fn test_successors() {
+    let mut powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
+    assert_eq!(powers_of_10.by_ref().collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
+    assert_eq!(powers_of_10.next(), None);
+
+    let mut empty = successors(None::<u32>, |_| unimplemented!());
+    assert_eq!(empty.next(), None);
+    assert_eq!(empty.next(), None);
+}
+
+#[test]
 fn test_fuse() {
     let mut it = 0..3;
     assert_eq!(it.len(), 3);
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 5ac89912268..7d62b4fa90f 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -19,6 +19,7 @@
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
+#![feature(iter_unfold)]
 #![feature(pattern)]
 #![feature(range_is_empty)]
 #![feature(raw)]