Rollup merge of #107424 - bpeel:clone-into-from-share-code, r=scottmcm
Make Vec::clone_from and slice::clone_into share the same code In the past, `Vec::clone_from` was implemented using `slice::clone_into`. The code from `clone_into` was later duplicated into `clone_from` in8725e4c337
, which is the commit that adds custom allocator support to Vec. Presumably this was done because the `slice::clone_into` method only works for vecs with the default allocator so it would have the wrong type to clone into `Vec<T, A>`. Later on in361398009b
the code for the two methods diverged because the `Vec::clone_from` version gained a specialization to optimize the case when T is Copy. In order to reduce code duplication and make them both be able to take advantage of this specialization, this PR moves the specialization into the slice module and makes vec use it again.
This commit is contained in:
commit
b3b9383f8d
@ -782,6 +782,38 @@ fn borrow_mut(&mut self) -> &mut [T] {
|
||||
}
|
||||
}
|
||||
|
||||
// Specializable trait for implementing ToOwned::clone_into. This is
|
||||
// public in the crate and has the Allocator parameter so that
|
||||
// vec::clone_from use it too.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
|
||||
fn clone_into(&self, target: &mut Vec<T, A>);
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
||||
default fn clone_into(&self, target: &mut Vec<T, A>) {
|
||||
// drop anything in target that will not be overwritten
|
||||
target.truncate(self.len());
|
||||
|
||||
// target.len <= self.len due to the truncate above, so the
|
||||
// slices here are always in-bounds.
|
||||
let (init, tail) = self.split_at(target.len());
|
||||
|
||||
// reuse the contained values' allocations/resources.
|
||||
target.clone_from_slice(init);
|
||||
target.extend_from_slice(tail);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
||||
fn clone_into(&self, target: &mut Vec<T, A>) {
|
||||
target.clear();
|
||||
target.extend_from_slice(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Clone> ToOwned for [T] {
|
||||
@ -797,16 +829,7 @@ fn to_owned(&self) -> Vec<T> {
|
||||
}
|
||||
|
||||
fn clone_into(&self, target: &mut Vec<T>) {
|
||||
// drop anything in target that will not be overwritten
|
||||
target.truncate(self.len());
|
||||
|
||||
// target.len <= self.len due to the truncate above, so the
|
||||
// slices here are always in-bounds.
|
||||
let (init, tail) = self.split_at(target.len());
|
||||
|
||||
// reuse the contained values' allocations/resources.
|
||||
target.clone_from_slice(init);
|
||||
target.extend_from_slice(tail);
|
||||
SpecCloneIntoVec::clone_into(self, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2646,35 +2646,6 @@ fn deref_mut(&mut self) -> &mut [T] {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
trait SpecCloneFrom {
|
||||
fn clone_from(this: &mut Self, other: &Self);
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
|
||||
default fn clone_from(this: &mut Self, other: &Self) {
|
||||
// drop anything that will not be overwritten
|
||||
this.truncate(other.len());
|
||||
|
||||
// self.len <= other.len due to the truncate above, so the
|
||||
// slices here are always in-bounds.
|
||||
let (init, tail) = other.split_at(this.len());
|
||||
|
||||
// reuse the contained values' allocations/resources.
|
||||
this.clone_from_slice(init);
|
||||
this.extend_from_slice(tail);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
|
||||
fn clone_from(this: &mut Self, other: &Self) {
|
||||
this.clear();
|
||||
this.extend_from_slice(other);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
|
||||
@ -2695,7 +2666,7 @@ fn clone(&self) -> Self {
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, other: &Self) {
|
||||
SpecCloneFrom::clone_from(self, other)
|
||||
crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user