1 //! Macros used by iterators of slice. 2 3 // Shrinks the iterator when T is a ZST, setting the length to `new_len`. 4 // `new_len` must not exceed `self.len()`. 5 macro_rules! zst_set_len { 6 ($self: ident, $new_len: expr) => {{ 7 #![allow(unused_unsafe)] // we're sometimes used within an unsafe block 8 9 // SAFETY: same as `invalid(_mut)`, but the macro doesn't know 10 // which versions of that function to call, so open-code it. 11 $self.end = unsafe { mem::transmute::<usize, _>($new_len) }; 12 }}; 13 } 14 15 // Shrinks the iterator when T is a ZST, reducing the length by `n`. 16 // `n` must not exceed `self.len()`. 17 macro_rules! zst_shrink { 18 ($self: ident, $n: ident) => { 19 let new_len = $self.end.addr() - $n; 20 zst_set_len!($self, new_len); 21 }; 22 } 23 24 // Inlining is_empty and len makes a huge performance difference 25 macro_rules! is_empty { 26 ($self: ident) => { 27 if T::IS_ZST { $self.end.addr() == 0 } else { $self.ptr.as_ptr() as *const _ == $self.end } 28 }; 29 } 30 31 macro_rules! len { 32 ($self: ident) => {{ 33 #![allow(unused_unsafe)] // we're sometimes used within an unsafe block 34 35 if T::IS_ZST { 36 $self.end.addr() 37 } else { 38 // To get rid of some bounds checks (see `position`), we use ptr_sub instead of 39 // offset_from (Tested by `codegen/slice-position-bounds-check`.) 40 // SAFETY: by the type invariant pointers are aligned and `start <= end` 41 unsafe { $self.end.sub_ptr($self.ptr.as_ptr()) } 42 } 43 }}; 44 } 45 46 // The shared definition of the `Iter` and `IterMut` iterators 47 macro_rules! iterator { 48 ( 49 struct $name:ident -> $ptr:ty, 50 $elem:ty, 51 $raw_mut:tt, 52 {$( $mut_:tt )?}, 53 {$($extra:tt)*} 54 ) => { 55 // Returns the first element and moves the start of the iterator forwards by 1. 56 // Greatly improves performance compared to an inlined function. The iterator 57 // must not be empty. 58 macro_rules! next_unchecked { 59 ($self: ident) => {& $( $mut_ )? *$self.post_inc_start(1)} 60 } 61 62 // Returns the last element and moves the end of the iterator backwards by 1. 63 // Greatly improves performance compared to an inlined function. The iterator 64 // must not be empty. 65 macro_rules! next_back_unchecked { 66 ($self: ident) => {& $( $mut_ )? *$self.pre_dec_end(1)} 67 } 68 69 impl<'a, T> $name<'a, T> { 70 // Helper function for creating a slice from the iterator. 71 #[inline(always)] 72 fn make_slice(&self) -> &'a [T] { 73 // SAFETY: the iterator was created from a slice with pointer 74 // `self.ptr` and length `len!(self)`. This guarantees that all 75 // the prerequisites for `from_raw_parts` are fulfilled. 76 unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) } 77 } 78 79 // Helper function for moving the start of the iterator forwards by `offset` elements, 80 // returning the old start. 81 // Unsafe because the offset must not exceed `self.len()`. 82 #[inline(always)] 83 unsafe fn post_inc_start(&mut self, offset: usize) -> * $raw_mut T { 84 let old = self.ptr; 85 if T::IS_ZST { 86 zst_shrink!(self, offset); 87 } else { 88 // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, 89 // so this new pointer is inside `self` and thus guaranteed to be non-null. 90 self.ptr = unsafe { self.ptr.add(offset) }; 91 } 92 old.as_ptr() 93 } 94 95 // Helper function for moving the end of the iterator backwards by `offset` elements, 96 // returning the new end. 97 // Unsafe because the offset must not exceed `self.len()`. 98 #[inline(always)] 99 unsafe fn pre_dec_end(&mut self, offset: usize) -> * $raw_mut T { 100 if T::IS_ZST { 101 zst_shrink!(self, offset); 102 self.ptr.as_ptr() 103 } else { 104 // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, 105 // which is guaranteed to not overflow an `isize`. Also, the resulting pointer 106 // is in bounds of `slice`, which fulfills the other requirements for `offset`. 107 self.end = unsafe { self.end.sub(offset) }; 108 self.end 109 } 110 } 111 } 112 113 #[stable(feature = "rust1", since = "1.0.0")] 114 impl<T> ExactSizeIterator for $name<'_, T> { 115 #[inline(always)] 116 fn len(&self) -> usize { 117 len!(self) 118 } 119 120 #[inline(always)] 121 fn is_empty(&self) -> bool { 122 is_empty!(self) 123 } 124 } 125 126 #[stable(feature = "rust1", since = "1.0.0")] 127 impl<'a, T> Iterator for $name<'a, T> { 128 type Item = $elem; 129 130 #[inline] 131 fn next(&mut self) -> Option<$elem> { 132 // could be implemented with slices, but this avoids bounds checks 133 134 // SAFETY: `assume` call is safe because slices over non-ZSTs must 135 // have a non-null end pointer. The call to `next_unchecked!` is 136 // safe since we check if the iterator is empty first. 137 unsafe { 138 if !<T>::IS_ZST { 139 assume(!self.end.is_null()); 140 } 141 if is_empty!(self) { 142 None 143 } else { 144 Some(next_unchecked!(self)) 145 } 146 } 147 } 148 149 #[inline] 150 fn size_hint(&self) -> (usize, Option<usize>) { 151 let exact = len!(self); 152 (exact, Some(exact)) 153 } 154 155 #[inline] 156 fn count(self) -> usize { 157 len!(self) 158 } 159 160 #[inline] 161 fn nth(&mut self, n: usize) -> Option<$elem> { 162 if n >= len!(self) { 163 // This iterator is now empty. 164 if T::IS_ZST { 165 zst_set_len!(self, 0); 166 } else { 167 // SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr 168 unsafe { 169 self.ptr = NonNull::new_unchecked(self.end as *mut T); 170 } 171 } 172 return None; 173 } 174 // SAFETY: We are in bounds. `post_inc_start` does the right thing even for ZSTs. 175 unsafe { 176 self.post_inc_start(n); 177 Some(next_unchecked!(self)) 178 } 179 } 180 181 #[inline] 182 fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { 183 let advance = cmp::min(len!(self), n); 184 // SAFETY: By construction, `advance` does not exceed `self.len()`. 185 unsafe { self.post_inc_start(advance) }; 186 NonZeroUsize::new(n - advance).map_or(Ok(()), Err) 187 } 188 189 #[inline] 190 fn last(mut self) -> Option<$elem> { 191 self.next_back() 192 } 193 194 #[inline] 195 fn fold<B, F>(self, init: B, mut f: F) -> B 196 where 197 F: FnMut(B, Self::Item) -> B, 198 { 199 // this implementation consists of the following optimizations compared to the 200 // default implementation: 201 // - do-while loop, as is llvm's preferred loop shape, 202 // see https://releases.llvm.org/16.0.0/docs/LoopTerminology.html#more-canonical-loops 203 // - bumps an index instead of a pointer since the latter case inhibits 204 // some optimizations, see #111603 205 // - avoids Option wrapping/matching 206 if is_empty!(self) { 207 return init; 208 } 209 let mut acc = init; 210 let mut i = 0; 211 let len = len!(self); 212 loop { 213 // SAFETY: the loop iterates `i in 0..len`, which always is in bounds of 214 // the slice allocation 215 acc = f(acc, unsafe { & $( $mut_ )? *self.ptr.add(i).as_ptr() }); 216 // SAFETY: `i` can't overflow since it'll only reach usize::MAX if the 217 // slice had that length, in which case we'll break out of the loop 218 // after the increment 219 i = unsafe { i.unchecked_add(1) }; 220 if i == len { 221 break; 222 } 223 } 224 acc 225 } 226 227 // We override the default implementation, which uses `try_fold`, 228 // because this simple implementation generates less LLVM IR and is 229 // faster to compile. 230 #[inline] 231 fn for_each<F>(mut self, mut f: F) 232 where 233 Self: Sized, 234 F: FnMut(Self::Item), 235 { 236 while let Some(x) = self.next() { 237 f(x); 238 } 239 } 240 241 // We override the default implementation, which uses `try_fold`, 242 // because this simple implementation generates less LLVM IR and is 243 // faster to compile. 244 #[inline] 245 fn all<F>(&mut self, mut f: F) -> bool 246 where 247 Self: Sized, 248 F: FnMut(Self::Item) -> bool, 249 { 250 while let Some(x) = self.next() { 251 if !f(x) { 252 return false; 253 } 254 } 255 true 256 } 257 258 // We override the default implementation, which uses `try_fold`, 259 // because this simple implementation generates less LLVM IR and is 260 // faster to compile. 261 #[inline] 262 fn any<F>(&mut self, mut f: F) -> bool 263 where 264 Self: Sized, 265 F: FnMut(Self::Item) -> bool, 266 { 267 while let Some(x) = self.next() { 268 if f(x) { 269 return true; 270 } 271 } 272 false 273 } 274 275 // We override the default implementation, which uses `try_fold`, 276 // because this simple implementation generates less LLVM IR and is 277 // faster to compile. 278 #[inline] 279 fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> 280 where 281 Self: Sized, 282 P: FnMut(&Self::Item) -> bool, 283 { 284 while let Some(x) = self.next() { 285 if predicate(&x) { 286 return Some(x); 287 } 288 } 289 None 290 } 291 292 // We override the default implementation, which uses `try_fold`, 293 // because this simple implementation generates less LLVM IR and is 294 // faster to compile. 295 #[inline] 296 fn find_map<B, F>(&mut self, mut f: F) -> Option<B> 297 where 298 Self: Sized, 299 F: FnMut(Self::Item) -> Option<B>, 300 { 301 while let Some(x) = self.next() { 302 if let Some(y) = f(x) { 303 return Some(y); 304 } 305 } 306 None 307 } 308 309 // We override the default implementation, which uses `try_fold`, 310 // because this simple implementation generates less LLVM IR and is 311 // faster to compile. Also, the `assume` avoids a bounds check. 312 #[inline] 313 #[rustc_inherit_overflow_checks] 314 fn position<P>(&mut self, mut predicate: P) -> Option<usize> where 315 Self: Sized, 316 P: FnMut(Self::Item) -> bool, 317 { 318 let n = len!(self); 319 let mut i = 0; 320 while let Some(x) = self.next() { 321 if predicate(x) { 322 // SAFETY: we are guaranteed to be in bounds by the loop invariant: 323 // when `i >= n`, `self.next()` returns `None` and the loop breaks. 324 unsafe { assume(i < n) }; 325 return Some(i); 326 } 327 i += 1; 328 } 329 None 330 } 331 332 // We override the default implementation, which uses `try_fold`, 333 // because this simple implementation generates less LLVM IR and is 334 // faster to compile. Also, the `assume` avoids a bounds check. 335 #[inline] 336 fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where 337 P: FnMut(Self::Item) -> bool, 338 Self: Sized + ExactSizeIterator + DoubleEndedIterator 339 { 340 let n = len!(self); 341 let mut i = n; 342 while let Some(x) = self.next_back() { 343 i -= 1; 344 if predicate(x) { 345 // SAFETY: `i` must be lower than `n` since it starts at `n` 346 // and is only decreasing. 347 unsafe { assume(i < n) }; 348 return Some(i); 349 } 350 } 351 None 352 } 353 354 #[inline] 355 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { 356 // SAFETY: the caller must guarantee that `i` is in bounds of 357 // the underlying slice, so `i` cannot overflow an `isize`, and 358 // the returned references is guaranteed to refer to an element 359 // of the slice and thus guaranteed to be valid. 360 // 361 // Also note that the caller also guarantees that we're never 362 // called with the same index again, and that no other methods 363 // that will access this subslice are called, so it is valid 364 // for the returned reference to be mutable in the case of 365 // `IterMut` 366 unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) } 367 } 368 369 $($extra)* 370 } 371 372 #[stable(feature = "rust1", since = "1.0.0")] 373 impl<'a, T> DoubleEndedIterator for $name<'a, T> { 374 #[inline] 375 fn next_back(&mut self) -> Option<$elem> { 376 // could be implemented with slices, but this avoids bounds checks 377 378 // SAFETY: `assume` call is safe because slices over non-ZSTs must 379 // have a non-null end pointer. The call to `next_back_unchecked!` 380 // is safe since we check if the iterator is empty first. 381 unsafe { 382 if !<T>::IS_ZST { 383 assume(!self.end.is_null()); 384 } 385 if is_empty!(self) { 386 None 387 } else { 388 Some(next_back_unchecked!(self)) 389 } 390 } 391 } 392 393 #[inline] 394 fn nth_back(&mut self, n: usize) -> Option<$elem> { 395 if n >= len!(self) { 396 // This iterator is now empty. 397 if T::IS_ZST { 398 zst_set_len!(self, 0); 399 } else { 400 self.end = self.ptr.as_ptr(); 401 } 402 return None; 403 } 404 // SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs. 405 unsafe { 406 self.pre_dec_end(n); 407 Some(next_back_unchecked!(self)) 408 } 409 } 410 411 #[inline] 412 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { 413 let advance = cmp::min(len!(self), n); 414 // SAFETY: By construction, `advance` does not exceed `self.len()`. 415 unsafe { self.pre_dec_end(advance) }; 416 NonZeroUsize::new(n - advance).map_or(Ok(()), Err) 417 } 418 } 419 420 #[stable(feature = "fused", since = "1.26.0")] 421 impl<T> FusedIterator for $name<'_, T> {} 422 423 #[unstable(feature = "trusted_len", issue = "37572")] 424 unsafe impl<T> TrustedLen for $name<'_, T> {} 425 426 impl<'a, T> UncheckedIterator for $name<'a, T> { 427 unsafe fn next_unchecked(&mut self) -> $elem { 428 // SAFETY: The caller promised there's at least one more item. 429 unsafe { 430 next_unchecked!(self) 431 } 432 } 433 } 434 435 #[stable(feature = "default_iters", since = "1.70.0")] 436 impl<T> Default for $name<'_, T> { 437 /// Creates an empty slice iterator. 438 /// 439 /// ``` 440 #[doc = concat!("# use core::slice::", stringify!($name), ";")] 441 #[doc = concat!("let iter: ", stringify!($name<'_, u8>), " = Default::default();")] 442 /// assert_eq!(iter.len(), 0); 443 /// ``` 444 fn default() -> Self { 445 (& $( $mut_ )? []).into_iter() 446 } 447 } 448 } 449 } 450 451 macro_rules! forward_iterator { 452 ($name:ident: $elem:ident, $iter_of:ty) => { 453 #[stable(feature = "rust1", since = "1.0.0")] 454 impl<'a, $elem, P> Iterator for $name<'a, $elem, P> 455 where 456 P: FnMut(&T) -> bool, 457 { 458 type Item = $iter_of; 459 460 #[inline] 461 fn next(&mut self) -> Option<$iter_of> { 462 self.inner.next() 463 } 464 465 #[inline] 466 fn size_hint(&self) -> (usize, Option<usize>) { 467 self.inner.size_hint() 468 } 469 } 470 471 #[stable(feature = "fused", since = "1.26.0")] 472 impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool {} 473 }; 474 } 475