implement TrustedLen for StepBy

This commit is contained in:
The8472 2021-05-20 00:29:20 +02:00 committed by The 8472
parent e927184629
commit a2a7caacf7
3 changed files with 24 additions and 9 deletions

View File

@ -1,7 +1,7 @@
use crate::convert::TryFrom; use crate::convert::TryFrom;
use crate::{ use crate::{
intrinsics, intrinsics,
iter::{from_fn, TrustedLen}, iter::{from_fn, TrustedLen, TrustedRandomAccess},
ops::{Range, Try}, ops::{Range, Try},
}; };
@ -124,6 +124,14 @@ fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
#[stable(feature = "iterator_step_by", since = "1.28.0")] #[stable(feature = "iterator_step_by", since = "1.28.0")]
impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {} impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly.
// These requirements can only be satisfied when the upper bound of the inner iterator's upper
// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while
// I: TrustedLen would not.
// This also covers the Range specializations since the ranges also implement TRA
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<I> TrustedLen for StepBy<I> where I: Iterator + TrustedRandomAccess {}
trait SpecRangeSetup<T> { trait SpecRangeSetup<T> {
fn setup(inner: T, step: usize) -> T; fn setup(inner: T, step: usize) -> T;
} }
@ -480,12 +488,6 @@ fn spec_fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
acc acc
} }
} }
/// Safety: This macro is only applied to ranges over types <= usize
/// which means the inner length is guaranteed to fit into a usize and so
/// the outer length calculation won't encounter clamped values
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl TrustedLen for StepBy<Range<$t>> {}
)*) )*)
} }

View File

@ -220,7 +220,8 @@ fn size_hint(&self) -> (usize, Option<usize>) {
assert_eq!(it.len(), 3); assert_eq!(it.len(), 3);
// Cannot be TrustedLen as a step greater than one makes an iterator // Cannot be TrustedLen as a step greater than one makes an iterator
// with (usize::MAX, None) no longer meet the safety requirements // with (usize::MAX, None) no longer meet the safety requirements.
// Exception: The inner iterator is known to have a len() <= usize::MAX
trait TrustedLenCheck { trait TrustedLenCheck {
fn test(self) -> bool; fn test(self) -> bool;
} }
@ -235,7 +236,9 @@ fn test(self) -> bool {
} }
} }
assert!(TrustedLenCheck::test(a.iter())); assert!(TrustedLenCheck::test(a.iter()));
assert!(!TrustedLenCheck::test(a.iter().step_by(1))); assert!(TrustedLenCheck::test(a.iter().step_by(1)));
assert!(TrustedLenCheck::test(a.iter().chain(a.iter())));
assert!(!TrustedLenCheck::test(a.iter().chain(a.iter()).step_by(1)));
} }
#[test] #[test]

View File

@ -474,6 +474,16 @@ fn test_range_inclusive_size_hint() {
assert_eq!((imin..=imax + 1).size_hint(), (usize::MAX, None)); assert_eq!((imin..=imax + 1).size_hint(), (usize::MAX, None));
} }
#[test]
fn test_range_trusted_random_access() {
let mut range = 0..10;
unsafe {
assert_eq!(range.next(), Some(0));
assert_eq!(range.__iterator_get_unchecked(0), 1);
assert_eq!(range.__iterator_get_unchecked(1), 2);
}
}
#[test] #[test]
fn test_double_ended_range() { fn test_double_ended_range() {
assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]); assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);