implement TrustedLen for StepBy
This commit is contained in:
parent
e927184629
commit
a2a7caacf7
@ -1,7 +1,7 @@
|
||||
use crate::convert::TryFrom;
|
||||
use crate::{
|
||||
intrinsics,
|
||||
iter::{from_fn, TrustedLen},
|
||||
iter::{from_fn, TrustedLen, TrustedRandomAccess},
|
||||
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")]
|
||||
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> {
|
||||
fn setup(inner: T, step: usize) -> T;
|
||||
}
|
||||
@ -480,12 +488,6 @@ fn spec_fold<Acc, F>(self, init: Acc, mut f: F) -> 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>> {}
|
||||
)*)
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,8 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
assert_eq!(it.len(), 3);
|
||||
|
||||
// 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 {
|
||||
fn test(self) -> bool;
|
||||
}
|
||||
@ -235,7 +236,9 @@ fn test(self) -> bool {
|
||||
}
|
||||
}
|
||||
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]
|
||||
|
@ -474,6 +474,16 @@ fn test_range_inclusive_size_hint() {
|
||||
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]
|
||||
fn test_double_ended_range() {
|
||||
assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
|
||||
|
Loading…
Reference in New Issue
Block a user