@@ -1942,6 +1942,18 @@ impl<T, A: Allocator> Vec<T, A> {
19421942 #[ unstable( feature = "vec_split_at_spare" , issue = "81944" ) ]
19431943 #[ inline]
19441944 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 ) {
19451957 let Range { start : ptr, end : spare_ptr } = self . as_mut_ptr_range ( ) ;
19461958 let spare_ptr = spare_ptr. cast :: < MaybeUninit < T > > ( ) ;
19471959 let spare_len = self . buf . capacity ( ) - self . len ;
@@ -1953,7 +1965,7 @@ impl<T, A: Allocator> Vec<T, A> {
19531965 let initialized = slice:: from_raw_parts_mut ( ptr, self . len ) ;
19541966 let spare = slice:: from_raw_parts_mut ( spare_ptr, spare_len) ;
19551967
1956- ( initialized, spare)
1968+ ( initialized, spare, & mut self . len )
19571969 }
19581970 }
19591971}
@@ -2165,22 +2177,23 @@ trait ExtendFromWithinSpec {
21652177
21662178impl < T : Clone , A : Allocator > ExtendFromWithinSpec for Vec < T , A > {
21672179 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 ( ) } ;
21772183
21782184 // 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 ) ;
21842197 }
21852198}
21862199
0 commit comments