1
1
use crate :: iter:: { TrustedLen , UncheckedIterator } ;
2
+ use crate :: marker:: PhantomData ;
2
3
use 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 } ;
5
6
6
7
/// A situationally-optimized version of `array.into_iter().for_each(func)`.
7
8
///
@@ -21,37 +22,29 @@ pub(crate) fn drain_array_with<T, R, const N: usize>(
21
22
func : impl for < ' a > FnOnce ( Drain < ' a , T > ) -> R ,
22
23
) -> R {
23
24
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 ) ;
26
30
func ( drain)
27
31
}
28
32
29
33
/// See [`drain_array_with`] -- this is `pub(crate)` only so it's allowed to be
30
34
/// 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 ] > ) ;
40
36
41
37
impl < T > Iterator for Drain < ' _ , T > {
42
38
type Item = T ;
43
39
44
40
#[ inline]
45
41
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 ( )
49
43
}
50
44
51
45
#[ inline]
52
46
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
53
- let n = self . len ( ) ;
54
- ( n, Some ( n) )
47
+ self . 0 . size_hint ( )
55
48
}
56
49
}
57
50
@@ -69,8 +62,6 @@ impl<T> UncheckedIterator for Drain<'_, T> {
69
62
unsafe fn next_unchecked ( & mut self ) -> T {
70
63
// SAFETY: `Drain` is 1:1 with the inner iterator, so if the caller promised
71
64
// 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 ( ) }
75
66
}
76
67
}
0 commit comments