Skip to content

Commit a9d719b

Browse files
committed
Add impl const for Clone
1 parent 4ba1cf9 commit a9d719b

File tree

9 files changed

+124
-27
lines changed

9 files changed

+124
-27
lines changed

library/core/src/clone.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@ mod impls {
575575
($($t:ty)*) => {
576576
$(
577577
#[stable(feature = "rust1", since = "1.0.0")]
578-
impl Clone for $t {
578+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
579+
impl const Clone for $t {
579580
#[inline(always)]
580581
fn clone(&self) -> Self {
581582
*self
@@ -593,23 +594,26 @@ mod impls {
593594
}
594595

595596
#[unstable(feature = "never_type", issue = "35121")]
596-
impl Clone for ! {
597+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
598+
impl const Clone for ! {
597599
#[inline]
598600
fn clone(&self) -> Self {
599601
*self
600602
}
601603
}
602604

603605
#[stable(feature = "rust1", since = "1.0.0")]
604-
impl<T: PointeeSized> Clone for *const T {
606+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
607+
impl<T: PointeeSized> const Clone for *const T {
605608
#[inline(always)]
606609
fn clone(&self) -> Self {
607610
*self
608611
}
609612
}
610613

611614
#[stable(feature = "rust1", since = "1.0.0")]
612-
impl<T: PointeeSized> Clone for *mut T {
615+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
616+
impl<T: PointeeSized> const Clone for *mut T {
613617
#[inline(always)]
614618
fn clone(&self) -> Self {
615619
*self
@@ -618,7 +622,8 @@ mod impls {
618622

619623
/// Shared references can be cloned, but mutable references *cannot*!
620624
#[stable(feature = "rust1", since = "1.0.0")]
621-
impl<T: PointeeSized> Clone for &T {
625+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
626+
impl<T: PointeeSized> const Clone for &T {
622627
#[inline(always)]
623628
#[rustc_diagnostic_item = "noop_method_clone"]
624629
fn clone(&self) -> Self {

library/core/src/marker.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,9 @@ marker_impls! {
462462
// library, and there's no way to safely have this behavior right now.
463463
#[rustc_unsafe_specialization_marker]
464464
#[rustc_diagnostic_item = "Copy"]
465-
pub trait Copy: Clone {
465+
#[const_trait]
466+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
467+
pub trait Copy: [const] Clone {
466468
// Empty.
467469
}
468470

library/core/src/ops/control_flow.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ use crate::{convert, ops};
8383
#[must_use]
8484
// ControlFlow should not implement PartialOrd or Ord, per RFC 3058:
8585
// https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow
86-
#[derive(Copy, Debug, Hash)]
87-
#[derive_const(Clone, PartialEq, Eq)]
86+
#[derive(Debug, Hash)]
87+
#[derive_const(Copy, Clone, PartialEq, Eq)]
8888
pub enum ControlFlow<B, C = ()> {
8989
/// Move on to the next phase of the operation as normal.
9090
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]

library/core/src/ops/index_range.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use crate::ub_checks;
99
///
1010
/// (Normal `Range` code needs to handle degenerate ranges like `10..0`,
1111
/// which takes extra checks compared to only handling the canonical form.)
12-
#[derive(Clone, Debug, PartialEq, Eq)]
12+
#[derive(Debug, Eq)]
13+
#[derive_const(Clone, PartialEq)]
1314
pub(crate) struct IndexRange {
1415
start: usize,
1516
end: usize,

library/core/src/ops/range.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ use crate::hash::Hash;
3838
/// [slicing index]: crate::slice::SliceIndex
3939
#[lang = "RangeFull"]
4040
#[doc(alias = "..")]
41-
#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
41+
#[derive(Eq, Hash)]
42+
#[derive_const(Copy, Clone, Default, PartialEq)]
4243
#[stable(feature = "rust1", since = "1.0.0")]
4344
pub struct RangeFull;
4445

@@ -75,7 +76,8 @@ impl fmt::Debug for RangeFull {
7576
/// ```
7677
#[lang = "Range"]
7778
#[doc(alias = "..")]
78-
#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186
79+
#[derive(Eq, Hash)]
80+
#[derive_const(Clone, Default, PartialEq)] // not Copy -- see #27186
7981
#[stable(feature = "rust1", since = "1.0.0")]
8082
pub struct Range<Idx> {
8183
/// The lower bound of the range (inclusive).
@@ -184,7 +186,8 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
184186
/// ```
185187
#[lang = "RangeFrom"]
186188
#[doc(alias = "..")]
187-
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
189+
#[derive(Eq, Hash)]
190+
#[derive_const(Clone, PartialEq)] // not Copy -- see #27186
188191
#[stable(feature = "rust1", since = "1.0.0")]
189192
pub struct RangeFrom<Idx> {
190193
/// The lower bound of the range (inclusive).
@@ -266,7 +269,8 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
266269
/// [slicing index]: crate::slice::SliceIndex
267270
#[lang = "RangeTo"]
268271
#[doc(alias = "..")]
269-
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
272+
#[derive(Eq, Hash)]
273+
#[derive_const(Copy, Clone, PartialEq)]
270274
#[stable(feature = "rust1", since = "1.0.0")]
271275
pub struct RangeTo<Idx> {
272276
/// The upper bound of the range (exclusive).
@@ -340,7 +344,8 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
340344
/// ```
341345
#[lang = "RangeInclusive"]
342346
#[doc(alias = "..=")]
343-
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
347+
#[derive(Eq, Hash)]
348+
#[derive_const(Clone, PartialEq)] // not Copy -- see #27186
344349
#[stable(feature = "inclusive_range", since = "1.26.0")]
345350
pub struct RangeInclusive<Idx> {
346351
// Note that the fields here are not public to allow changing the
@@ -587,7 +592,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
587592
/// [slicing index]: crate::slice::SliceIndex
588593
#[lang = "RangeToInclusive"]
589594
#[doc(alias = "..=")]
590-
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
595+
#[derive(Hash)]
596+
#[derive(Copy, Clone, PartialEq, Eq)]
591597
#[stable(feature = "inclusive_range", since = "1.26.0")]
592598
pub struct RangeToInclusive<Idx> {
593599
/// The upper bound of the range (inclusive)
@@ -668,7 +674,8 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
668674
///
669675
/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
670676
#[stable(feature = "collections_bound", since = "1.17.0")]
671-
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
677+
#[derive(Debug, Eq, Hash)]
678+
#[derive_const(Clone, Copy, PartialEq)]
672679
pub enum Bound<T> {
673680
/// An inclusive bound.
674681
#[stable(feature = "collections_bound", since = "1.17.0")]

library/core/src/slice/mod.rs

Lines changed: 25 additions & 10 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};
@@ -3785,10 +3786,12 @@ impl<T> [T] {
37853786
/// [`copy_from_slice`]: slice::copy_from_slice
37863787
/// [`split_at_mut`]: slice::split_at_mut
37873788
#[stable(feature = "clone_from_slice", since = "1.7.0")]
3789+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
3790+
#[rustc_allow_const_fn_unstable(const_precise_live_drops)]
37883791
#[track_caller]
3789-
pub fn clone_from_slice(&mut self, src: &[T])
3792+
pub const fn clone_from_slice(&mut self, src: &[T])
37903793
where
3791-
T: Clone,
3794+
T: [const] Clone + [const] Destruct,
37923795
{
37933796
self.spec_clone_from(src);
37943797
}
@@ -5089,31 +5092,43 @@ impl [f64] {
50895092
}
50905093
}
50915094

5095+
#[const_trait]
5096+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
50925097
trait CloneFromSpec<T> {
5093-
fn spec_clone_from(&mut self, src: &[T]);
5098+
fn spec_clone_from(&mut self, src: &[T])
5099+
where
5100+
T: [const] Destruct;
50945101
}
50955102

5096-
impl<T> CloneFromSpec<T> for [T]
5103+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
5104+
impl<T> const CloneFromSpec<T> for [T]
50975105
where
5098-
T: Clone,
5106+
T: [const] Clone,
50995107
{
51005108
#[track_caller]
5101-
default fn spec_clone_from(&mut self, src: &[T]) {
5109+
default fn spec_clone_from(&mut self, src: &[T])
5110+
where
5111+
T: [const] Destruct,
5112+
{
51025113
assert!(self.len() == src.len(), "destination and source slices have different lengths");
51035114
// NOTE: We need to explicitly slice them to the same length
51045115
// to make it easier for the optimizer to elide bounds checking.
51055116
// But since it can't be relied on we also have an explicit specialization for T: Copy.
51065117
let len = self.len();
51075118
let src = &src[..len];
5108-
for i in 0..len {
5109-
self[i].clone_from(&src[i]);
5119+
// FIXME(const_hack): make this a `for idx in 0..self.len()` loop.
5120+
let mut idx = 0;
5121+
while idx < self.len() {
5122+
self[idx].clone_from(&src[idx]);
5123+
idx += 1;
51105124
}
51115125
}
51125126
}
51135127

5114-
impl<T> CloneFromSpec<T> for [T]
5128+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
5129+
impl<T> const CloneFromSpec<T> for [T]
51155130
where
5116-
T: Copy,
5131+
T: [const] Copy,
51175132
{
51185133
#[track_caller]
51195134
fn spec_clone_from(&mut self, src: &[T]) {

library/core/src/tuple.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ macro_rules! tuple_impls {
126126
maybe_tuple_doc! {
127127
$($T)+ @
128128
#[stable(feature = "rust1", since = "1.0.0")]
129-
impl<$($T: Default),+> Default for ($($T,)+) {
129+
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
130+
impl<$($T: ~const Default),+> const Default for ($($T,)+) {
130131
#[inline]
131132
fn default() -> ($($T,)+) {
132133
($({ let x: $T = Default::default(); x},)+)

library/coretests/tests/clone.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,67 @@ 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+
// assert!(TUPLE == TUPLE_CLONE);
186+
}
187+
}

library/coretests/tests/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
#![feature(cfg_target_has_reliable_f16_f128)]
1616
#![feature(char_max_len)]
1717
#![feature(clone_to_uninit)]
18+
#![feature(const_clone)]
1819
#![feature(const_cmp)]
1920
#![feature(const_convert)]
21+
#![feature(const_default)]
2022
#![feature(const_destruct)]
2123
#![feature(const_eval_select)]
2224
#![feature(const_ops)]

0 commit comments

Comments
 (0)