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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions library/core/src/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ mod impls {
($($t:ty)*) => {
$(
#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for $t {
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
impl const Clone for $t {
#[inline(always)]
fn clone(&self) -> Self {
*self
Expand All @@ -593,23 +594,26 @@ mod impls {
}

#[unstable(feature = "never_type", issue = "35121")]
impl Clone for ! {
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
impl const Clone for ! {
#[inline]
fn clone(&self) -> Self {
*self
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PointeeSized> Clone for *const T {
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
impl<T: PointeeSized> const Clone for *const T {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}

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

/// Shared references can be cloned, but mutable references *cannot*!
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PointeeSized> Clone for &T {
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
impl<T: PointeeSized> const Clone for &T {
#[inline(always)]
#[rustc_diagnostic_item = "noop_method_clone"]
fn clone(&self) -> Self {
Expand Down
4 changes: 3 additions & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,9 @@ marker_impls! {
// library, and there's no way to safely have this behavior right now.
#[rustc_unsafe_specialization_marker]
#[rustc_diagnostic_item = "Copy"]
pub trait Copy: Clone {
#[const_trait]
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
pub trait Copy: [const] Clone {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rust-lang/wg-const-eval in a perfect world Copy would imply const Clone. But since users can manually write out Copy and separate Clone impls, I don't think we could do this.

Just making sure we're all aware of this situation and whether we'd want to mitigate it by something funky like making manual Clone impls for Copy types automatically make the impl const no matter its written constness

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

making manual Clone impls for Copy types automatically make the impl const no matter its written constness

That would be a breaking change, wouldn't it?

const Copy is a funny concept to begin with, it makes fairly little sense... there's not really any way in which a type can be runtime-only Copy, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we used to think the same about Sized. What if runtime sized types also need a runtime copy op?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was also a similar discussion in context of const Eq.
#144847 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I keep this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well... I can't tell without a compiler code deep dive what the implications of ppl being able to write const Copy bounds are

// Empty.
}

Expand Down
4 changes: 2 additions & 2 deletions library/core/src/ops/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ use crate::{convert, ops};
#[must_use]
// ControlFlow should not implement PartialOrd or Ord, per RFC 3058:
// https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow
#[derive(Copy, Debug, Hash)]
#[derive_const(Clone, PartialEq, Eq)]
#[derive(Debug, Hash)]
#[derive_const(Copy, Clone, PartialEq, Eq)]
pub enum ControlFlow<B, C = ()> {
/// Move on to the next phase of the operation as normal.
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/ops/index_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use crate::ub_checks;
///
/// (Normal `Range` code needs to handle degenerate ranges like `10..0`,
/// which takes extra checks compared to only handling the canonical form.)
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Debug, Eq)]
#[derive_const(Clone, PartialEq)]
pub(crate) struct IndexRange {
start: usize,
end: usize,
Expand Down
21 changes: 14 additions & 7 deletions library/core/src/ops/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ use crate::hash::Hash;
/// [slicing index]: crate::slice::SliceIndex
#[lang = "RangeFull"]
#[doc(alias = "..")]
#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
#[derive(Eq, Hash)]
#[derive_const(Copy, Clone, Default, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFull;

Expand Down Expand Up @@ -75,7 +76,8 @@ impl fmt::Debug for RangeFull {
/// ```
#[lang = "Range"]
#[doc(alias = "..")]
#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[derive(Eq, Hash)]
#[derive_const(Clone, Default, PartialEq)] // not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Range<Idx> {
/// The lower bound of the range (inclusive).
Expand Down Expand Up @@ -184,7 +186,8 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// ```
#[lang = "RangeFrom"]
#[doc(alias = "..")]
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[derive(Eq, Hash)]
#[derive_const(Clone, PartialEq)] // not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFrom<Idx> {
/// The lower bound of the range (inclusive).
Expand Down Expand Up @@ -266,7 +269,8 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// [slicing index]: crate::slice::SliceIndex
#[lang = "RangeTo"]
#[doc(alias = "..")]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Eq, Hash)]
#[derive_const(Copy, Clone, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeTo<Idx> {
/// The upper bound of the range (exclusive).
Expand Down Expand Up @@ -340,7 +344,8 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// ```
#[lang = "RangeInclusive"]
#[doc(alias = "..=")]
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[derive(Eq, Hash)]
#[derive_const(Clone, PartialEq)] // not Copy -- see #27186
#[stable(feature = "inclusive_range", since = "1.26.0")]
pub struct RangeInclusive<Idx> {
// Note that the fields here are not public to allow changing the
Expand Down Expand Up @@ -587,7 +592,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// [slicing index]: crate::slice::SliceIndex
#[lang = "RangeToInclusive"]
#[doc(alias = "..=")]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Hash)]
#[derive_const(Copy, Clone, PartialEq, Eq)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
pub struct RangeToInclusive<Idx> {
/// The upper bound of the range (inclusive)
Expand Down Expand Up @@ -668,7 +674,8 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
///
/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
#[stable(feature = "collections_bound", since = "1.17.0")]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[derive(Debug, Eq, Hash)]
#[derive_const(Clone, Copy, PartialEq)]
pub enum Bound<T> {
/// An inclusive bound.
#[stable(feature = "collections_bound", since = "1.17.0")]
Expand Down
14 changes: 11 additions & 3 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 @@ -5089,8 +5090,12 @@ 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]
Expand All @@ -5105,8 +5110,11 @@ 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;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[stable(feature = "rust1", since = "1.0.0")]
impl<$($T: Default),+> Default for ($($T,)+) {
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
impl<$($T: ~const Default),+> const Default for ($($T,)+) {
#[inline]
fn default() -> ($($T,)+) {
($({ let x: $T = Default::default(); x},)+)
Expand Down
63 changes: 63 additions & 0 deletions library/coretests/tests/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,66 @@ 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);
}
}
3 changes: 3 additions & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
#![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_eval_select)]
#![feature(const_index)]
#![feature(const_mul_add)]
#![feature(const_ops)]
#![feature(const_option_ops)]
Expand Down
Loading