Skip to content

Commit d7b7f2c

Browse files
committed
Add const cloning of slices and tests
1 parent f2bae99 commit d7b7f2c

File tree

3 files changed

+94
-9
lines changed

3 files changed

+94
-9
lines changed

library/core/src/slice/mod.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use crate::cmp::Ordering::{self, Equal, Greater, Less};
1010
use crate::intrinsics::{exact_div, unchecked_sub};
11+
use crate::marker::Destruct;
1112
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
1213
use crate::num::NonZero;
1314
use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive};
@@ -3818,9 +3819,10 @@ impl<T> [T] {
38183819
/// [`split_at_mut`]: slice::split_at_mut
38193820
#[stable(feature = "clone_from_slice", since = "1.7.0")]
38203821
#[track_caller]
3821-
pub fn clone_from_slice(&mut self, src: &[T])
3822+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
3823+
pub const fn clone_from_slice(&mut self, src: &[T])
38223824
where
3823-
T: Clone,
3825+
T: [const] Clone + [const] Destruct,
38243826
{
38253827
self.spec_clone_from(src);
38263828
}
@@ -5121,13 +5123,18 @@ impl [f64] {
51215123
}
51225124
}
51235125

5126+
#[const_trait]
5127+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
51245128
trait CloneFromSpec<T> {
5125-
fn spec_clone_from(&mut self, src: &[T]);
5129+
fn spec_clone_from(&mut self, src: &[T])
5130+
where
5131+
T: [const] Destruct;
51265132
}
51275133

5128-
impl<T> CloneFromSpec<T> for [T]
5134+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
5135+
impl<T> const CloneFromSpec<T> for [T]
51295136
where
5130-
T: Clone,
5137+
T: [const] Clone + [const] Destruct,
51315138
{
51325139
#[track_caller]
51335140
default fn spec_clone_from(&mut self, src: &[T]) {
@@ -5137,15 +5144,19 @@ where
51375144
// But since it can't be relied on we also have an explicit specialization for T: Copy.
51385145
let len = self.len();
51395146
let src = &src[..len];
5140-
for i in 0..len {
5141-
self[i].clone_from(&src[i]);
5147+
// FIXME(const_hack): make this a `for idx in 0..self.len()` loop.
5148+
let mut idx = 0;
5149+
while idx < self.len() {
5150+
self[idx].clone_from(&src[idx]);
5151+
idx += 1;
51425152
}
51435153
}
51445154
}
51455155

5146-
impl<T> CloneFromSpec<T> for [T]
5156+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
5157+
impl<T> const CloneFromSpec<T> for [T]
51475158
where
5148-
T: Copy,
5159+
T: Copy + [const] Clone + [const] Destruct,
51495160
{
51505161
#[track_caller]
51515162
fn spec_clone_from(&mut self, src: &[T]) {

library/coretests/tests/clone.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,74 @@ fn cstr_metadata_is_length_with_nul() {
121121
let bytes: *const [u8] = p as *const [u8];
122122
assert_eq!(s.to_bytes_with_nul().len(), bytes.len());
123123
}
124+
125+
#[test]
126+
fn test_const_clone() {
127+
const {
128+
let bool: bool = Default::default();
129+
let char: char = Default::default();
130+
let ascii_char: std::ascii::Char = Default::default();
131+
let usize: usize = Default::default();
132+
let u8: u8 = Default::default();
133+
let u16: u16 = Default::default();
134+
let u32: u32 = Default::default();
135+
let u64: u64 = Default::default();
136+
let u128: u128 = Default::default();
137+
let i8: i8 = Default::default();
138+
let i16: i16 = Default::default();
139+
let i32: i32 = Default::default();
140+
let i64: i64 = Default::default();
141+
let i128: i128 = Default::default();
142+
let f16: f16 = Default::default();
143+
let f32: f32 = Default::default();
144+
let f64: f64 = Default::default();
145+
let f128: f128 = Default::default();
146+
147+
let bool_clone: bool = bool.clone();
148+
let char_clone: char = char.clone();
149+
let ascii_char_clone: std::ascii::Char = ascii_char.clone();
150+
151+
let usize_clone: usize = usize.clone();
152+
let u8_clone: u8 = u8.clone();
153+
let u16_clone: u16 = u16.clone();
154+
let u32_clone: u32 = u32.clone();
155+
let u64_clone: u64 = u64.clone();
156+
let u128_clone: u128 = u128.clone();
157+
let i8_clone: i8 = i8.clone();
158+
let i16_clone: i16 = i16.clone();
159+
let i32_clone: i32 = i32.clone();
160+
let i64_clone: i64 = i64.clone();
161+
let i128_clone: i128 = i128.clone();
162+
let f16_clone: f16 = f16.clone();
163+
let f32_clone: f32 = f32.clone();
164+
let f64_clone: f64 = f64.clone();
165+
let f128_clone: f128 = f128.clone();
166+
167+
assert!(bool == bool_clone);
168+
assert!(char == char_clone);
169+
assert!(ascii_char == ascii_char_clone);
170+
assert!(usize == usize_clone);
171+
assert!(u8 == u8_clone);
172+
assert!(u16 == u16_clone);
173+
assert!(u32 == u32_clone);
174+
assert!(u64 == u64_clone);
175+
assert!(u128 == u128_clone);
176+
assert!(i8 == i8_clone);
177+
assert!(i16 == i16_clone);
178+
assert!(i32 == i32_clone);
179+
assert!(i64 == i64_clone);
180+
assert!(i128 == i128_clone);
181+
assert!(f16 == f16_clone);
182+
assert!(f32 == f32_clone);
183+
assert!(f64 == f64_clone);
184+
assert!(f128 == f128_clone);
185+
186+
let src: [i32; 4] = [1, 2, 3, 4];
187+
let mut dst: [i32; 2] = [0, 0];
188+
189+
dst.clone_from_slice(&src[2..]);
190+
191+
assert!(src == [1, 2, 3, 4]);
192+
assert!(dst == [3, 4]);
193+
}
194+
}

library/coretests/tests/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717
#![feature(char_max_len)]
1818
#![feature(clone_to_uninit)]
1919
#![feature(const_cell_traits)]
20+
#![feature(const_clone)]
2021
#![feature(const_cmp)]
2122
#![feature(const_convert)]
23+
#![feature(const_default)]
2224
#![feature(const_destruct)]
2325
#![feature(const_drop_in_place)]
2426
#![feature(const_eval_select)]
27+
#![feature(const_index)]
2528
#![feature(const_mul_add)]
2629
#![feature(const_ops)]
2730
#![feature(const_option_ops)]

0 commit comments

Comments
 (0)