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

`}

`