@@ -64,27 +64,37 @@ where
64
64
type Item = T ;
65
65
66
66
fn next ( & mut self ) -> Option < T > {
67
- unsafe {
68
- while self . idx < self . end {
69
- let i = self . idx ;
70
- let v = slice:: from_raw_parts_mut ( self . vec . as_mut_ptr ( ) , self . old_len ) ;
71
- let drained = ( self . pred ) ( & mut v[ i] ) ;
72
- // Update the index *after* the predicate is called. If the index
73
- // is updated prior and the predicate panics, the element at this
74
- // index would be leaked.
75
- self . idx += 1 ;
76
- if drained {
77
- self . del += 1 ;
78
- return Some ( ptr:: read ( & v[ i] ) ) ;
79
- } else if self . del > 0 {
80
- let del = self . del ;
81
- let src: * const T = & v[ i] ;
82
- let dst: * mut T = & mut v[ i - del] ;
83
- ptr:: copy_nonoverlapping ( src, dst, 1 ) ;
67
+ while self . idx < self . end {
68
+ let i = self . idx ;
69
+ // SAFETY:
70
+ // We know that `i < self.end` from the if guard and that `self.end <= self.old_len` from
71
+ // the validity of `Self`. Therefore `i` points to an element within `vec`.
72
+ //
73
+ // Additionally, the i-th element is valid because each element is visited at most once
74
+ // and it is the first time we access vec[i].
75
+ //
76
+ // Note: we can't use `vec.get_unchecked_mut(i)` here since the precondition for that
77
+ // function is that i < vec.len(), but we've set vec's length to zero.
78
+ let cur = unsafe { & mut * self . vec . as_mut_ptr ( ) . add ( i) } ;
79
+ let drained = ( self . pred ) ( cur) ;
80
+ // Update the index *after* the predicate is called. If the index
81
+ // is updated prior and the predicate panics, the element at this
82
+ // index would be leaked.
83
+ self . idx += 1 ;
84
+ if drained {
85
+ self . del += 1 ;
86
+ // SAFETY: We never touch this element again after returning it.
87
+ return Some ( unsafe { ptr:: read ( cur) } ) ;
88
+ } else if self . del > 0 {
89
+ // SAFETY: `self.del` > 0, so the hole slot must not overlap with current element.
90
+ // We use copy for move, and never touch this element again.
91
+ unsafe {
92
+ let hole_slot = self . vec . as_mut_ptr ( ) . add ( i - self . del ) ;
93
+ ptr:: copy_nonoverlapping ( cur, hole_slot, 1 ) ;
84
94
}
85
95
}
86
- None
87
96
}
97
+ None
88
98
}
89
99
90
100
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -95,14 +105,18 @@ where
95
105
#[ stable( feature = "extract_if" , since = "1.87.0" ) ]
96
106
impl < T , F , A : Allocator > Drop for ExtractIf < ' _ , T , F , A > {
97
107
fn drop ( & mut self ) {
98
- unsafe {
99
- if self . idx < self . old_len && self . del > 0 {
100
- let ptr = self . vec . as_mut_ptr ( ) ;
101
- let src = ptr. add ( self . idx ) ;
102
- let dst = src. sub ( self . del ) ;
103
- let tail_len = self . old_len - self . idx ;
104
- src. copy_to ( dst, tail_len) ;
108
+ if self . del > 0 {
109
+ // SAFETY: Trailing unchecked items must be valid since we never touch them.
110
+ unsafe {
111
+ ptr:: copy (
112
+ self . vec . as_ptr ( ) . add ( self . idx ) ,
113
+ self . vec . as_mut_ptr ( ) . add ( self . idx - self . del ) ,
114
+ self . old_len - self . idx ,
115
+ ) ;
105
116
}
117
+ }
118
+ // SAFETY: After filling holes, all items are in contiguous memory.
119
+ unsafe {
106
120
self . vec . set_len ( self . old_len - self . del ) ;
107
121
}
108
122
}
0 commit comments