|
1 | 1 | use crate::intrinsics::unlikely;
|
| 2 | +use crate::iter::adapters::zip::try_get_unchecked; |
2 | 3 | use crate::iter::TrustedFused;
|
3 |
| -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; |
| 4 | +use crate::iter::{ |
| 5 | + adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess, |
| 6 | + TrustedRandomAccessNoCoerce, |
| 7 | +}; |
4 | 8 | use crate::num::NonZeroUsize;
|
5 | 9 | use crate::ops::{ControlFlow, Try};
|
6 | 10 |
|
@@ -152,6 +156,32 @@ where
|
152 | 156 |
|
153 | 157 | NonZeroUsize::new(n).map_or(Ok(()), Err)
|
154 | 158 | }
|
| 159 | + |
| 160 | + #[doc(hidden)] |
| 161 | + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item |
| 162 | + where |
| 163 | + Self: TrustedRandomAccessNoCoerce, |
| 164 | + { |
| 165 | + // SAFETY: the caller must uphold the contract for |
| 166 | + // `Iterator::__iterator_get_unchecked`. |
| 167 | + // |
| 168 | + // Dropping the skipped prefix when index 0 is passed is safe |
| 169 | + // since |
| 170 | + // * the caller passing index 0 means that the inner iterator has more items than `self.n` |
| 171 | + // * TRA contract requires that get_unchecked will only be called once |
| 172 | + // (unless elements are copyable) |
| 173 | + // * it does not conflict with in-place iteration since index 0 must be accessed |
| 174 | + // before something is written into the storage used by the prefix |
| 175 | + unsafe { |
| 176 | + if Self::MAY_HAVE_SIDE_EFFECT && idx == 0 { |
| 177 | + for skipped_idx in 0..self.n { |
| 178 | + drop(try_get_unchecked(&mut self.iter, skipped_idx)); |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + try_get_unchecked(&mut self.iter, idx + self.n) |
| 183 | + } |
| 184 | + } |
155 | 185 | }
|
156 | 186 |
|
157 | 187 | #[stable(feature = "rust1", since = "1.0.0")]
|
@@ -237,3 +267,23 @@ unsafe impl<I: InPlaceIterable> InPlaceIterable for Skip<I> {
|
237 | 267 | const EXPAND_BY: Option<NonZeroUsize> = I::EXPAND_BY;
|
238 | 268 | const MERGE_BY: Option<NonZeroUsize> = I::MERGE_BY;
|
239 | 269 | }
|
| 270 | + |
| 271 | +#[doc(hidden)] |
| 272 | +#[unstable(feature = "trusted_random_access", issue = "none")] |
| 273 | +unsafe impl<I> TrustedRandomAccess for Skip<I> where I: TrustedRandomAccess {} |
| 274 | + |
| 275 | +#[doc(hidden)] |
| 276 | +#[unstable(feature = "trusted_random_access", issue = "none")] |
| 277 | +unsafe impl<I> TrustedRandomAccessNoCoerce for Skip<I> |
| 278 | +where |
| 279 | + I: TrustedRandomAccessNoCoerce, |
| 280 | +{ |
| 281 | + const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; |
| 282 | +} |
| 283 | + |
| 284 | +// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly. |
| 285 | +// These requirements can only be satisfied when the upper bound of the inner iterator's upper |
| 286 | +// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while |
| 287 | +// I: TrustedLen would not. |
| 288 | +#[unstable(feature = "trusted_len", issue = "37572")] |
| 289 | +unsafe impl<I> TrustedLen for Skip<I> where I: Iterator + TrustedRandomAccess {} |
0 commit comments