From f12698cc2dc3d4ddc09de9f9adda4b0048d116a3 Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Tue, 21 Oct 2025 13:35:25 +0300 Subject: [PATCH] Add const cloning of slices and tests --- library/core/src/slice/mod.rs | 29 +++++++++---- library/coretests/tests/clone.rs | 71 ++++++++++++++++++++++++++++++++ library/coretests/tests/lib.rs | 3 ++ 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 61eb78294f68b..406ab62549cd4 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -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}; @@ -3786,9 +3787,10 @@ impl [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); } @@ -5089,13 +5091,18 @@ impl [f64] { } } +#[const_trait] +#[rustc_const_unstable(feature = "const_clone", issue = "142757")] trait CloneFromSpec { - fn spec_clone_from(&mut self, src: &[T]); + fn spec_clone_from(&mut self, src: &[T]) + where + T: [const] Destruct; } -impl CloneFromSpec for [T] +#[rustc_const_unstable(feature = "const_clone", issue = "142757")] +impl const CloneFromSpec for [T] where - T: Clone, + T: [const] Clone + [const] Destruct, { #[track_caller] default fn spec_clone_from(&mut self, src: &[T]) { @@ -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 CloneFromSpec for [T] +#[rustc_const_unstable(feature = "const_clone", issue = "142757")] +impl const CloneFromSpec for [T] where - T: Copy, + T: Copy + [const] Clone + [const] Destruct, { #[track_caller] fn spec_clone_from(&mut self, src: &[T]) { diff --git a/library/coretests/tests/clone.rs b/library/coretests/tests/clone.rs index 054b1d3d4986c..68871dbccf07b 100644 --- a/library/coretests/tests/clone.rs +++ b/library/coretests/tests/clone.rs @@ -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]); + } +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index c2dc3a99ab109..3a6aaf3952fac 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -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)]