@@ -145,6 +145,12 @@ use self::spec_extend::SpecExtend;
145145#[ cfg( not( no_global_oom_handling) ) ]
146146mod spec_extend;
147147
148+ #[ cfg( not( no_global_oom_handling) ) ]
149+ use self :: spec_extend_elem:: SpecExtendElem ;
150+
151+ #[ cfg( not( no_global_oom_handling) ) ]
152+ mod spec_extend_elem;
153+
148154/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
149155///
150156/// # Examples
@@ -2871,7 +2877,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
28712877 let len = self . len ( ) ;
28722878
28732879 if new_len > len {
2874- self . extend_with ( new_len - len, value)
2880+ self . extend_elem ( new_len - len, value)
28752881 } else {
28762882 self . truncate ( new_len) ;
28772883 }
@@ -2985,32 +2991,38 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> {
29852991
29862992impl < T : Clone , A : Allocator > Vec < T , A > {
29872993 #[ cfg( not( no_global_oom_handling) ) ]
2988- /// Extend the vector by `n` clones of value.
2989- fn extend_with ( & mut self , n : usize , value : T ) {
2994+ #[ inline]
2995+ /// Extend the vector by `n` clones of `value`.
2996+ ///
2997+ /// Uses specialization to dispatch to `extend_elem_copy` if possible.
2998+ fn extend_elem ( & mut self , n : usize , value : T ) {
2999+ self . spec_extend_elem ( n, value) ;
3000+ }
3001+
3002+ #[ cfg( not( no_global_oom_handling) ) ]
3003+ #[ inline]
3004+ /// Extend the vector by `n` *copies* of `value`.
3005+ fn extend_elem_copy ( & mut self , n : usize , value : T )
3006+ where
3007+ T : Copy ,
3008+ {
29903009 self . reserve ( n) ;
29913010
3011+ // SAFETY: We now have space for all the elements, so the pointer math
3012+ // is all in-bounds. Because `T: Copy`, there's no user code being run
3013+ // here (no `clone` nor any `drop` in the assignment).
29923014 unsafe {
2993- let mut ptr = self . as_mut_ptr ( ) . add ( self . len ( ) ) ;
2994- // Use SetLenOnDrop to work around bug where compiler
2995- // might not realize the store through `ptr` through self.set_len()
2996- // don't alias.
2997- let mut local_len = SetLenOnDrop :: new ( & mut self . len ) ;
2998-
2999- // Write all elements except the last one
3000- for _ in 1 ..n {
3001- ptr:: write ( ptr, value. clone ( ) ) ;
3002- ptr = ptr. add ( 1 ) ;
3003- // Increment the length in every step in case clone() panics
3004- local_len. increment_len ( 1 ) ;
3005- }
3006-
3007- if n > 0 {
3008- // We can write the last element directly without cloning needlessly
3009- ptr:: write ( ptr, value) ;
3010- local_len. increment_len ( 1 ) ;
3015+ // Because there's no user code being run here, we can skip it for ZSTs.
3016+ // That helps tests in debug mode that do things like `vec![(); HUGE]`.
3017+ // See <https://github.com/rust-lang/rust/pull/118094>
3018+ if !T :: IS_ZST {
3019+ let ptr = self . as_mut_ptr ( ) . add ( self . len ) ;
3020+ for i in 0 ..n {
3021+ * ptr. add ( i) = value;
3022+ }
30113023 }
30123024
3013- // len set by scope guard
3025+ self . len += n ;
30143026 }
30153027 }
30163028}
0 commit comments