Skip to content

Commit a59e885

Browse files
committed
Auto merge of #87913 - a1phyr:vec_spec_clone_from, r=dtolnay
Specialize `Vec::clone_from` for `Copy` types This should improve performance and reduce code size. This also improves `clone_from` for `String`, `OsString` and `PathBuf`.
2 parents 136eaa1 + 94d6b22 commit a59e885

File tree

1 file changed

+30
-10
lines changed

1 file changed

+30
-10
lines changed

library/alloc/src/vec/mod.rs

+30-10
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,35 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
23782378
}
23792379
}
23802380

2381+
#[cfg(not(no_global_oom_handling))]
2382+
trait SpecCloneFrom {
2383+
fn clone_from(this: &mut Self, other: &Self);
2384+
}
2385+
2386+
#[cfg(not(no_global_oom_handling))]
2387+
impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
2388+
default fn clone_from(this: &mut Self, other: &Self) {
2389+
// drop anything that will not be overwritten
2390+
this.truncate(other.len());
2391+
2392+
// self.len <= other.len due to the truncate above, so the
2393+
// slices here are always in-bounds.
2394+
let (init, tail) = other.split_at(this.len());
2395+
2396+
// reuse the contained values' allocations/resources.
2397+
this.clone_from_slice(init);
2398+
this.extend_from_slice(tail);
2399+
}
2400+
}
2401+
2402+
#[cfg(not(no_global_oom_handling))]
2403+
impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
2404+
fn clone_from(this: &mut Self, other: &Self) {
2405+
this.clear();
2406+
this.extend_from_slice(other);
2407+
}
2408+
}
2409+
23812410
#[cfg(not(no_global_oom_handling))]
23822411
#[stable(feature = "rust1", since = "1.0.0")]
23832412
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
@@ -2398,16 +2427,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
23982427
}
23992428

24002429
fn clone_from(&mut self, other: &Self) {
2401-
// drop anything that will not be overwritten
2402-
self.truncate(other.len());
2403-
2404-
// self.len <= other.len due to the truncate above, so the
2405-
// slices here are always in-bounds.
2406-
let (init, tail) = other.split_at(self.len());
2407-
2408-
// reuse the contained values' allocations/resources.
2409-
self.clone_from_slice(init);
2410-
self.extend_from_slice(tail);
2430+
SpecCloneFrom::clone_from(self, other)
24112431
}
24122432
}
24132433

0 commit comments

Comments
 (0)