diff options
| author | bors <bors@rust-lang.org> | 2018-11-23 18:42:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-11-23 18:42:20 +0000 |
| commit | 1f57e4841157d5cbd4c4e22018f93bd1801c98c2 (patch) | |
| tree | 1c6b53efd2d50c15afb6896ba713bf1bf10f8412 /src/libcore | |
| parent | 821bad3a5b13862e9fbfae35b446ab91a976a75e (diff) | |
| parent | 36189a2739f22dd03a8067544c42ebc2288fbeb1 (diff) | |
| download | rust-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.rs | 6 | ||||
| -rw-r--r-- | src/libcore/iter/range.rs | 8 | ||||
| -rw-r--r-- | src/libcore/iter/sources.rs | 161 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 6 | ||||
| -rw-r--r-- | src/libcore/tests/iter.rs | 11 | ||||
| -rw-r--r-- | src/libcore/tests/lib.rs | 1 |
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)] |
