11use crate :: iter:: { TrustedLen , UncheckedIterator } ;
2+ use crate :: marker:: PhantomData ;
23use crate :: mem:: ManuallyDrop ;
3- use crate :: ptr:: drop_in_place ;
4- use crate :: slice;
4+ use crate :: ptr:: NonNull ;
5+ use crate :: slice:: { self , DrainRaw } ;
56
67/// A situationally-optimized version of `array.into_iter().for_each(func)`.
78///
@@ -21,37 +22,29 @@ pub(crate) fn drain_array_with<T, R, const N: usize>(
2122 func : impl for < ' a > FnOnce ( Drain < ' a , T > ) -> R ,
2223) -> R {
2324 let mut array = ManuallyDrop :: new ( array) ;
24- // SAFETY: Now that the local won't drop it, it's ok to construct the `Drain` which will.
25- let drain = Drain ( array. iter_mut ( ) ) ;
25+ // SAFETY: Now that the local won't drop it, it's ok to construct the `DrainRaw` which will.
26+ // We ensure via the lifetime that it can't be used after the function returns,
27+ // and thus the local `array` will always exist while iterating it.
28+ let raw = unsafe { DrainRaw :: from_parts ( NonNull :: new_unchecked ( array. as_mut_ptr ( ) ) , N ) } ;
29+ let drain = Drain ( raw, PhantomData ) ;
2630 func ( drain)
2731}
2832
2933/// See [`drain_array_with`] -- this is `pub(crate)` only so it's allowed to be
3034/// mentioned in the signature of that method. (Otherwise it hits `E0446`.)
31- // INVARIANT: It's ok to drop the remainder of the inner iterator.
32- pub ( crate ) struct Drain < ' a , T > ( slice:: IterMut < ' a , T > ) ;
33-
34- impl < T > Drop for Drain < ' _ , T > {
35- fn drop ( & mut self ) {
36- // SAFETY: By the type invariant, we're allowed to drop all these.
37- unsafe { drop_in_place ( self . 0 . as_mut_slice ( ) ) }
38- }
39- }
35+ pub ( crate ) struct Drain < ' a , T > ( slice:: DrainRaw < T > , PhantomData < & ' a mut [ T ] > ) ;
4036
4137impl < T > Iterator for Drain < ' _ , T > {
4238 type Item = T ;
4339
4440 #[ inline]
4541 fn next ( & mut self ) -> Option < T > {
46- let p: * const T = self . 0 . next ( ) ?;
47- // SAFETY: The iterator was already advanced, so we won't drop this later.
48- Some ( unsafe { p. read ( ) } )
42+ self . 0 . next ( )
4943 }
5044
5145 #[ inline]
5246 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
53- let n = self . len ( ) ;
54- ( n, Some ( n) )
47+ self . 0 . size_hint ( )
5548 }
5649}
5750
@@ -69,8 +62,6 @@ impl<T> UncheckedIterator for Drain<'_, T> {
6962 unsafe fn next_unchecked ( & mut self ) -> T {
7063 // SAFETY: `Drain` is 1:1 with the inner iterator, so if the caller promised
7164 // that there's an element left, the inner iterator has one too.
72- let p: * const T = unsafe { self . 0 . next_unchecked ( ) } ;
73- // SAFETY: The iterator was already advanced, so we won't drop this later.
74- unsafe { p. read ( ) }
65+ unsafe { self . 0 . next_unchecked ( ) }
7566 }
7667}
0 commit comments