Skip to content

Commit b3b9383

Browse files
authored
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` in 8725e4c, 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 in 3613980 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.
2 parents d1320a5 + a34f11c commit b3b9383

File tree

2 files changed

+34
-40
lines changed

2 files changed

+34
-40
lines changed

library/alloc/src/slice.rs

+33-10
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,38 @@ impl<T, A: Allocator> BorrowMut<[T]> for Vec<T, A> {
782782
}
783783
}
784784

785+
// Specializable trait for implementing ToOwned::clone_into. This is
786+
// public in the crate and has the Allocator parameter so that
787+
// vec::clone_from use it too.
788+
#[cfg(not(no_global_oom_handling))]
789+
pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
790+
fn clone_into(&self, target: &mut Vec<T, A>);
791+
}
792+
793+
#[cfg(not(no_global_oom_handling))]
794+
impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
795+
default fn clone_into(&self, target: &mut Vec<T, A>) {
796+
// drop anything in target that will not be overwritten
797+
target.truncate(self.len());
798+
799+
// target.len <= self.len due to the truncate above, so the
800+
// slices here are always in-bounds.
801+
let (init, tail) = self.split_at(target.len());
802+
803+
// reuse the contained values' allocations/resources.
804+
target.clone_from_slice(init);
805+
target.extend_from_slice(tail);
806+
}
807+
}
808+
809+
#[cfg(not(no_global_oom_handling))]
810+
impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
811+
fn clone_into(&self, target: &mut Vec<T, A>) {
812+
target.clear();
813+
target.extend_from_slice(self);
814+
}
815+
}
816+
785817
#[cfg(not(no_global_oom_handling))]
786818
#[stable(feature = "rust1", since = "1.0.0")]
787819
impl<T: Clone> ToOwned for [T] {
@@ -797,16 +829,7 @@ impl<T: Clone> ToOwned for [T] {
797829
}
798830

799831
fn clone_into(&self, target: &mut Vec<T>) {
800-
// drop anything in target that will not be overwritten
801-
target.truncate(self.len());
802-
803-
// target.len <= self.len due to the truncate above, so the
804-
// slices here are always in-bounds.
805-
let (init, tail) = self.split_at(target.len());
806-
807-
// reuse the contained values' allocations/resources.
808-
target.clone_from_slice(init);
809-
target.extend_from_slice(tail);
832+
SpecCloneIntoVec::clone_into(self, target);
810833
}
811834
}
812835

library/alloc/src/vec/mod.rs

+1-30
Original file line numberDiff line numberDiff line change
@@ -2646,35 +2646,6 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
26462646
}
26472647
}
26482648

2649-
#[cfg(not(no_global_oom_handling))]
2650-
trait SpecCloneFrom {
2651-
fn clone_from(this: &mut Self, other: &Self);
2652-
}
2653-
2654-
#[cfg(not(no_global_oom_handling))]
2655-
impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
2656-
default fn clone_from(this: &mut Self, other: &Self) {
2657-
// drop anything that will not be overwritten
2658-
this.truncate(other.len());
2659-
2660-
// self.len <= other.len due to the truncate above, so the
2661-
// slices here are always in-bounds.
2662-
let (init, tail) = other.split_at(this.len());
2663-
2664-
// reuse the contained values' allocations/resources.
2665-
this.clone_from_slice(init);
2666-
this.extend_from_slice(tail);
2667-
}
2668-
}
2669-
2670-
#[cfg(not(no_global_oom_handling))]
2671-
impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
2672-
fn clone_from(this: &mut Self, other: &Self) {
2673-
this.clear();
2674-
this.extend_from_slice(other);
2675-
}
2676-
}
2677-
26782649
#[cfg(not(no_global_oom_handling))]
26792650
#[stable(feature = "rust1", since = "1.0.0")]
26802651
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
@@ -2695,7 +2666,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
26952666
}
26962667

26972668
fn clone_from(&mut self, other: &Self) {
2698-
SpecCloneFrom::clone_from(self, other)
2669+
crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
26992670
}
27002671
}
27012672

0 commit comments

Comments
 (0)