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