diff options
| author | Baoshan <pangbw@gmail.com> | 2019-08-29 09:29:23 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-29 09:29:23 -0700 |
| commit | 043c19c69c0beac3696cb82d44476ba4298a6b07 (patch) | |
| tree | 1813e5dd1e4efd5806f401968b4ed34b8c9c76ac /src/libcore | |
| parent | cae6d66d9989857e321e0963142b08b1517dc723 (diff) | |
| parent | 76f17219c71973fd4a58f2f8020eec4d8f5dcd11 (diff) | |
| download | rust-043c19c69c0beac3696cb82d44476ba4298a6b07.tar.gz rust-043c19c69c0beac3696cb82d44476ba4298a6b07.zip | |
Merge branch 'master' into bpang-runtest
Diffstat (limited to 'src/libcore')
30 files changed, 926 insertions, 463 deletions
diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 078091a9b54..e8a0a88f12a 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -470,10 +470,5 @@ impl TypeId { #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name")] pub const fn type_name<T: ?Sized>() -> &'static str { - #[cfg(bootstrap)] - unsafe { - intrinsics::type_name::<T>() - } - #[cfg(not(bootstrap))] intrinsics::type_name::<T>() } diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index e6a6fdde540..4087333e2cf 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -14,6 +14,7 @@ use crate::fmt; use crate::ops::Range; use crate::iter::FusedIterator; +use crate::str::from_utf8_unchecked; /// An iterator over the escaped version of a byte. /// @@ -22,6 +23,7 @@ use crate::iter::FusedIterator; /// /// [`escape_default`]: fn.escape_default.html #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] pub struct EscapeDefault { range: Range<usize>, data: [u8; 4], @@ -130,6 +132,13 @@ impl ExactSizeIterator for EscapeDefault {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} +#[stable(feature = "ascii_escape_display", since = "1.39.0")] +impl fmt::Display for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) }) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index aa834db2b9b..e91bf53c5b4 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -553,12 +553,7 @@ impl char { /// `XID_Start` is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] + #[unstable(feature = "unicode_internals", issue = "0")] pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } @@ -569,12 +564,7 @@ impl char { /// `XID_Continue` is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Continue` but modified for closure under NFKx. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] + #[unstable(feature = "unicode_internals", issue = "0")] #[inline] pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 0c99356390b..ec70d396e96 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -134,9 +134,8 @@ pub trait Clone : Sized { } /// Derive macro generating an impl of the trait `Clone`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 38a52d97da2..cb9feb074dd 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -201,9 +201,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> { } /// Derive macro generating an impl of the trait `PartialEq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialEq($item:item) { /* compiler built-in */ } @@ -265,9 +264,8 @@ pub trait Eq: PartialEq<Self> { } /// Derive macro generating an impl of the trait `Eq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -617,9 +615,8 @@ pub trait Ord: Eq + PartialOrd<Self> { } /// Derive macro generating an impl of the trait `Ord`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Ord($item:item) { /* compiler built-in */ } @@ -867,9 +864,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { } /// Derive macro generating an impl of the trait `PartialOrd`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialOrd($item:item) { /* compiler built-in */ } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 8d95e9de158..66acc5165fc 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -116,9 +116,8 @@ pub trait Default: Sized { } /// Derive macro generating an impl of the trait `Default`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Default($item:item) { /* compiler built-in */ } diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index cb4e32622ff..15ce2277fa0 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -98,7 +98,7 @@ pub struct DebugStruct<'a, 'b: 'a> { has_fields: bool, } -pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, +pub(super) fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugStruct<'a, 'b> { let result = fmt.write_str(name); @@ -251,7 +251,10 @@ pub struct DebugTuple<'a, 'b: 'a> { empty_name: bool, } -pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> { +pub(super) fn debug_tuple_new<'a, 'b>( + fmt: &'a mut fmt::Formatter<'b>, + name: &str, +) -> DebugTuple<'a, 'b> { let result = fmt.write_str(name); DebugTuple { fmt, @@ -418,7 +421,7 @@ pub struct DebugSet<'a, 'b: 'a> { inner: DebugInner<'a, 'b>, } -pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { +pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { let result = fmt.write_str("{"); DebugSet { inner: DebugInner { @@ -555,7 +558,7 @@ pub struct DebugList<'a, 'b: 'a> { inner: DebugInner<'a, 'b>, } -pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { +pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { let result = fmt.write_str("["); DebugList { inner: DebugInner { @@ -697,7 +700,7 @@ pub struct DebugMap<'a, 'b: 'a> { state: PadAdapterState, } -pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { +pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { let result = fmt.write_str("{"); DebugMap { fmt, diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0ea01d4b84a..bd31d25dd03 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -546,16 +546,14 @@ pub trait Debug { } // Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Debug; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index c4cbf40a93a..bf3daa32840 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -199,16 +199,14 @@ pub trait Hash { } // Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Hash; @@ -553,8 +551,6 @@ impl<H> PartialEq for BuildHasherDefault<H> { #[stable(since = "1.29.0", feature = "build_hasher_eq")] impl<H> Eq for BuildHasherDefault<H> {} -////////////////////////////////////////////////////////////////////////////// - mod impls { use crate::mem; use crate::slice; diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ceaa870d2b3..d145f2212f9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1293,18 +1293,40 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_add<T>(a: T, b: T) -> T; /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_sub<T>(a: T, b: T) -> T; /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_mul<T>(a: T, b: T) -> T; + /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_add` method. For example, + /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_add<T>(a: T, b: T) -> T; + /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_sub` method. For example, + /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_sub<T>(a: T, b: T) -> T; + /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_mul` method. For example, + /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_mul<T>(a: T, b: T) -> T; + /// Computes `a + b`, while saturating at numeric bounds. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs index 76239ebc0ab..c9612596b1b 100644 --- a/src/libcore/iter/adapters/chain.rs +++ b/src/libcore/iter/adapters/chain.rs @@ -173,17 +173,23 @@ impl<A, B> Iterator for Chain<A, B> where #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); + match self.state { + ChainState::Both => { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); - let lower = a_lower.saturating_add(b_lower); + let lower = a_lower.saturating_add(b_lower); - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None - }; + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None + }; - (lower, upper) + (lower, upper) + } + ChainState::Front => self.a.size_hint(), + ChainState::Back => self.b.size_hint(), + } } } @@ -207,6 +213,29 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where } } + #[inline] + fn nth_back(&mut self, mut n: usize) -> Option<A::Item> { + match self.state { + ChainState::Both | ChainState::Back => { + for x in self.b.by_ref().rev() { + if n == 0 { + return Some(x) + } + n -= 1; + } + if let ChainState::Both = self.state { + self.state = ChainState::Front; + } + } + ChainState::Front => {} + } + if let ChainState::Front = self.state { + self.a.nth_back(n) + } else { + None + } + } + fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index d8d41a2a31e..a45173f614d 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -72,8 +72,7 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F> impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> where F: FnMut(I::Item) -> U, - U: IntoIterator, - U::IntoIter: DoubleEndedIterator, + U: IntoIterator<IntoIter: DoubleEndedIterator>, { #[inline] fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() } @@ -107,10 +106,7 @@ impl<I, U, F> FusedIterator for FlatMap<I, U, F> /// [`Iterator`]: trait.Iterator.html #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iterator_flatten", since = "1.29.0")] -pub struct Flatten<I: Iterator> -where - I::Item: IntoIterator, -{ +pub struct Flatten<I: Iterator<Item: IntoIterator>> { inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>, } @@ -229,7 +225,7 @@ where if let elt@Some(_) = inner.next() { return elt } } match self.iter.next() { - None => return self.backiter.as_mut().and_then(|it| it.next()), + None => return self.backiter.as_mut()?.next(), Some(inner) => self.frontiter = Some(inner.into_iter()), } } @@ -237,8 +233,8 @@ where #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); + let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); let lo = flo.saturating_add(blo); match (self.iter.size_hint(), fhi, bhi) { ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), @@ -250,20 +246,25 @@ where fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>( + frontiter: &'a mut Option<T::IntoIter>, + fold: &'a mut impl FnMut(Acc, T::Item) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, x| { + let mut mid = x.into_iter(); + let r = mid.try_fold(acc, &mut *fold); + *frontiter = Some(mid); + r + } + } + if let Some(ref mut front) = self.frontiter { init = front.try_fold(init, &mut fold)?; } self.frontiter = None; - { - let frontiter = &mut self.frontiter; - init = self.iter.try_fold(init, |acc, x| { - let mut mid = x.into_iter(); - let r = mid.try_fold(acc, &mut fold); - *frontiter = Some(mid); - r - })?; - } + init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?; self.frontiter = None; if let Some(ref mut back) = self.backiter { @@ -275,13 +276,20 @@ where } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { + #[inline] + fn flatten<U: Iterator, Acc>( + fold: &mut impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc + '_ { + move |acc, iter| iter.fold(acc, &mut *fold) + } + self.frontiter.into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) - .fold(init, |acc, iter| iter.fold(acc, &mut fold)) + .fold(init, flatten(fold)) } } @@ -297,7 +305,7 @@ where if let elt@Some(_) = inner.next_back() { return elt } } match self.iter.next_back() { - None => return self.frontiter.as_mut().and_then(|it| it.next_back()), + None => return self.frontiter.as_mut()?.next_back(), next => self.backiter = next.map(IntoIterator::into_iter), } } @@ -307,22 +315,29 @@ where fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - if let Some(ref mut back) = self.backiter { - init = back.try_rfold(init, &mut fold)?; - } - self.backiter = None; - + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>( + backiter: &'a mut Option<T::IntoIter>, + fold: &'a mut impl FnMut(Acc, T::Item) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a where + T::IntoIter: DoubleEndedIterator, { - let backiter = &mut self.backiter; - init = self.iter.try_rfold(init, |acc, x| { + move |acc, x| { let mut mid = x.into_iter(); - let r = mid.try_rfold(acc, &mut fold); + let r = mid.try_rfold(acc, &mut *fold); *backiter = Some(mid); r - })?; + } + } + + if let Some(ref mut back) = self.backiter { + init = back.try_rfold(init, &mut fold)?; } self.backiter = None; + init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?; + self.backiter = None; + if let Some(ref mut front) = self.frontiter { init = front.try_rfold(init, &mut fold)?; } @@ -332,12 +347,19 @@ where } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { + #[inline] + fn flatten<U: DoubleEndedIterator, Acc>( + fold: &mut impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc + '_ { + move |acc, iter| iter.rfold(acc, &mut *fold) + } + self.frontiter.into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) - .rfold(init, |acc, iter| iter.rfold(acc, &mut fold)) + .rfold(init, flatten(fold)) } } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index b2702902956..a63434abd6c 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1,6 +1,6 @@ use crate::cmp; use crate::fmt; -use crate::ops::Try; +use crate::ops::{Add, AddAssign, Try}; use crate::usize; use crate::intrinsics; @@ -143,6 +143,18 @@ impl<I> Copied<I> { } } +fn copy_fold<T: Copy, Acc>( + mut f: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, &T) -> Acc { + move |acc, &elt| f(acc, elt) +} + +fn copy_try_fold<T: Copy, Acc, R>( + mut f: impl FnMut(Acc, T) -> R, +) -> impl FnMut(Acc, &T) -> R { + move |acc, &elt| f(acc, elt) +} + #[stable(feature = "iter_copied", since = "1.36.0")] impl<'a, I, T: 'a> Iterator for Copied<I> where I: Iterator<Item=&'a T>, T: Copy @@ -157,16 +169,16 @@ impl<'a, I, T: 'a> Iterator for Copied<I> self.it.size_hint() } - fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_fold(init, move |acc, &elt| f(acc, elt)) + self.it.try_fold(init, copy_try_fold(f)) } - fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.fold(init, move |acc, &elt| f(acc, elt)) + self.it.fold(init, copy_fold(f)) } } @@ -178,16 +190,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I> self.it.next_back().copied() } - fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_rfold(init, move |acc, &elt| f(acc, elt)) + self.it.try_rfold(init, copy_try_fold(f)) } - fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.rfold(init, move |acc, &elt| f(acc, elt)) + self.it.rfold(init, copy_fold(f)) } } @@ -248,6 +260,12 @@ impl<I> Cloned<I> { } } +fn clone_try_fold<T: Clone, Acc, R>( + mut f: impl FnMut(Acc, T) -> R, +) -> impl FnMut(Acc, &T) -> R { + move |acc, elt| f(acc, elt.clone()) +} + #[stable(feature = "iter_cloned", since = "1.1.0")] impl<'a, I, T: 'a> Iterator for Cloned<I> where I: Iterator<Item=&'a T>, T: Clone @@ -262,16 +280,16 @@ impl<'a, I, T: 'a> Iterator for Cloned<I> self.it.size_hint() } - fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_fold(init, move |acc, elt| f(acc, elt.clone())) + self.it.try_fold(init, clone_try_fold(f)) } - fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.fold(init, move |acc, elt| f(acc, elt.clone())) + self.it.map(T::clone).fold(init, f) } } @@ -283,16 +301,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> self.it.next_back().cloned() } - fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone())) + self.it.try_rfold(init, clone_try_fold(f)) } - fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.rfold(init, move |acc, elt| f(acc, elt.clone())) + self.it.map(T::clone).rfold(init, f) } } @@ -387,6 +405,36 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator { _ => (usize::MAX, None) } } + + #[inline] + fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + { + // fully iterate the current iterator. this is necessary because + // `self.iter` may be empty even when `self.orig` isn't + acc = self.iter.try_fold(acc, &mut f)?; + self.iter = self.orig.clone(); + + // complete a full cycle, keeping track of whether the cycled + // iterator is empty or not. we need to return early in case + // of an empty iterator to prevent an infinite loop + let mut is_empty = true; + acc = self.iter.try_fold(acc, |acc, x| { + is_empty = false; + f(acc, x) + })?; + + if is_empty { + return Try::from_ok(acc); + } + + loop { + self.iter = self.orig.clone(); + acc = self.iter.try_fold(acc, &mut f)?; + } + } } #[stable(feature = "fused", since = "1.26.0")] @@ -430,14 +478,24 @@ impl<I> Iterator for StepBy<I> where I: Iterator { #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let inner_hint = self.iter.size_hint(); + #[inline] + fn first_size(step: usize) -> impl Fn(usize) -> usize { + move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) } + } + + #[inline] + fn other_size(step: usize) -> impl Fn(usize) -> usize { + move |n| n / (step + 1) + } + + let (low, high) = self.iter.size_hint(); if self.first_take { - let f = |n| if n == 0 { 0 } else { 1 + (n-1)/(self.step+1) }; - (f(inner_hint.0), inner_hint.1.map(f)) + let f = first_size(self.step); + (f(low), high.map(f)) } else { - let f = |n| n / (self.step+1); - (f(inner_hint.0), inner_hint.1.map(f)) + let f = other_size(self.step); + (f(low), high.map(f)) } } @@ -594,6 +652,20 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> { } } +fn map_fold<T, B, Acc>( + mut f: impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, elt| g(acc, f(elt)) +} + +fn map_try_fold<'a, T, B, Acc, R>( + f: &'a mut impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, elt| g(acc, f(elt)) +} + #[stable(feature = "rust1", since = "1.0.0")] impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B { type Item = B; @@ -608,18 +680,16 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B { self.iter.size_hint() } - fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where + fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, elt| g(acc, f(elt))) + self.iter.try_fold(init, map_try_fold(&mut self.f, g)) } - fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc + fn fold<Acc, G>(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, elt| g(acc, f(elt))) + self.iter.fold(init, map_fold(self.f, g)) } } @@ -632,18 +702,16 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where self.iter.next_back().map(&mut self.f) } - fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where + fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt))) + self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) } - fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc + fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, elt| g(acc, f(elt))) + self.iter.rfold(init, map_fold(self.f, g)) } } @@ -710,13 +778,27 @@ impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> { } } +fn filter_fold<T, Acc>( + mut predicate: impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } +} + +fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>( + predicate: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| if predicate(&item) { fold(acc, item) } else { R::from_ok(acc) } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool { type Item = I::Item; #[inline] fn next(&mut self) -> Option<I::Item> { - self.try_for_each(Err).err() + self.iter.find(&mut self.predicate) } #[inline] @@ -738,32 +820,26 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool // leaving more budget for LLVM optimizations. #[inline] fn count(self) -> usize { - let mut predicate = self.predicate; - self.iter.map(|x| predicate(&x) as usize).sum() + #[inline] + fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize { + move |x| predicate(&x) as usize + } + + self.iter.map(to_usize(self.predicate)).sum() } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let predicate = &mut self.predicate; - self.iter.try_fold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - Try::from_ok(acc) - }) + self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold)) } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut predicate = self.predicate; - self.iter.fold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - acc - }) + self.iter.fold(init, filter_fold(self.predicate, fold)) } } @@ -773,31 +849,21 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> { #[inline] fn next_back(&mut self) -> Option<I::Item> { - self.try_rfold((), |_, x| Err(x)).err() + self.iter.rfind(&mut self.predicate) } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let predicate = &mut self.predicate; - self.iter.try_rfold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - Try::from_ok(acc) - }) + self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut predicate = self.predicate; - self.iter.rfold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - acc - }) + self.iter.rfold(init, filter_fold(self.predicate, fold)) } } @@ -834,6 +900,26 @@ impl<I: fmt::Debug, F> fmt::Debug for FilterMap<I, F> { } } +fn filter_map_fold<T, B, Acc>( + mut f: impl FnMut(T) -> Option<B>, + mut fold: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + } +} + +fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>( + f: &'a mut impl FnMut(T) -> Option<B>, + mut fold: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => R::from_ok(acc), + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<B, I: Iterator, F> Iterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B>, @@ -842,7 +928,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> #[inline] fn next(&mut self) -> Option<B> { - self.try_for_each(Err).err() + self.iter.find_map(&mut self.f) } #[inline] @@ -852,25 +938,17 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => Try::from_ok(acc), - }) + self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold)) } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => acc, - }) + self.iter.fold(init, filter_map_fold(self.f, fold)) } } @@ -880,29 +958,31 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> { #[inline] fn next_back(&mut self) -> Option<B> { - self.try_rfold((), |_, x| Err(x)).err() + #[inline] + fn find<T, B>( + f: &mut impl FnMut(T) -> Option<B> + ) -> impl FnMut((), T) -> LoopState<(), B> + '_ { + move |(), x| match f(x) { + Some(x) => LoopState::Break(x), + None => LoopState::Continue(()), + } + } + + self.iter.try_rfold((), find(&mut self.f)).break_value() } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => Try::from_ok(acc), - }) + self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => acc, - }) + self.iter.rfold(init, filter_map_fold(self.f, fold)) } } @@ -944,14 +1024,12 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { /// /// Might panic if the index of the element overflows a `usize`. #[inline] - #[rustc_inherit_overflow_checks] fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> { - self.iter.next().map(|a| { - let ret = (self.count, a); - // Possible undefined overflow. - self.count += 1; - ret - }) + let a = self.iter.next()?; + let i = self.count; + // Possible undefined overflow. + AddAssign::add_assign(&mut self.count, 1); + Some((i, a)) } #[inline] @@ -960,13 +1038,12 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { } #[inline] - #[rustc_inherit_overflow_checks] fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> { - self.iter.nth(n).map(|a| { - let i = self.count + n; - self.count = i + 1; - (i, a) - }) + let a = self.iter.nth(n)?; + // Possible undefined overflow. + let i = Add::add(self.count, n); + self.count = Add::add(i, 1); + Some((i, a)) } #[inline] @@ -975,29 +1052,43 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { } #[inline] - #[rustc_inherit_overflow_checks] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let count = &mut self.count; - self.iter.try_fold(init, move |acc, item| { - let acc = fold(acc, (*count, item)); - *count += 1; - acc - }) + #[inline] + fn enumerate<'a, T, Acc, R>( + count: &'a mut usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { + let acc = fold(acc, (*count, item)); + // Possible undefined overflow. + AddAssign::add_assign(count, 1); + acc + } + } + + self.iter.try_fold(init, enumerate(&mut self.count, fold)) } #[inline] - #[rustc_inherit_overflow_checks] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut count = self.count; - self.iter.fold(init, move |acc, item| { - let acc = fold(acc, (count, item)); - count += 1; - acc - }) + #[inline] + fn enumerate<T, Acc>( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + let acc = fold(acc, (count, item)); + // Possible undefined overflow. + AddAssign::add_assign(&mut count, 1); + acc + } + } + + self.iter.fold(init, enumerate(self.count, fold)) } } @@ -1007,48 +1098,60 @@ impl<I> DoubleEndedIterator for Enumerate<I> where { #[inline] fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> { - self.iter.next_back().map(|a| { - let len = self.iter.len(); - // Can safely add, `ExactSizeIterator` promises that the number of - // elements fits into a `usize`. - (self.count + len, a) - }) + let a = self.iter.next_back()?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) } #[inline] fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> { - self.iter.nth_back(n).map(|a| { - let len = self.iter.len(); - // Can safely add, `ExactSizeIterator` promises that the number of - // elements fits into a `usize`. - (self.count + len, a) - }) + let a = self.iter.nth_back(n)?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. - let mut count = self.count + self.iter.len(); - self.iter.try_rfold(init, move |acc, item| { - count -= 1; - fold(acc, (count, item)) - }) + fn enumerate<T, Acc, R>( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R, + ) -> impl FnMut(Acc, T) -> R { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.try_rfold(init, enumerate(count, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. - let mut count = self.count + self.iter.len(); - self.iter.rfold(init, move |acc, item| { - count -= 1; - fold(acc, (count, item)) - }) + fn enumerate<T, Acc>( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.rfold(init, enumerate(count, fold)) } } @@ -1162,7 +1265,10 @@ impl<I: Iterator> Iterator for Peekable<I> { }; let (lo, hi) = self.iter.size_hint(); let lo = lo.saturating_add(peek_len); - let hi = hi.and_then(|x| x.checked_add(peek_len)); + let hi = match hi { + Some(x) => x.checked_add(peek_len), + None => None, + }; (lo, hi) } @@ -1321,16 +1427,23 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P> #[inline] fn next(&mut self) -> Option<I::Item> { + fn check<'a, T>( + flag: &'a mut bool, + pred: &'a mut impl FnMut(&T) -> bool, + ) -> impl FnMut(&T) -> bool + 'a { + move |x| { + if *flag || !pred(x) { + *flag = true; + true + } else { + false + } + } + } + let flag = &mut self.flag; let pred = &mut self.predicate; - self.iter.find(move |x| { - if *flag || !pred(x) { - *flag = true; - true - } else { - false - } - }) + self.iter.find(check(flag, pred)) } #[inline] @@ -1412,14 +1525,13 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P> if self.flag { None } else { - self.iter.next().and_then(|x| { - if (self.predicate)(&x) { - Some(x) - } else { - self.flag = true; - None - } - }) + let x = self.iter.next()?; + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } } } @@ -1434,22 +1546,30 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P> } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - if self.flag { - Try::from_ok(init) - } else { - let flag = &mut self.flag; - let p = &mut self.predicate; - self.iter.try_fold(init, move |acc, x|{ + fn check<'a, T, Acc, R: Try<Ok = Acc>>( + flag: &'a mut bool, + p: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a { + move |acc, x| { if p(&x) { LoopState::from_try(fold(acc, x)) } else { *flag = true; LoopState::Break(Try::from_ok(acc)) } - }).into_try() + } + } + + if self.flag { + Try::from_ok(init) + } else { + let flag = &mut self.flag; + let p = &mut self.predicate; + self.iter.try_fold(init, check(flag, p, fold)).into_try() } } } @@ -1534,7 +1654,10 @@ impl<I> Iterator for Skip<I> where I: Iterator { let (lower, upper) = self.iter.size_hint(); let lower = lower.saturating_sub(self.n); - let upper = upper.map(|x| x.saturating_sub(self.n)); + let upper = match upper { + Some(x) => Some(x.saturating_sub(self.n)), + None => None, + }; (lower, upper) } @@ -1595,19 +1718,26 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize } } - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let mut n = self.len(); - if n == 0 { - Try::from_ok(init) - } else { - self.iter.try_rfold(init, move |acc, x| { + fn check<T, Acc, R: Try<Ok = Acc>>( + mut n: usize, + mut fold: impl FnMut(Acc, T) -> R, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> { + move |acc, x| { n -= 1; let r = fold(acc, x); if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } - }).into_try() + } + } + + let n = self.len(); + if n == 0 { + Try::from_ok(init) + } else { + self.iter.try_rfold(init, check(n, fold)).into_try() } } } @@ -1682,19 +1812,26 @@ impl<I> Iterator for Take<I> where I: Iterator{ } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - if self.n == 0 { - Try::from_ok(init) - } else { - let n = &mut self.n; - self.iter.try_fold(init, move |acc, x| { + fn check<'a, T, Acc, R: Try<Ok = Acc>>( + n: &'a mut usize, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a { + move |acc, x| { *n -= 1; let r = fold(acc, x); if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } - }).into_try() + } + } + + if self.n == 0 { + Try::from_ok(init) + } else { + let n = &mut self.n; + self.iter.try_fold(init, check(n, fold)).into_try() } } } @@ -1793,7 +1930,8 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where #[inline] fn next(&mut self) -> Option<B> { - self.iter.next().and_then(|a| (self.f)(&mut self.state, a)) + let a = self.iter.next()?; + (self.f)(&mut self.state, a) } #[inline] @@ -1803,17 +1941,25 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { + fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>( + state: &'a mut St, + f: &'a mut impl FnMut(&mut St, T) -> Option<B>, + mut fold: impl FnMut(Acc, B) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a { + move |acc, x| { + match f(state, x) { + None => LoopState::Break(Try::from_ok(acc)), + Some(x) => LoopState::from_try(fold(acc, x)), + } + } + } + let state = &mut self.state; let f = &mut self.f; - self.iter.try_fold(init, move |acc, x| { - match f(state, x) { - None => LoopState::Break(Try::from_ok(acc)), - Some(x) => LoopState::from_try(fold(acc, x)), - } - }).into_try() + self.iter.try_fold(init, scan(state, f, fold)).into_try() } } @@ -2104,6 +2250,20 @@ impl<I: Iterator, F> Inspect<I, F> where F: FnMut(&I::Item) { } } +fn inspect_fold<T, Acc>( + mut f: impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { f(&item); fold(acc, item) } +} + +fn inspect_try_fold<'a, T, Acc, R>( + f: &'a mut impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { f(&item); fold(acc, item) } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) { type Item = I::Item; @@ -2120,19 +2280,17 @@ impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) { } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold)) } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.fold(init, inspect_fold(self.f, fold)) } } @@ -2147,19 +2305,17 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F> } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.rfold(init, inspect_fold(self.f, fold)) } } diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs index 06f047d9287..430ceacdd9f 100644 --- a/src/libcore/iter/adapters/zip.rs +++ b/src/libcore/iter/adapters/zip.rs @@ -94,11 +94,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> #[inline] default fn next(&mut self) -> Option<(A::Item, B::Item)> { - self.a.next().and_then(|x| { - self.b.next().and_then(|y| { - Some((x, y)) - }) - }) + let x = self.a.next()?; + let y = self.b.next()?; + Some((x, y)) } #[inline] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 70a3b70c180..183176005ed 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -394,7 +394,8 @@ impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> { #[inline] fn next(&mut self) -> Option<A> { - self.gen.take().map(|f| f()) + let f = self.gen.take()?; + Some(f()) } #[inline] @@ -608,10 +609,9 @@ impl<T, F> Iterator for Successors<T, F> #[inline] fn next(&mut self) -> Option<Self::Item> { - self.next.take().map(|item| { - self.next = (self.succ)(&item); - item - }) + let item = self.next.take()?; + self.next = (self.succ)(&item); + Some(item) } #[inline] diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index 812463e77f9..818f0330329 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -85,28 +85,28 @@ macro_rules! float_sum_product { #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum<I: Iterator<Item=$a>>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + b) + iter.fold(0.0, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product<I: Iterator<Item=$a>>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * b) + iter.fold(1.0, Mul::mul) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + *b) + iter.fold(0.0, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * *b) + iter.fold(1.0, Mul::mul) } } )*) diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index 2c1aeb5690a..006b243ca42 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -69,7 +69,7 @@ pub trait DoubleEndedIterator: Iterator { /// Returns the `n`th element from the end of the iterator. /// /// This is essentially the reversed version of [`nth`]. Although like most indexing - /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro + /// operations, the count starts from zero, so `nth_back(0)` returns the first value from /// the end, `nth_back(1)` the second, and so on. /// /// Note that all elements between the end and the returned element will be @@ -219,12 +219,17 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] - fn rfold<B, F>(mut self, accum: B, mut f: F) -> B + fn rfold<B, F>(mut self, accum: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap() + #[inline] + fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { + move |acc, x| Ok(f(acc, x)) + } + + self.try_rfold(accum, ok(f)).unwrap() } /// Searches for an element of an iterator from the back that satisfies a predicate. @@ -271,15 +276,21 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item> + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool { - self.try_rfold((), move |(), x| { - if predicate(&x) { LoopState::Break(x) } - else { LoopState::Continue(()) } - }).break_value() + #[inline] + fn check<T>( + mut predicate: impl FnMut(&T) -> bool, + ) -> impl FnMut((), T) -> LoopState<(), T> { + move |(), x| { + if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) } + } + } + + self.try_rfold((), check(predicate)).break_value() } } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 7e941267ce8..d644787d2c4 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1,5 +1,5 @@ use crate::cmp::Ordering; -use crate::ops::Try; +use crate::ops::{Add, Try}; use super::super::LoopState; use super::super::{Chain, Cycle, Copied, Cloned, Enumerate, Filter, FilterMap, Fuse}; @@ -234,11 +234,15 @@ pub trait Iterator { /// assert_eq!(a.iter().count(), 5); /// ``` #[inline] - #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] fn count(self) -> usize where Self: Sized { - // Might overflow. - self.fold(0, |cnt, _| cnt + 1) + #[inline] + fn add1<T>(count: usize, _: T) -> usize { + // Might overflow. + Add::add(count, 1) + } + + self.fold(0, add1) } /// Consumes the iterator, returning the last element. @@ -263,7 +267,12 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn last(self) -> Option<Self::Item> where Self: Sized { - self.fold(None, |_, x| Some(x)) + #[inline] + fn some<T>(_: Option<T>, x: T) -> Option<T> { + Some(x) + } + + self.fold(None, some) } /// Returns the `n`th element of the iterator. @@ -596,10 +605,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] - fn for_each<F>(self, mut f: F) where + fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), { - self.fold((), move |(), item| f(item)); + #[inline] + fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) { + move |(), item| f(item) + } + + self.fold((), call(f)); } /// Creates an iterator which uses a closure to determine if an element @@ -1490,21 +1504,30 @@ pub trait Iterator { /// assert_eq!(odd, vec![1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn partition<B, F>(self, mut f: F) -> (B, B) where + fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool { + #[inline] + fn extend<'a, T, B: Extend<T>>( + mut f: impl FnMut(&T) -> bool + 'a, + left: &'a mut B, + right: &'a mut B, + ) -> impl FnMut(T) + 'a { + move |x| { + if f(&x) { + left.extend(Some(x)); + } else { + right.extend(Some(x)); + } + } + } + let mut left: B = Default::default(); let mut right: B = Default::default(); - self.for_each(|x| { - if f(&x) { - left.extend(Some(x)) - } else { - right.extend(Some(x)) - } - }); + self.for_each(extend(f, &mut left, &mut right)); (left, right) } @@ -1702,10 +1725,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_for_each<F, R>(&mut self, mut f: F) -> R where + fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Ok=()> { - self.try_fold((), move |(), x| f(x)) + #[inline] + fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { + move |(), x| f(x) + } + + self.try_fold((), call(f)) } /// An iterator method that applies a function, producing a single, final value. @@ -1777,10 +1805,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn fold<B, F>(mut self, init: B, mut f: F) -> B where + fn fold<B, F>(mut self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap() + #[inline] + fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { + move |acc, x| Ok(f(acc, x)) + } + + self.try_fold(init, ok(f)).unwrap() } /// Tests if every element of the iterator matches a predicate. @@ -1822,13 +1855,18 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn all<F>(&mut self, mut f: F) -> bool where + fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - self.try_for_each(move |x| { - if f(x) { LoopState::Continue(()) } - else { LoopState::Break(()) } - }) == LoopState::Continue(()) + #[inline] + fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { + if f(x) { LoopState::Continue(()) } + else { LoopState::Break(()) } + } + } + + self.try_for_each(check(f)) == LoopState::Continue(()) } /// Tests if any element of the iterator matches a predicate. @@ -1870,14 +1908,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn any<F>(&mut self, mut f: F) -> bool where + fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - self.try_for_each(move |x| { - if f(x) { LoopState::Break(()) } - else { LoopState::Continue(()) } - }) == LoopState::Break(()) + #[inline] + fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { + if f(x) { LoopState::Break(()) } + else { LoopState::Continue(()) } + } + } + + self.try_for_each(check(f)) == LoopState::Break(()) } /// Searches for an element of an iterator that satisfies a predicate. @@ -1924,14 +1967,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where + fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, { - self.try_for_each(move |x| { - if predicate(&x) { LoopState::Break(x) } - else { LoopState::Continue(()) } - }).break_value() + #[inline] + fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> { + move |x| { + if predicate(&x) { LoopState::Break(x) } + else { LoopState::Continue(()) } + } + } + + self.try_for_each(check(predicate)).break_value() } /// Applies function to the elements of iterator and returns @@ -1951,16 +1999,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] - fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where + fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, { - self.try_for_each(move |x| { - match f(x) { + #[inline] + fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut(T) -> LoopState<(), B> { + move |x| match f(x) { Some(x) => LoopState::Break(x), None => LoopState::Continue(()), } - }).break_value() + } + + self.try_for_each(check(f)).break_value() } /// Searches for an element in an iterator, returning its index. @@ -2018,17 +2069,23 @@ pub trait Iterator { /// /// ``` #[inline] - #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] - fn position<P>(&mut self, mut predicate: P) -> Option<usize> where + fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, { - // The addition might panic on overflow - self.try_fold(0, move |i, x| { - if predicate(x) { LoopState::Break(i) } - else { LoopState::Continue(i + 1) } - }).break_value() + #[inline] + fn check<T>( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> LoopState<usize, usize> { + // The addition might panic on overflow + move |i, x| { + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(Add::add(i, 1)) } + } + } + + self.try_fold(0, check(predicate)).break_value() } /// Searches for an element in an iterator from the right, returning its @@ -2071,18 +2128,25 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where + fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator { // No need for an overflow check here, because `ExactSizeIterator` // implies that the number of elements fits into a `usize`. + #[inline] + fn check<T>( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> LoopState<usize, usize> { + move |i, x| { + let i = i - 1; + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(i) } + } + } + let n = self.len(); - self.try_rfold(n, move |i, x| { - let i = i - 1; - if predicate(x) { LoopState::Break(i) } - else { LoopState::Continue(i) } - }).break_value() + self.try_rfold(n, check(predicate)).break_value() } /// Returns the maximum element of an iterator. @@ -2151,11 +2215,22 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item> + fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item) -> B, { + #[inline] + fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + // switch to y even if it is only equal, to preserve stability. - select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x) + #[inline] + fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool { + x_p <= y_p + } + + let (_, x) = select_fold1(self.map(key(f)), select)?; + Some(x) } /// Returns the element that gives the maximum value with respect to the @@ -2174,11 +2249,16 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] - fn max_by<F>(self, mut compare: F) -> Option<Self::Item> + fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { // switch to y even if it is only equal, to preserve stability. - select_fold1(self, |x, y| compare(x, y) != Ordering::Greater) + #[inline] + fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool { + move |x, y| compare(x, y) != Ordering::Greater + } + + select_fold1(self, select(compare)) } /// Returns the element that gives the minimum value from the @@ -2195,12 +2275,24 @@ pub trait Iterator { /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0); /// ``` + #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item> + fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item) -> B, { + #[inline] + fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + // only switch to y if it is strictly smaller, to preserve stability. - select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x) + #[inline] + fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool { + x_p > y_p + } + + let (_, x) = select_fold1(self.map(key(f)), select)?; + Some(x) } /// Returns the element that gives the minimum value with respect to the @@ -2219,11 +2311,16 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] - fn min_by<F>(self, mut compare: F) -> Option<Self::Item> + fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { // only switch to y if it is strictly smaller, to preserve stability. - select_fold1(self, |x, y| compare(x, y) == Ordering::Greater) + #[inline] + fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool { + move |x, y| compare(x, y) == Ordering::Greater + } + + select_fold1(self, select(compare)) } @@ -2284,13 +2381,20 @@ pub trait Iterator { FromB: Default + Extend<B>, Self: Sized + Iterator<Item=(A, B)>, { + fn extend<'a, A, B>( + ts: &'a mut impl Extend<A>, + us: &'a mut impl Extend<B>, + ) -> impl FnMut((A, B)) + 'a { + move |(t, u)| { + ts.extend(Some(t)); + us.extend(Some(u)); + } + } + let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); - self.for_each(|(t, u)| { - ts.extend(Some(t)); - us.extend(Some(u)); - }); + self.for_each(extend(&mut ts, &mut us)); (ts, us) } @@ -2617,7 +2721,7 @@ pub trait Iterator { Self: Sized, Self::Item: PartialOrd, { - self.is_sorted_by(|a, b| a.partial_cmp(b)) + self.is_sorted_by(PartialOrd::partial_cmp) } /// Checks if the elements of this iterator are sorted using the given comparator function. @@ -2639,10 +2743,7 @@ pub trait Iterator { }; while let Some(curr) = self.next() { - if compare(&last, &curr) - .map(|o| o == Ordering::Greater) - .unwrap_or(true) - { + if let Some(Ordering::Greater) | None = compare(&last, &curr) { return false; } last = curr; @@ -2687,17 +2788,21 @@ pub trait Iterator { /// commonalities of {max,min}{,_by}. In particular, this avoids /// having to implement optimizations several times. #[inline] -fn select_fold1<I, F>(mut it: I, mut f: F) -> Option<I::Item> +fn select_fold1<I, F>(mut it: I, f: F) -> Option<I::Item> where I: Iterator, F: FnMut(&I::Item, &I::Item) -> bool, { + #[inline] + fn select<T>(mut f: impl FnMut(&T, &T) -> bool) -> impl FnMut(T, T) -> T { + move |sel, x| if f(&sel, &x) { x } else { sel } + } + // start with the first element as our selection. This avoids // having to use `Option`s inside the loop, translating to a // sizeable performance gain (6x in one case). - it.next().map(|first| { - it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel }) - }) + let first = it.next()?; + Some(it.fold(first, select(f))) } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 678ff768792..c168d5c8a2e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -63,7 +63,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] @@ -129,7 +129,7 @@ #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(mem_take)] #![feature(associated_type_bounds)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f9dc53874ac..6c88a766a2f 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -2,21 +2,21 @@ /// /// For details, see `std::macros`. #[macro_export] -#[allow_internal_unstable(core_panic, __rust_unstable_column)] +#[allow_internal_unstable(core_panic)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( $crate::panic!("explicit panic") ); ($msg:expr) => ({ - $crate::panicking::panic(&($msg, file!(), line!(), __rust_unstable_column!())) + $crate::panicking::panic(&($msg, $crate::file!(), $crate::line!(), $crate::column!())) }); ($msg:expr,) => ( $crate::panic!($msg) ); ($fmt:expr, $($arg:tt)+) => ({ - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)+), - &(file!(), line!(), __rust_unstable_column!())) + $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), + &($crate::file!(), $crate::line!(), $crate::column!())) }); } @@ -70,7 +70,7 @@ macro_rules! assert_eq { panic!(r#"assertion failed: `(left == right)` left: `{:?}`, right: `{:?}`: {}"#, &*left_val, &*right_val, - format_args!($($arg)+)) + $crate::format_args!($($arg)+)) } } } @@ -127,7 +127,7 @@ macro_rules! assert_ne { panic!(r#"assertion failed: `(left != right)` left: `{:?}`, right: `{:?}`: {}"#, &*left_val, &*right_val, - format_args!($($arg)+)) + $crate::format_args!($($arg)+)) } } } @@ -181,7 +181,7 @@ macro_rules! assert_ne { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); }) } /// Asserts that two expressions are equal to each other. @@ -208,7 +208,7 @@ macro_rules! debug_assert { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); }) } /// Asserts that two expressions are not equal to each other. @@ -235,7 +235,7 @@ macro_rules! debug_assert_eq { #[macro_export] #[stable(feature = "assert_ne", since = "1.13.0")] macro_rules! debug_assert_ne { - ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) } /// Unwraps a result or propagates its error. @@ -386,7 +386,7 @@ macro_rules! r#try { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! write { - ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*))) + ($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*))) } /// Write formatted data into a buffer, with a newline appended. @@ -446,7 +446,7 @@ macro_rules! writeln { $crate::writeln!($dst) ); ($dst:expr, $($arg:tt)*) => ( - $dst.write_fmt(format_args_nl!($($arg)*)) + $dst.write_fmt($crate::format_args_nl!($($arg)*)) ); } @@ -515,7 +515,7 @@ macro_rules! unreachable { $crate::unreachable!($msg) }); ($fmt:expr, $($arg:tt)*) => ({ - panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) }); } @@ -573,7 +573,7 @@ macro_rules! unreachable { #[stable(feature = "rust1", since = "1.0.0")] macro_rules! unimplemented { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); + ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } /// Indicates unfinished code. @@ -632,41 +632,7 @@ macro_rules! unimplemented { #[unstable(feature = "todo_macro", issue = "59277")] macro_rules! todo { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Remove both versions of this macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(bootstrap)] -macro_rules! uninit_array { - // This `assume_init` is safe because an array of `MaybeUninit` does not - // require initialization. - ($t:ty; $size:expr) => (unsafe { - MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init() - }); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Just inline this version of the macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(not(bootstrap))] -macro_rules! uninit_array { - ($t:ty; $size:expr) => ( - [MaybeUninit::<$t>::UNINIT; $size] - ); + ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } /// Definitions of built-in macros. @@ -674,7 +640,6 @@ macro_rules! uninit_array { /// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, /// with exception of expansion functions transforming macro inputs into outputs, /// those functions are provided by the compiler. -#[cfg(not(bootstrap))] pub(crate) mod builtin { /// Causes compilation to fail with the given error message when encountered. @@ -962,13 +927,6 @@ pub(crate) mod builtin { #[macro_export] macro_rules! column { () => { /* compiler built-in */ } } - /// Same as `column`, but less likely to be shadowed. - #[unstable(feature = "__rust_unstable_column", issue = "0", - reason = "internal implementation detail of the `panic` macro")] - #[rustc_builtin_macro] - #[macro_export] - macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } } - /// Expands to the file name in which it was invoked. /// /// With [`line!`] and [`column!`], these macros provide debugging information for @@ -1305,14 +1263,14 @@ pub(crate) mod builtin { /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)] pub macro RustcDecodable($item:item) { /* compiler built-in */ } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics)] pub macro RustcEncodable($item:item) { /* compiler built-in */ } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 78a27361165..89af2528c05 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -289,9 +289,8 @@ pub trait Copy : Clone { } /// Derive macro generating an impl of the trait `Copy`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Copy($item:item) { /* compiler built-in */ } diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 1bbea02e0c7..9e9e901c76d 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -213,7 +213,7 @@ use crate::mem::ManuallyDrop; #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] // Lang item so we can wrap other types in it. This is useful for generators. -#[cfg_attr(not(bootstrap), lang = "maybe_uninit")] +#[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] pub union MaybeUninit<T> { @@ -312,7 +312,7 @@ impl<T> MaybeUninit<T> { /// without dropping it, so be careful not to use this twice unless you want to /// skip running the destructor. For your convenience, this also returns a mutable /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { unsafe { @@ -502,7 +502,7 @@ impl<T> MaybeUninit<T> { /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::<T>(); @@ -516,7 +516,7 @@ impl<T> MaybeUninit<T> { /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized /// state. Calling this when the content is not yet fully initialized causes undefined /// behavior. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { &*self.value @@ -532,21 +532,21 @@ impl<T> MaybeUninit<T> { // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { &mut *self.value } /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T { this as *const [MaybeUninit<T>] as *const T } /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T { this as *mut [MaybeUninit<T>] as *mut T diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 2534400b833..87ec05a243d 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -453,7 +453,7 @@ pub const fn needs_drop<T>() -> bool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn zeroed<T>() -> T { intrinsics::panic_if_uninhabited::<T>(); @@ -481,7 +481,7 @@ pub unsafe fn zeroed<T>() -> T { #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn uninitialized<T>() -> T { intrinsics::panic_if_uninhabited::<T>(); diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 67e30e7ffcb..b46e06f8d8a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,7 +1112,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -1135,7 +1141,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -1157,7 +1169,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_mul(self, rhs) + } } } @@ -3031,7 +3049,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -3053,7 +3077,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -3076,7 +3106,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_mul(self, rhs) + } } doc_comment! { diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 84cf85f339c..7cc279a9ef2 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -46,20 +46,16 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::fmt::macros::Debug; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::hash::macros::Hash; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::{ - __rust_unstable_column, asm, assert, cfg, @@ -83,7 +79,6 @@ pub use crate::{ trace_macros, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(no_inline)] diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index f0d011fe6b2..3521dd79979 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -122,6 +122,14 @@ impl<T: ?Sized> Unique<T> { pub unsafe fn as_mut(&mut self) -> &mut T { &mut *self.as_ptr() } + + /// Casts to a pointer of another type. + #[inline] + pub const fn cast<U>(self) -> Unique<U> { + unsafe { + Unique::new_unchecked(self.as_ptr() as *mut U) + } + } } #[unstable(feature = "ptr_internals", issue = "0")] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ce5af13d4ca..bfbbb15c8d4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4637,6 +4637,22 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'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 = start + self.chunk_size; + 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 = "chunks_exact", since = "1.31.0")] diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs index 3db70d5e764..fec17c4d1a4 100644 --- a/src/libcore/task/poll.rs +++ b/src/libcore/task/poll.rs @@ -81,6 +81,34 @@ impl<T, E> Poll<Result<T, E>> { } } +impl<T, E> Poll<Option<Result<T, E>>> { + /// Changes the success value of this `Poll` with the closure provided. + #[unstable(feature = "poll_map", issue = "63514")] + pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> + where F: FnOnce(T) -> U + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } + + /// Changes the error value of this `Poll` with the closure provided. + #[unstable(feature = "poll_map", issue = "63514")] + pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> + where F: FnOnce(E) -> U + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} + #[stable(feature = "futures_api", since = "1.36.0")] impl<T> From<T> for Poll<T> { fn from(t: T) -> Poll<T> { diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3615fab7915..3a4f76852a0 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -104,6 +104,22 @@ fn test_iterator_chain_nth() { } #[test] +fn test_iterator_chain_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let ys = [30, 40, 50, 60]; + let zs = []; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + for (i, x) in expected.iter().rev().enumerate() { + assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i)); + } + assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5)); + + let mut it = xs.iter().chain(&zs); + assert_eq!(it.nth_back(5), Some(&0)); + assert_eq!(it.next(), None); +} + +#[test] fn test_iterator_chain_last() { let xs = [0, 1, 2, 3, 4, 5]; let ys = [30, 40, 50, 60]; @@ -137,6 +153,54 @@ fn test_iterator_chain_find() { } #[test] +fn test_iterator_chain_size_hint() { + struct Iter { + is_empty: bool, + } + + impl Iterator for Iter { + type Item = (); + + // alternates between `None` and `Some(())` + fn next(&mut self) -> Option<Self::Item> { + if self.is_empty { + self.is_empty = false; + None + } else { + self.is_empty = true; + Some(()) + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + if self.is_empty { + (0, Some(0)) + } else { + (1, Some(1)) + } + } + } + + impl DoubleEndedIterator for Iter { + fn next_back(&mut self) -> Option<Self::Item> { + self.next() + } + } + + // this chains an iterator of length 0 with an iterator of length 1, + // so after calling `.next()` once, the iterator is empty and the + // state is `ChainState::Back`. `.size_hint()` should now disregard + // the size hint of the left iterator + let mut iter = Iter { is_empty: true }.chain(once(())); + assert_eq!(iter.next(), Some(())); + assert_eq!(iter.size_hint(), (0, Some(0))); + + let mut iter = once(()).chain(Iter { is_empty: true }); + assert_eq!(iter.next_back(), Some(())); + assert_eq!(iter.size_hint(), (0, Some(0))); +} + +#[test] fn test_zip_nth() { let xs = [0, 1, 2, 4, 5]; let ys = [10, 11, 12]; @@ -1136,6 +1200,18 @@ fn test_cycle() { assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0); assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4); + + assert_eq!((0..10).cycle().take(5).sum::<i32>(), 10); + assert_eq!((0..10).cycle().take(15).sum::<i32>(), 55); + assert_eq!((0..10).cycle().take(25).sum::<i32>(), 100); + + let mut iter = (0..10).cycle(); + iter.nth(14); + assert_eq!(iter.take(8).sum::<i32>(), 38); + + let mut iter = (0..10).cycle(); + iter.nth(9); + assert_eq!(iter.take(3).sum::<i32>(), 3); } #[test] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 4790152512a..6609bc3135a 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -375,6 +375,25 @@ fn test_chunks_exact_mut_nth() { } #[test] +fn test_chunks_exact_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.chunks_exact_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c2 = v2.chunks_exact_mut(3); + assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]); + assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c3 = v3.chunks_exact_mut(10); + assert_eq!(c3.nth_back(0), None); +} + +#[test] fn test_chunks_exact_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let c = v.chunks_exact_mut(2); |
