Skip to content

Commit 021a74c

Browse files
committed
Add impl const for Clone
1 parent 4eedad3 commit 021a74c

File tree

9 files changed

+151
-26
lines changed

9 files changed

+151
-26
lines changed

library/core/src/clone.rs

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

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

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

612615
#[stable(feature = "rust1", since = "1.0.0")]
613-
impl<T: PointeeSized> Clone for *mut T {
616+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
617+
impl<T: PointeeSized> const Clone for *mut T {
614618
#[inline(always)]
615619
fn clone(&self) -> Self {
616620
*self
@@ -619,7 +623,8 @@ mod impls {
619623

620624
/// Shared references can be cloned, but mutable references *cannot*!
621625
#[stable(feature = "rust1", since = "1.0.0")]
622-
impl<T: PointeeSized> Clone for &T {
626+
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
627+
impl<T: PointeeSized> const Clone for &T {
623628
#[inline(always)]
624629
#[rustc_diagnostic_item = "noop_method_clone"]
625630
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +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(Debug, Clone, Copy, PartialEq, Eq, Hash)]
86+
#[derive(Debug, Eq, Hash)]
87+
#[derive_const(Clone, Copy, PartialEq)]
8788
pub enum ControlFlow<B, C = ()> {
8889
/// Move on to the next phase of the operation as normal.
8990
#[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
@@ -122,7 +122,8 @@ macro_rules! tuple_impls {
122122
maybe_tuple_doc! {
123123
$($T)+ @
124124
#[stable(feature = "rust1", since = "1.0.0")]
125-
impl<$($T: Default),+> Default for ($($T,)+) {
125+
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
126+
impl<$($T: ~const Default),+> const Default for ($($T,)+) {
126127
#[inline]
127128
fn default() -> ($($T,)+) {
128129
($({ let x: $T = Default::default(); x},)+)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#![feature(
2+
const_trait_impl, const_default, const_clone, ptr_alignment_type,
3+
ascii_char, f16, f128, sync_unsafe_cell,
4+
)]
5+
#![allow(dead_code)]
6+
// core::default
7+
const UNIT: () = Default::default();
8+
const BOOL: bool = Default::default();
9+
const CHAR: char = Default::default();
10+
const ASCII_CHAR: std::ascii::Char = Default::default();
11+
const USIZE: usize = Default::default();
12+
const U8: u8 = Default::default();
13+
const U16: u16 = Default::default();
14+
const U32: u32 = Default::default();
15+
const U64: u64 = Default::default();
16+
const U128: u128 = Default::default();
17+
const I8: i8 = Default::default();
18+
const I16: i16 = Default::default();
19+
const I32: i32 = Default::default();
20+
const I64: i64 = Default::default();
21+
const I128: i128 = Default::default();
22+
const F16: f16 = Default::default();
23+
const F32: f32 = Default::default();
24+
const F64: f64 = Default::default();
25+
const F128: f128 = Default::default();
26+
// core::marker
27+
const PHANTOM: std::marker::PhantomData<()> = Default::default();
28+
// core::option
29+
const OPT: Option<i32> = Default::default();
30+
// core::iter::sources::empty
31+
const EMPTY: std::iter::Empty<()> = Default::default();
32+
// core::ptr::alignment
33+
const ALIGNMENT: std::ptr::Alignment = Default::default();
34+
// core::slice
35+
const SLICE: &[()] = Default::default();
36+
const MUT_SLICE: &mut [()] = Default::default();
37+
// core::str
38+
const STR: &str = Default::default();
39+
const MUT_STR: &mut str = Default::default();
40+
// core::cell
41+
const CELL: std::cell::Cell<()> = Default::default();
42+
const REF_CELL: std::cell::RefCell<()> = Default::default();
43+
const UNSAFE_CELL: std::cell::UnsafeCell<()> = Default::default();
44+
const SYNC_UNSAFE_CELL: std::cell::SyncUnsafeCell<()> = Default::default();
45+
const TUPLE: (u8, u16, u32, u64, u128, i8) = Default::default();
46+
47+
// core::clone
48+
const UNIT_CLONE: () = UNIT.clone();
49+
//~^ ERROR: the trait bound `(): const Clone` is not satisfied
50+
const BOOL_CLONE: bool = BOOL.clone();
51+
const CHAR_CLONE: char = CHAR.clone();
52+
const ASCII_CHAR_CLONE: std::ascii::Char = ASCII_CHAR.clone();
53+
//~^ ERROR: the trait bound `Char: const Clone` is not satisfied
54+
const USIZE_CLONE: usize = USIZE.clone();
55+
const U8_CLONE: u8 = U8.clone();
56+
const U16_CLONE: u16 = U16.clone();
57+
const U32_CLONE: u32 = U32.clone();
58+
const U64_CLONE: u64 = U64.clone();
59+
const U128_CLONE: u128 = U128.clone();
60+
const I8_CLONE: i8 = I8.clone();
61+
const I16_CLONE: i16 = I16.clone();
62+
const I32_CLONE: i32 = I32.clone();
63+
const I64_CLONE: i64 = I64.clone();
64+
const I128_CLONE: i128 = I128.clone();
65+
const F16_CLONE: f16 = F16.clone();
66+
const F32_CLONE: f32 = F32.clone();
67+
const F64_CLONE: f64 = F64.clone();
68+
const F128_CLONE: f128 = F128.clone();
69+
const TUPLE_CLONE: (u8, u16, u32, u64, u128, i8) = TUPLE.clone();
70+
//~^ ERROR: the trait bound `(u8, u16, u32, u64, u128, i8): const Clone` is not satisfied [E0277]
71+
72+
fn main() {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0277]: the trait bound `(): const Clone` is not satisfied
2+
--> $DIR/const-clone.rs:48:29
3+
|
4+
LL | const UNIT_CLONE: () = UNIT.clone();
5+
| ^^^^^
6+
7+
error[E0277]: the trait bound `Char: const Clone` is not satisfied
8+
--> $DIR/const-clone.rs:52:55
9+
|
10+
LL | const ASCII_CHAR_CLONE: std::ascii::Char = ASCII_CHAR.clone();
11+
| ^^^^^
12+
13+
error[E0277]: the trait bound `(u8, u16, u32, u64, u128, i8): const Clone` is not satisfied
14+
--> $DIR/const-clone.rs:69:59
15+
|
16+
LL | const TUPLE_CLONE: (u8, u16, u32, u64, u128, i8) = TUPLE.clone();
17+
| ^^^^^
18+
19+
error: aborting due to 3 previous errors
20+
21+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)