@@ -145,6 +145,12 @@ use self::spec_extend::SpecExtend;
145
145
#[ cfg( not( no_global_oom_handling) ) ]
146
146
mod spec_extend;
147
147
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
+
148
154
/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
149
155
///
150
156
/// # Examples
@@ -2871,7 +2877,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
2871
2877
let len = self . len ( ) ;
2872
2878
2873
2879
if new_len > len {
2874
- self . extend_with ( new_len - len, value)
2880
+ self . extend_elem ( new_len - len, value)
2875
2881
} else {
2876
2882
self . truncate ( new_len) ;
2877
2883
}
@@ -2985,32 +2991,38 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> {
2985
2991
2986
2992
impl < T : Clone , A : Allocator > Vec < T , A > {
2987
2993
#[ 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
+ {
2990
3009
self . reserve ( n) ;
2991
3010
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).
2992
3014
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
+ }
3011
3023
}
3012
3024
3013
- // len set by scope guard
3025
+ self . len += n ;
3014
3026
}
3015
3027
}
3016
3028
}
0 commit comments