diff options
| author | bors <bors@rust-lang.org> | 2019-07-28 01:03:16 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-07-28 01:03:16 +0000 |
| commit | 9a239ef4ded03d155c72b68b5a2dd7aff013e141 (patch) | |
| tree | ddecacf7cf04b32211999b7d65dae0bbf2012102 /src/libcore | |
| parent | c798dffac9dc8c82374db48f5b474690cc6e9686 (diff) | |
| parent | 34c0f4698bda7e06d66ee9040a2923250b0c12d0 (diff) | |
| download | rust-9a239ef4ded03d155c72b68b5a2dd7aff013e141.tar.gz rust-9a239ef4ded03d155c72b68b5a2dd7aff013e141.zip | |
Auto merge of #63057 - Centril:rollup-z3a3c6v, r=Centril
Rollup of 8 pull requests Successful merges: - #61207 (Allow lifetime elision in `Pin<&(mut) Self>`) - #62074 (squash of all commits for nth_back on ChunksMut) - #62771 (Break dependencies between `syntax_ext` and other crates) - #62883 (Refactoring use common code between option, result and accum) - #62949 (Re-enable assertions in PPC dist builder) - #62996 (tidy: Add a check for inline unit tests) - #63038 (Make more informative error on outer attribute after inner) - #63050 (ci: download awscli from our mirror) Failed merges: r? @ghost
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 135 | ||||
| -rw-r--r-- | src/libcore/iter/mod.rs | 2 | ||||
| -rw-r--r-- | src/libcore/iter/traits/accum.rs | 136 | ||||
| -rw-r--r-- | src/libcore/option.rs | 42 | ||||
| -rw-r--r-- | src/libcore/result.rs | 36 | ||||
| -rw-r--r-- | src/libcore/slice/mod.rs | 19 | ||||
| -rw-r--r-- | src/libcore/tests/slice.rs | 22 |
7 files changed, 182 insertions, 210 deletions
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index c2edcd22f95..8eae52ffd32 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -2062,3 +2062,138 @@ impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F> #[stable(feature = "fused", since = "1.26.0")] impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {} + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Option::Some` values. +pub(crate) struct OptionShunt<I> { + iter: I, + exited_early: bool, +} + +impl<I, T> OptionShunt<I> +where + I: Iterator<Item = Option<T>>, +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Option<T>`. Any `None` value will stop the inner iterator and + /// the overall result will be a `None`. + pub fn process<F, U>(iter: I, mut f: F) -> Option<U> + where + F: FnMut(&mut Self) -> U, + { + let mut shunt = OptionShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + OptionShunt { + iter, + exited_early: false, + } + } + + /// Consume the adapter and rebuild a `Option` value. + fn reconstruct<U>(self, val: U) -> Option<U> { + if self.exited_early { + None + } else { + Some(val) + } + } +} + +impl<I, T> Iterator for OptionShunt<I> +where + I: Iterator<Item = Option<T>>, +{ + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + match self.iter.next() { + Some(Some(v)) => Some(v), + Some(None) => { + self.exited_early = true; + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + if self.exited_early { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Result::Ok` values. +/// +/// If an error is encountered, the iterator stops and the error is +/// stored. The error may be recovered later via `reconstruct`. +pub(crate) struct ResultShunt<I, E> { + iter: I, + error: Option<E>, +} + +impl<I, T, E> ResultShunt<I, E> + where I: Iterator<Item = Result<T, E>> +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Result<T, _>`. Any errors will stop the inner iterator and + /// the overall result will be an error. + pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E> + where F: FnMut(&mut Self) -> U + { + let mut shunt = ResultShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + ResultShunt { + iter, + error: None, + } + } + + /// Consume the adapter and rebuild a `Result` value. This should + /// *always* be called, otherwise any potential error would be + /// lost. + fn reconstruct<U>(self, val: U) -> Result<U, E> { + match self.error { + None => Ok(val), + Some(e) => Err(e), + } + } +} + +impl<I, T, E> Iterator for ResultShunt<I, E> + where I: Iterator<Item = Result<T, E>> +{ + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + match self.iter.next() { + Some(Ok(v)) => Some(v), + Some(Err(e)) => { + self.error = Some(e); + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + if self.error.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 6eccb9d1ea8..4a7d7f96b9b 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -360,7 +360,7 @@ pub use self::adapters::Flatten; #[stable(feature = "iter_copied", since = "1.36.0")] pub use self::adapters::Copied; -pub(crate) use self::adapters::TrustedRandomAccess; +pub(crate) use self::adapters::{TrustedRandomAccess, OptionShunt, ResultShunt}; mod range; mod sources; diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index adfb639bae3..01b64fb08ac 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -1,5 +1,6 @@ use crate::ops::{Mul, Add}; use crate::num::Wrapping; +use crate::iter::adapters::{OptionShunt, ResultShunt}; /// Trait to represent types that can be created by summing up an iterator. /// @@ -114,74 +115,6 @@ macro_rules! float_sum_product { integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } -/// An iterator adapter that produces output as long as the underlying -/// iterator produces `Result::Ok` values. -/// -/// If an error is encountered, the iterator stops and the error is -/// stored. The error may be recovered later via `reconstruct`. -struct ResultShunt<I, E> { - iter: I, - error: Option<E>, -} - -impl<I, T, E> ResultShunt<I, E> - where I: Iterator<Item = Result<T, E>> -{ - /// Process the given iterator as if it yielded a `T` instead of a - /// `Result<T, _>`. Any errors will stop the inner iterator and - /// the overall result will be an error. - pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E> - where F: FnMut(&mut Self) -> U - { - let mut shunt = ResultShunt::new(iter); - let value = f(shunt.by_ref()); - shunt.reconstruct(value) - } - - fn new(iter: I) -> Self { - ResultShunt { - iter, - error: None, - } - } - - /// Consume the adapter and rebuild a `Result` value. This should - /// *always* be called, otherwise any potential error would be - /// lost. - fn reconstruct<U>(self, val: U) -> Result<U, E> { - match self.error { - None => Ok(val), - Some(e) => Err(e), - } - } -} - -impl<I, T, E> Iterator for ResultShunt<I, E> - where I: Iterator<Item = Result<T, E>> -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - match self.iter.next() { - Some(Ok(v)) => Some(v), - Some(Err(e)) => { - self.error = Some(e); - None - } - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - if self.error.is_some() { - (0, Some(0)) - } else { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } - } -} - #[stable(feature = "iter_arith_traits_result", since="1.16.0")] impl<T, U, E> Sum<Result<U, E>> for Result<T, E> where T: Sum<U>, @@ -224,73 +157,6 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E> } } -/// An iterator adapter that produces output as long as the underlying -/// iterator produces `Option::Some` values. -struct OptionShunt<I> { - iter: I, - exited_early: bool, -} - -impl<I, T> OptionShunt<I> -where - I: Iterator<Item = Option<T>>, -{ - /// Process the given iterator as if it yielded a `T` instead of a - /// `Option<T>`. Any `None` value will stop the inner iterator and - /// the overall result will be a `None`. - pub fn process<F, U>(iter: I, mut f: F) -> Option<U> - where - F: FnMut(&mut Self) -> U, - { - let mut shunt = OptionShunt::new(iter); - let value = f(shunt.by_ref()); - shunt.reconstruct(value) - } - - fn new(iter: I) -> Self { - OptionShunt { - iter, - exited_early: false, - } - } - - /// Consume the adapter and rebuild a `Option` value. - fn reconstruct<U>(self, val: U) -> Option<U> { - if self.exited_early { - None - } else { - Some(val) - } - } -} - -impl<I, T> Iterator for OptionShunt<I> -where - I: Iterator<Item = Option<T>>, -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - match self.iter.next() { - Some(Some(v)) => Some(v), - Some(None) => { - self.exited_early = true; - None - } - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - if self.exited_early { - (0, Some(0)) - } else { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } - } -} - #[stable(feature = "iter_arith_traits_option", since = "1.37.0")] impl<T, U> Sum<Option<U>> for Option<T> where diff --git a/src/libcore/option.rs b/src/libcore/option.rs index abc8883d398..70a87cfe5a7 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -135,7 +135,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::iter::{FromIterator, FusedIterator, TrustedLen}; +use crate::iter::{FromIterator, FusedIterator, TrustedLen, OptionShunt}; use crate::{convert, fmt, hint, mem, ops::{self, Deref, DerefMut}}; use crate::pin::Pin; @@ -1499,45 +1499,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. - struct Adapter<Iter> { - iter: Iter, - found_none: bool, - } - - impl<T, Iter: Iterator<Item=Option<T>>> Iterator for Adapter<Iter> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option<T> { - match self.iter.next() { - Some(Some(value)) => Some(value), - Some(None) => { - self.found_none = true; - None - } - None => None, - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - if self.found_none { - (0, Some(0)) - } else { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } - } - } - - let mut adapter = Adapter { iter: iter.into_iter(), found_none: false }; - let v: V = FromIterator::from_iter(adapter.by_ref()); - - if adapter.found_none { - None - } else { - Some(v) - } + OptionShunt::process(iter.into_iter(), |i| i.collect()) } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index cb6bc058730..559877ddd5a 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -231,7 +231,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; -use crate::iter::{FromIterator, FusedIterator, TrustedLen}; +use crate::iter::{FromIterator, FusedIterator, TrustedLen, ResultShunt}; use crate::ops::{self, Deref, DerefMut}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). @@ -1343,39 +1343,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. - struct Adapter<Iter, E> { - iter: Iter, - err: Option<E>, - } - - impl<T, E, Iter: Iterator<Item=Result<T, E>>> Iterator for Adapter<Iter, E> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option<T> { - match self.iter.next() { - Some(Ok(value)) => Some(value), - Some(Err(err)) => { - self.err = Some(err); - None - } - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_min, max) = self.iter.size_hint(); - (0, max) - } - } - - let mut adapter = Adapter { iter: iter.into_iter(), err: None }; - let v: V = FromIterator::from_iter(adapter.by_ref()); - - match adapter.err { - Some(err) => Err(err), - None => Ok(v), - } + ResultShunt::process(iter.into_iter(), |i| i.collect()) } } diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index e7b820e79e5..b06511cad97 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4339,6 +4339,25 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { Some(tail) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<Self::Item> { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = match start.checked_add(self.chunk_size) { + Some(res) => cmp::min(res, self.v.len()), + None => self.v.len(), + }; + let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (head, nth_back) = temp.split_at_mut(start); + self.v = head; + Some(nth_back) + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 42ec9d451f7..b046c3ce5ce 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -223,6 +223,28 @@ fn test_chunks_mut_nth() { } #[test] +fn test_chunks_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.chunks_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + + let v1: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c1 = v1.chunks_mut(3); + assert_eq!(c1.nth_back(1).unwrap(), &[0, 1, 2]); + assert_eq!(c1.next(), None); + + let v3: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c3 = v3.chunks_mut(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); + + let v4: &mut [i32] = &mut [0, 1, 2]; + let mut c4 = v4.chunks_mut(10); + assert_eq!(c4.nth_back(1_000_000_000usize), None); +} + +#[test] fn test_chunks_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let c = v.chunks_mut(2); |
