diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 990de541b6783..23d6edd6d794e 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -50,6 +50,7 @@ #![feature(specialization)] #![feature(staged_api)] #![feature(step_by)] +#![feature(trusted_len)] #![feature(unicode)] #![feature(unique)] #![cfg_attr(test, feature(rand, test))] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f3d78c20a4d6b..053dcd8272e29 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -68,7 +68,7 @@ use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; -use core::iter::{FromIterator, FusedIterator}; +use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; use core::ops::{Index, IndexMut}; use core::ops; @@ -76,7 +76,6 @@ use core::ptr; use core::ptr::Shared; use core::slice; -use super::SpecExtend; use super::range::RangeArgument; /// A contiguous growable array type, written `Vec` but pronounced 'vector.' @@ -1212,26 +1211,7 @@ impl Vec { /// ``` #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] pub fn extend_from_slice(&mut self, other: &[T]) { - self.reserve(other.len()); - - // Unsafe code so this can be optimised to a memcpy (or something - // similarly fast) when T is Copy. LLVM is easily confused, so any - // extra operations during the loop can prevent this optimisation. - unsafe { - let len = self.len(); - let ptr = self.get_unchecked_mut(len) as *mut T; - // Use SetLenOnDrop to work around bug where compiler - // may not realize the store through `ptr` trough self.set_len() - // don't alias. - let mut local_len = SetLenOnDrop::new(&mut self.len); - - for i in 0..other.len() { - ptr::write(ptr.offset(i as isize), other.get_unchecked(i).clone()); - local_len.increment_len(1); - } - - // len set by scope guard - } + self.extend(other.iter().cloned()) } } @@ -1573,19 +1553,25 @@ impl<'a, T> IntoIterator for &'a mut Vec { impl Extend for Vec { #[inline] fn extend>(&mut self, iter: I) { - >::spec_extend(self, iter); + self.extend_desugared(iter.into_iter()) } } -impl SpecExtend for Vec { - default fn spec_extend(&mut self, iter: I) { - self.extend_desugared(iter.into_iter()) - } +trait IsTrustedLen : Iterator { + fn trusted_len(&self) -> Option { None } } +impl IsTrustedLen for I where I: Iterator { } -impl SpecExtend> for Vec { - fn spec_extend(&mut self, ref mut other: Vec) { - self.append(other); +impl IsTrustedLen for I where I: TrustedLen +{ + fn trusted_len(&self) -> Option { + let (low, high) = self.size_hint(); + if let Some(high_value) = high { + debug_assert_eq!(low, high_value, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high)); + } + high } } @@ -1596,16 +1582,30 @@ impl Vec { // for item in iterator { // self.push(item); // } - while let Some(element) = iterator.next() { - let len = self.len(); - if len == self.capacity() { - let (lower, _) = iterator.size_hint(); - self.reserve(lower.saturating_add(1)); - } + if let Some(additional) = iterator.trusted_len() { + self.reserve(additional); unsafe { - ptr::write(self.get_unchecked_mut(len), element); - // NB can't overflow since we would have had to alloc the address space - self.set_len(len + 1); + let mut ptr = self.as_mut_ptr().offset(self.len() as isize); + let mut local_len = SetLenOnDrop::new(&mut self.len); + for element in iterator { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + } + } + } else { + while let Some(element) = iterator.next() { + let len = self.len(); + if len == self.capacity() { + let (lower, _) = iterator.size_hint(); + self.reserve(lower.saturating_add(1)); + } + unsafe { + ptr::write(self.get_unchecked_mut(len), element); + // NB can't overflow since we would have had to alloc the address space + self.set_len(len + 1); + } } } } @@ -1614,24 +1614,7 @@ impl Vec { #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { fn extend>(&mut self, iter: I) { - >::extend_vec(iter, self); - } -} - -// helper trait for specialization of Vec's Extend impl -trait SpecExtendVec { - fn extend_vec(self, vec: &mut Vec); -} - -impl <'a, T: 'a + Copy, I: IntoIterator> SpecExtendVec for I { - default fn extend_vec(self, vec: &mut Vec) { - vec.extend(self.into_iter().cloned()); - } -} - -impl<'a, T: Copy> SpecExtendVec for &'a [T] { - fn extend_vec(self, vec: &mut Vec) { - vec.extend_from_slice(self); + self.extend(iter.into_iter().map(|&x| x)) } } @@ -1948,6 +1931,9 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] impl Clone for IntoIter { fn clone(&self) -> IntoIter { diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 9eeb2608071c2..58d04218e072c 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -328,6 +328,8 @@ pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; pub use self::traits::{ExactSizeIterator, Sum, Product}; #[unstable(feature = "fused", issue = "35602")] pub use self::traits::FusedIterator; +#[unstable(feature = "trusted_len", issue = "37572")] +pub use self::traits::TrustedLen; mod iterator; mod range; @@ -372,6 +374,10 @@ impl ExactSizeIterator for Rev impl FusedIterator for Rev where I: FusedIterator + DoubleEndedIterator {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Rev + where I: TrustedLen + DoubleEndedIterator {} + /// An iterator that clones the elements of an underlying iterator. /// /// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its @@ -432,6 +438,12 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned fn may_have_side_effect() -> bool { true } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, I, T: 'a> TrustedLen for Cloned + where I: TrustedLen, + T: Clone +{} + /// An iterator that repeats endlessly. /// /// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its @@ -642,6 +654,11 @@ impl FusedIterator for Chain B: FusedIterator, {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Chain + where A: TrustedLen, B: TrustedLen, +{} + /// An iterator that iterates two other iterators simultaneously. /// /// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its @@ -859,6 +876,11 @@ unsafe impl TrustedRandomAccess for Zip impl FusedIterator for Zip where A: FusedIterator, B: FusedIterator, {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Zip + where A: TrustedLen, B: TrustedLen, +{} + /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map()`] method on [`Iterator`]. See its @@ -959,6 +981,11 @@ impl ExactSizeIterator for Map impl FusedIterator for Map where F: FnMut(I::Item) -> B {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Map + where I: TrustedLen, + F: FnMut(I::Item) -> B {} + #[doc(hidden)] unsafe impl TrustedRandomAccess for Map where I: TrustedRandomAccess, @@ -1195,6 +1222,12 @@ unsafe impl TrustedRandomAccess for Enumerate #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Enumerate where I: FusedIterator {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Enumerate + where I: TrustedLen, +{} + + /// An iterator with a `peek()` that returns an optional reference to the next /// element. /// diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index eaa3d50c88ade..7c96be2facb48 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -12,7 +12,7 @@ use mem; use ops::{self, Add, Sub}; use usize; -use super::FusedIterator; +use super::{FusedIterator, TrustedLen}; /// Objects that can be stepped over in both directions. /// @@ -480,6 +480,22 @@ macro_rules! range_incl_exact_iter_impl { )*) } +macro_rules! range_trusted_len_impl { + ($($t:ty)*) => ($( + #[unstable(feature = "trusted_len", issue = "37572")] + unsafe impl TrustedLen for ops::Range<$t> { } + )*) +} + +macro_rules! range_incl_trusted_len_impl { + ($($t:ty)*) => ($( + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + unsafe impl TrustedLen for ops::RangeInclusive<$t> { } + )*) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ops::Range where for<'a> &'a A: Add<&'a A, Output = A> @@ -513,6 +529,13 @@ impl Iterator for ops::Range where range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); range_incl_exact_iter_impl!(u8 u16 i8 i16); +// These macros generate `TrustedLen` impls. +// +// They need to guarantee that .size_hint() is either exact, or that +// the upper bound is None when it does not fit the type limits. +range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); +range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); + #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for ops::Range where for<'a> &'a A: Add<&'a A, Output = A>, diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index b55d6f96af9bf..2b0dd63a5714a 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -665,3 +665,22 @@ pub trait FusedIterator: Iterator {} #[unstable(feature = "fused", issue = "35602")] impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} + +/// An iterator that reports an accurate length using size_hint. +/// +/// The iterator reports a size hint where it is either exact +/// (lower bound is equal to upper bound), or the upper bound is `None`. +/// The upper bound must only be `None` if the actual iterator length is +/// larger than `usize::MAX`. +/// +/// The iterator must produce exactly the number of elements it reported. +/// +/// # Safety +/// +/// This trait must only be implemented when the contract is upheld. +/// Consumers of this trait must inspect `.size_hint()`’s upper bound. +#[unstable(feature = "trusted_len", issue = "37572")] +pub unsafe trait TrustedLen : Iterator {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, I: TrustedLen + ?Sized> TrustedLen for &'a mut I {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index cb18feff73422..063adc2ac9f8a 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -145,7 +145,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use iter::{FromIterator, FusedIterator}; +use iter::{FromIterator, FusedIterator, TrustedLen}; use mem; // Note that this is not a lang item per se, but it has a hidden dependency on @@ -803,6 +803,7 @@ impl DoubleEndedIterator for Item { impl ExactSizeIterator for Item {} impl FusedIterator for Item {} +unsafe impl TrustedLen for Item {} /// An iterator over a reference of the contained item in an [`Option`]. /// @@ -833,6 +834,9 @@ impl<'a, A> ExactSizeIterator for Iter<'a, A> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, A> FusedIterator for Iter<'a, A> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> Clone for Iter<'a, A> { fn clone(&self) -> Iter<'a, A> { @@ -868,6 +872,8 @@ impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, A> FusedIterator for IterMut<'a, A> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} /// An iterator over the item contained inside an [`Option`]. /// @@ -898,6 +904,9 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + ///////////////////////////////////////////////////////////////////////////// // FromIterator ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 96845259299be..bae1eda7c4a9b 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -249,7 +249,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use fmt; -use iter::{FromIterator, FusedIterator}; +use iter::{FromIterator, FusedIterator, TrustedLen}; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). /// @@ -886,6 +886,9 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Iter<'a, T> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { inner: self.inner } } @@ -924,6 +927,9 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for IterMut<'a, T> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} + /// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is /// created by the [`into_iter`] method on [`Result`][`Result`] (provided by /// the [`IntoIterator`] trait). @@ -961,6 +967,9 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + ///////////////////////////////////////////////////////////////////////////// // FromIterator ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 31be404ba905a..871b63145ca6d 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -988,6 +988,9 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Iter<'a, T> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, T> TrustedLen for Iter<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } } @@ -1109,6 +1112,9 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for IterMut<'a, T> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {} + /// An internal abstraction over the splitting iterators, so that /// splitn, splitn_mut etc can be implemented once. #[doc(hidden)]