Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::intrinsics::{exact_div, unchecked_sub};
use crate::marker::Destruct;
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
use crate::num::NonZero;
use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive};
Expand Down Expand Up @@ -3786,9 +3787,10 @@ impl<T> [T] {
/// [`split_at_mut`]: slice::split_at_mut
#[stable(feature = "clone_from_slice", since = "1.7.0")]
#[track_caller]
pub fn clone_from_slice(&mut self, src: &[T])
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
pub const fn clone_from_slice(&mut self, src: &[T])
where
T: Clone,
T: [const] Clone + [const] Destruct,
{
self.spec_clone_from(src);
}
Expand Down Expand Up @@ -5089,13 +5091,18 @@ impl [f64] {
}
}

#[const_trait]
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
trait CloneFromSpec<T> {
fn spec_clone_from(&mut self, src: &[T]);
fn spec_clone_from(&mut self, src: &[T])
where
T: [const] Destruct;
}

impl<T> CloneFromSpec<T> for [T]
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
impl<T> const CloneFromSpec<T> for [T]
where
T: Clone,
T: [const] Clone + [const] Destruct,
{
#[track_caller]
default fn spec_clone_from(&mut self, src: &[T]) {
Expand All @@ -5105,15 +5112,19 @@ where
// 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]);
// FIXME(const_hack): make this a `for idx in 0..self.len()` loop.
let mut idx = 0;
while idx < self.len() {
self[idx].clone_from(&src[idx]);
idx += 1;
}
}
}

impl<T> CloneFromSpec<T> for [T]
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
impl<T> const CloneFromSpec<T> for [T]
where
T: Copy,
T: Copy + [const] Clone + [const] Destruct,
{
#[track_caller]
fn spec_clone_from(&mut self, src: &[T]) {
Expand Down
71 changes: 71 additions & 0 deletions library/coretests/tests/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,74 @@ fn cstr_metadata_is_length_with_nul() {
let bytes: *const [u8] = p as *const [u8];
assert_eq!(s.to_bytes_with_nul().len(), bytes.len());
}

#[test]
fn test_const_clone() {
const {
let bool: bool = Default::default();
let char: char = Default::default();
let ascii_char: std::ascii::Char = Default::default();
let usize: usize = Default::default();
let u8: u8 = Default::default();
let u16: u16 = Default::default();
let u32: u32 = Default::default();
let u64: u64 = Default::default();
let u128: u128 = Default::default();
let i8: i8 = Default::default();
let i16: i16 = Default::default();
let i32: i32 = Default::default();
let i64: i64 = Default::default();
let i128: i128 = Default::default();
let f16: f16 = Default::default();
let f32: f32 = Default::default();
let f64: f64 = Default::default();
let f128: f128 = Default::default();

let bool_clone: bool = bool.clone();
let char_clone: char = char.clone();
let ascii_char_clone: std::ascii::Char = ascii_char.clone();

let usize_clone: usize = usize.clone();
let u8_clone: u8 = u8.clone();
let u16_clone: u16 = u16.clone();
let u32_clone: u32 = u32.clone();
let u64_clone: u64 = u64.clone();
let u128_clone: u128 = u128.clone();
let i8_clone: i8 = i8.clone();
let i16_clone: i16 = i16.clone();
let i32_clone: i32 = i32.clone();
let i64_clone: i64 = i64.clone();
let i128_clone: i128 = i128.clone();
let f16_clone: f16 = f16.clone();
let f32_clone: f32 = f32.clone();
let f64_clone: f64 = f64.clone();
let f128_clone: f128 = f128.clone();

assert!(bool == bool_clone);
assert!(char == char_clone);
assert!(ascii_char == ascii_char_clone);
assert!(usize == usize_clone);
assert!(u8 == u8_clone);
assert!(u16 == u16_clone);
assert!(u32 == u32_clone);
assert!(u64 == u64_clone);
assert!(u128 == u128_clone);
assert!(i8 == i8_clone);
assert!(i16 == i16_clone);
assert!(i32 == i32_clone);
assert!(i64 == i64_clone);
assert!(i128 == i128_clone);
assert!(f16 == f16_clone);
assert!(f32 == f32_clone);
assert!(f64 == f64_clone);
assert!(f128 == f128_clone);

let src: [i32; 4] = [1, 2, 3, 4];
let mut dst: [i32; 2] = [0, 0];

dst.clone_from_slice(&src[2..]);

assert!(src == [1, 2, 3, 4]);
assert!(dst == [3, 4]);
}
}
3 changes: 3 additions & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
#![feature(char_internals)]
#![feature(char_max_len)]
#![feature(clone_to_uninit)]
#![feature(const_clone)]
#![feature(const_cmp)]
#![feature(const_convert)]
#![feature(const_default)]
#![feature(const_destruct)]
#![feature(const_drop_in_place)]
#![feature(const_eval_select)]
#![feature(const_index)]
#![feature(const_mul_add)]
#![feature(const_ops)]
#![feature(const_option_ops)]
Expand Down
Loading