Skip to content

Commit 0913004

Browse files
committed
Auto merge of #31834 - ubsan:copy_from_slice, r=alexcrichton
implements rust-lang/rfcs#1419 r? alexcrichton
2 parents 9c6a008 + e12b1f9 commit 0913004

File tree

5 files changed

+63
-1
lines changed

5 files changed

+63
-1
lines changed

src/libcollections/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
2828

2929
#![cfg_attr(test, allow(deprecated))] // rand
30+
#![cfg_attr(not(test), feature(copy_from_slice))] // impl [T]
3031
#![cfg_attr(not(stage0), deny(warnings))]
3132

3233
#![feature(alloc)]

src/libcollections/slice.rs

+24
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,30 @@ impl<T> [T] {
837837
core_slice::SliceExt::clone_from_slice(self, src)
838838
}
839839

840+
/// Copies all elements from `src` into `self`, using a memcpy.
841+
///
842+
/// The length of `src` must be the same as `self`.
843+
///
844+
/// # Panics
845+
///
846+
/// This function will panic if the two slices have different lengths.
847+
///
848+
/// # Example
849+
///
850+
/// ```rust
851+
/// #![feature(copy_from_slice)]
852+
/// let mut dst = [0, 0, 0];
853+
/// let src = [1, 2, 3];
854+
///
855+
/// dst.copy_from_slice(&src);
856+
/// assert_eq!(src, dst);
857+
/// ```
858+
#[unstable(feature = "copy_from_slice", issue = "31755")]
859+
pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
860+
core_slice::SliceExt::copy_from_slice(self, src)
861+
}
862+
863+
840864
/// Copies `self` into a new `Vec`.
841865
#[stable(feature = "rust1", since = "1.0.0")]
842866
#[inline]

src/libcollectionstest/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#![feature(btree_range)]
1717
#![feature(collections)]
1818
#![feature(collections_bound)]
19+
#![feature(copy_from_slice)]
1920
#![feature(const_fn)]
2021
#![feature(fn_traits)]
2122
#![feature(enumset)]

src/libcollectionstest/slice.rs

+24
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,30 @@ fn test_box_slice_clone_panics() {
11381138
assert_eq!(drop_count.load(Ordering::SeqCst), 8);
11391139
}
11401140

1141+
#[test]
1142+
fn test_copy_from_slice() {
1143+
let src = [0, 1, 2, 3, 4, 5];
1144+
let mut dst = [0; 6];
1145+
dst.copy_from_slice(&src);
1146+
assert_eq!(src, dst)
1147+
}
1148+
1149+
#[test]
1150+
#[should_panic(expected = "destination and source slices have different lengths")]
1151+
fn test_copy_from_slice_dst_longer() {
1152+
let src = [0, 1, 2, 3];
1153+
let mut dst = [0; 5];
1154+
dst.copy_from_slice(&src);
1155+
}
1156+
1157+
#[test]
1158+
#[should_panic(expected = "destination and source slices have different lengths")]
1159+
fn test_copy_from_slice_dst_shorter() {
1160+
let src = [0, 1, 2, 3];
1161+
let mut dst = [0; 3];
1162+
dst.copy_from_slice(&src);
1163+
}
1164+
11411165
mod bench {
11421166
use std::{mem, ptr};
11431167
use std::__rand::{Rng, thread_rng};

src/libcore/slice.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use result::Result;
4848
use result::Result::{Ok, Err};
4949
use ptr;
5050
use mem;
51-
use marker::{Send, Sync, self};
51+
use marker::{Copy, Send, Sync, self};
5252
use raw::Repr;
5353
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
5454
use raw::Slice as RawSlice;
@@ -152,6 +152,8 @@ pub trait SliceExt {
152152

153153
#[stable(feature = "clone_from_slice", since = "1.7.0")]
154154
fn clone_from_slice(&mut self, &[Self::Item]) where Self::Item: Clone;
155+
#[unstable(feature = "copy_from_slice", issue = "31755")]
156+
fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
155157
}
156158

157159
// Use macros to be generic over const/mut
@@ -488,6 +490,16 @@ impl<T> SliceExt for [T] {
488490
self[i].clone_from(&src[i]);
489491
}
490492
}
493+
494+
#[inline]
495+
fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
496+
assert!(self.len() == src.len(),
497+
"destination and source slices have different lengths");
498+
unsafe {
499+
ptr::copy_nonoverlapping(
500+
src.as_ptr(), self.as_mut_ptr(), self.len());
501+
}
502+
}
491503
}
492504

493505
#[stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)