Skip to content

Commit

Permalink
Auto merge of #81854 - the8472:specialize-clone-slice, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
specialize slice::clone_from_slice() for T: Copy
  • Loading branch information
bors committed Feb 13, 2021
2 parents dd4851d + 130fb24 commit 3158857
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2944,15 +2944,7 @@ impl<T> [T] {
where
T: Clone,
{
assert!(self.len() == src.len(), "destination and source slices have different lengths");
// NOTE: We need to explicitly slice them to the same length
// for bounds checking to be elided, and the optimizer will
// generate memcpy for simple cases (for example T = u8).
let len = self.len();
let src = &src[..len];
for i in 0..len {
self[i].clone_from(&src[i]);
}
self.spec_clone_from(src);
}

/// Copies all elements from `src` into `self`, using a memcpy.
Expand Down Expand Up @@ -3461,6 +3453,36 @@ impl<T> [T] {
}
}

trait CloneFromSpec<T> {
fn spec_clone_from(&mut self, src: &[T]);
}

impl<T> CloneFromSpec<T> for [T]
where
T: Clone,
{
default fn spec_clone_from(&mut self, src: &[T]) {
assert!(self.len() == src.len(), "destination and source slices have different lengths");
// NOTE: We need to explicitly slice them to the same length
// to make it easier for the optimizer to elide bounds checking.
// But since it can't be relied on we also have an explicit specialization for T: Copy.
let len = self.len();
let src = &src[..len];
for i in 0..len {
self[i].clone_from(&src[i]);
}
}
}

impl<T> CloneFromSpec<T> for [T]
where
T: Copy,
{
fn spec_clone_from(&mut self, src: &[T]) {
self.copy_from_slice(src);
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for &[T] {
/// Creates an empty slice.
Expand Down

0 comments on commit 3158857

Please sign in to comment.