Auto merge of #120050 - scottmcm:vec-resize-memset, r= · rust-lang/rust@f5c3755 (original) (raw)
`@@ -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
`}
`