@@ -1942,6 +1942,16 @@ 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 ( & mut self ) -> ( & mut [ T ] , & mut [ MaybeUninit < T > ] , & mut usize ) {
1945
1955
let Range { start : ptr, end : spare_ptr } = self . as_mut_ptr_range ( ) ;
1946
1956
let spare_ptr = spare_ptr. cast :: < MaybeUninit < T > > ( ) ;
1947
1957
let spare_len = self . buf . capacity ( ) - self . len ;
@@ -1953,9 +1963,9 @@ impl<T, A: Allocator> Vec<T, A> {
1953
1963
let initialized = slice:: from_raw_parts_mut ( ptr, self . len ) ;
1954
1964
let spare = slice:: from_raw_parts_mut ( spare_ptr, spare_len) ;
1955
1965
1956
- ( initialized, spare)
1966
+ ( initialized, spare, & mut self . len )
1957
1967
}
1958
- }
1968
+ }
1959
1969
}
1960
1970
1961
1971
impl < T : Clone , A : Allocator > Vec < T , A > {
@@ -2165,22 +2175,23 @@ trait ExtendFromWithinSpec {
2165
2175
2166
2176
impl < T : Clone , A : Allocator > ExtendFromWithinSpec for Vec < T , A > {
2167
2177
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
- } ;
2178
+ // SAFETY:
2179
+ // - len is increased only after initializing elements
2180
+ let ( this, spare, len) = unsafe { self . split_at_spare_mut_with_len ( ) } ;
2177
2181
2178
2182
// SAFETY:
2179
- // - elements were just initialized
2180
- unsafe {
2181
- let new_len = self . len ( ) + initialized;
2182
- self . set_len ( new_len) ;
2183
- }
2183
+ // - caller guaratees that src is a valid index
2184
+ let to_clone = unsafe { this. get_unchecked ( src) } ;
2185
+
2186
+ to_clone
2187
+ . iter ( )
2188
+ . cloned ( )
2189
+ . zip ( spare. iter_mut ( ) )
2190
+ . map ( |( src, dst) | dst. write ( src) )
2191
+ // Note:
2192
+ // - Element was just initialized with `MaybeUninit::write`, so it's ok to increace len
2193
+ // - len is increased after each element to prevent leaks (see issue #82533)
2194
+ . for_each ( |_| * len += 1 ) ;
2184
2195
}
2185
2196
}
2186
2197
0 commit comments