diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f26324127003b..31f5abef8b67b 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1244,7 +1244,26 @@ impl Vec { /// ``` #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] pub fn extend_from_slice(&mut self, other: &[T]) { - self.extend(other.iter().cloned()) + self.reserve(other.len()); + + // Unsafe code so this can be optimised to a memcpy (or something + // similarly fast) when T is Copy. LLVM is easily confused, so any + // extra operations during the loop can prevent this optimisation. + unsafe { + let len = self.len(); + let ptr = self.get_unchecked_mut(len) as *mut T; + // Use SetLenOnDrop to work around bug where compiler + // may not realize the store through `ptr` trough self.set_len() + // don't alias. + let mut local_len = SetLenOnDrop::new(&mut self.len); + + for i in 0..other.len() { + ptr::write(ptr.offset(i as isize), other.get_unchecked(i).clone()); + local_len.increment_len(1); + } + + // len set by scope guard + } } } @@ -1669,7 +1688,26 @@ impl Vec { #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { fn extend>(&mut self, iter: I) { - self.extend(iter.into_iter().map(|&x| x)) + >::extend_vec(iter, self); + } +} + +// helper trait for specialization of Vec's Extend<&T> impl +trait SpecExtendRef { + fn extend_vec(self, vec: &mut Vec); +} + +impl<'a, T: 'a + Copy, I> SpecExtendRef for I + where I: IntoIterator +{ + default fn extend_vec(self, vec: &mut Vec) { + vec.extend(self.into_iter().map(|&x| x)) + } +} + +impl<'a, T: Copy> SpecExtendRef for &'a [T] { + fn extend_vec(self, vec: &mut Vec) { + vec.extend_from_slice(self); } }