@@ -1942,6 +1942,18 @@ impl<T, A: Allocator> Vec<T, A> {
1942
1942
#[ unstable( feature = "vec_split_at_spare" , issue = "81944" ) ]
1943
1943
#[ inline]
1944
1944
pub fn split_at_spare_mut ( & mut self ) -> ( & mut [ T ] , & mut [ MaybeUninit < T > ] ) {
1945
+ // SAFETY:
1946
+ // - len is ignored and so never changed
1947
+ let ( init, spare, _) = unsafe { self . split_at_spare_mut_with_len ( ) } ;
1948
+ ( init, spare)
1949
+ }
1950
+
1951
+ /// Safety: changing returned .2 (&mut usize) is considered the same as calling `.set_len(_)`.
1952
+ ///
1953
+ /// This method is used to have unique access to all vec parts at once in `extend_from_within`.
1954
+ unsafe fn split_at_spare_mut_with_len (
1955
+ & mut self ,
1956
+ ) -> ( & mut [ T ] , & mut [ MaybeUninit < T > ] , & mut usize ) {
1945
1957
let Range { start : ptr, end : spare_ptr } = self . as_mut_ptr_range ( ) ;
1946
1958
let spare_ptr = spare_ptr. cast :: < MaybeUninit < T > > ( ) ;
1947
1959
let spare_len = self . buf . capacity ( ) - self . len ;
@@ -1953,7 +1965,7 @@ impl<T, A: Allocator> Vec<T, A> {
1953
1965
let initialized = slice:: from_raw_parts_mut ( ptr, self . len ) ;
1954
1966
let spare = slice:: from_raw_parts_mut ( spare_ptr, spare_len) ;
1955
1967
1956
- ( initialized, spare)
1968
+ ( initialized, spare, & mut self . len )
1957
1969
}
1958
1970
}
1959
1971
}
@@ -2165,22 +2177,23 @@ trait ExtendFromWithinSpec {
2165
2177
2166
2178
impl < T : Clone , A : Allocator > ExtendFromWithinSpec for Vec < T , A > {
2167
2179
default unsafe fn spec_extend_from_within ( & mut self , src : Range < usize > ) {
2168
- let initialized = {
2169
- let ( this, spare) = self . split_at_spare_mut ( ) ;
2170
-
2171
- // SAFETY:
2172
- // - caller guaratees that src is a valid index
2173
- let to_clone = unsafe { this. get_unchecked ( src) } ;
2174
-
2175
- to_clone. iter ( ) . cloned ( ) . zip ( spare. iter_mut ( ) ) . map ( |( e, s) | s. write ( e) ) . count ( )
2176
- } ;
2180
+ // SAFETY:
2181
+ // - len is increased only after initializing elements
2182
+ let ( this, spare, len) = unsafe { self . split_at_spare_mut_with_len ( ) } ;
2177
2183
2178
2184
// SAFETY:
2179
- // - elements were just initialized
2180
- unsafe {
2181
- let new_len = self . len ( ) + initialized;
2182
- self . set_len ( new_len) ;
2183
- }
2185
+ // - caller guaratees that src is a valid index
2186
+ let to_clone = unsafe { this. get_unchecked ( src) } ;
2187
+
2188
+ to_clone
2189
+ . iter ( )
2190
+ . cloned ( )
2191
+ . zip ( spare. iter_mut ( ) )
2192
+ . map ( |( src, dst) | dst. write ( src) )
2193
+ // Note:
2194
+ // - Element was just initialized with `MaybeUninit::write`, so it's ok to increace len
2195
+ // - len is increased after each element to prevent leaks (see issue #82533)
2196
+ . for_each ( |_| * len += 1 ) ;
2184
2197
}
2185
2198
}
2186
2199
0 commit comments