(almost) get rid of the unsound #[rustc_unsafe_specialization_marker] on Copy, introduce TrivialClone
This commit is contained in:
parent
acda5e9f9a
commit
5fb5861765
24 changed files with 190 additions and 56 deletions
|
|
@ -1,4 +1,6 @@
|
|||
use core::any::Any;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::TrivialClone;
|
||||
use core::error::Error;
|
||||
use core::mem;
|
||||
use core::pin::Pin;
|
||||
|
|
@ -75,11 +77,13 @@ impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
|
|||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy> BoxFromSlice<T> for Box<[T]> {
|
||||
impl<T: TrivialClone> BoxFromSlice<T> for Box<[T]> {
|
||||
#[inline]
|
||||
fn from_slice(slice: &[T]) -> Self {
|
||||
let len = slice.len();
|
||||
let buf = RawVec::with_capacity(len);
|
||||
// SAFETY: since `T` implements `TrivialClone`, this is sound and
|
||||
// equivalent to the above.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
|
||||
buf.into_box(slice.len()).assume_init()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::TrivialClone;
|
||||
use core::cmp::{self, Ordering};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{ByRefSized, repeat_n, repeat_with};
|
||||
|
|
@ -3419,7 +3421,7 @@ impl<T: Clone, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
|
|||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
|
||||
impl<T: TrivialClone, A: Allocator> SpecExtendFromWithin for VecDeque<T, A> {
|
||||
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
|
||||
let dst = self.len();
|
||||
let count = src.end - src.start;
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@
|
|||
#![feature(std_internals)]
|
||||
#![feature(str_internals)]
|
||||
#![feature(temporary_niche_types)]
|
||||
#![feature(trivial_clone)]
|
||||
#![feature(trusted_fused)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(trusted_random_access)]
|
||||
|
|
|
|||
|
|
@ -243,9 +243,9 @@
|
|||
|
||||
use core::any::Any;
|
||||
use core::cell::{Cell, CloneFromCell};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::CloneToUninit;
|
||||
use core::clone::UseCloned;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::{CloneToUninit, TrivialClone};
|
||||
use core::cmp::Ordering;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::intrinsics::abort;
|
||||
|
|
@ -2224,7 +2224,8 @@ impl<T> Rc<[T]> {
|
|||
|
||||
/// Copy elements from slice into newly allocated `Rc<[T]>`
|
||||
///
|
||||
/// Unsafe because the caller must either take ownership or bind `T: Copy`
|
||||
/// Unsafe because the caller must either take ownership, bind `T: Copy` or
|
||||
/// bind `T: TrivialClone`.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
|
||||
unsafe {
|
||||
|
|
@ -2314,9 +2315,11 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
|
|||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy> RcFromSlice<T> for Rc<[T]> {
|
||||
impl<T: TrivialClone> RcFromSlice<T> for Rc<[T]> {
|
||||
#[inline]
|
||||
fn from_slice(v: &[T]) -> Self {
|
||||
// SAFETY: `T` implements `TrivialClone`, so this is sound and equivalent
|
||||
// to the above.
|
||||
unsafe { Rc::copy_from_slice(v) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::TrivialClone;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::cmp::Ordering::{self, Less};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::mem::MaybeUninit;
|
||||
|
|
@ -439,7 +441,7 @@ impl<T> [T] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> ConvertVec for T {
|
||||
impl<T: TrivialClone> ConvertVec for T {
|
||||
#[inline]
|
||||
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
|
||||
let mut v = Vec::with_capacity_in(s.len(), alloc);
|
||||
|
|
@ -822,7 +824,7 @@ impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
|||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
||||
impl<T: TrivialClone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
||||
fn clone_into(&self, target: &mut Vec<T, A>) {
|
||||
target.clear();
|
||||
target.extend_from_slice(self);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use core::any::Any;
|
|||
use core::cell::CloneFromCell;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::CloneToUninit;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::TrivialClone;
|
||||
use core::clone::UseCloned;
|
||||
use core::cmp::Ordering;
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
|
@ -2156,7 +2158,8 @@ impl<T> Arc<[T]> {
|
|||
|
||||
/// Copy elements from slice into newly allocated `Arc<[T]>`
|
||||
///
|
||||
/// Unsafe because the caller must either take ownership or bind `T: Copy`.
|
||||
/// Unsafe because the caller must either take ownership, bind `T: Copy` or
|
||||
/// bind `T: TrivialClone`.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
|
||||
unsafe {
|
||||
|
|
@ -2248,9 +2251,11 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
|
|||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
|
||||
impl<T: TrivialClone> ArcFromSlice<T> for Arc<[T]> {
|
||||
#[inline]
|
||||
fn from_slice(v: &[T]) -> Self {
|
||||
// SAFETY: `T` implements `TrivialClone`, so this is sound and equivalent
|
||||
// to the above.
|
||||
unsafe { Arc::copy_from_slice(v) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::TrivialClone;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::cmp;
|
||||
use core::cmp::Ordering;
|
||||
|
|
@ -3494,7 +3496,7 @@ impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
|
|||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
|
||||
impl<T: TrivialClone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
|
||||
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
|
||||
let count = src.len();
|
||||
{
|
||||
|
|
@ -3507,8 +3509,8 @@ impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
|
|||
// SAFETY:
|
||||
// - Both pointers are created from unique slice references (`&mut [_]`)
|
||||
// so they are valid and do not overlap.
|
||||
// - Elements are :Copy so it's OK to copy them, without doing
|
||||
// anything with the original values
|
||||
// - Elements implement `TrivialClone` so this is equivalent to calling
|
||||
// `clone` on every one of them.
|
||||
// - `count` is equal to the len of `source`, so source is valid for
|
||||
// `count` reads
|
||||
// - `.reserve(count)` guarantees that `spare.len() >= count` so spare
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use core::clone::TrivialClone;
|
||||
use core::iter::TrustedLen;
|
||||
use core::slice::{self};
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ where
|
|||
|
||||
impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A>
|
||||
where
|
||||
T: Copy,
|
||||
T: TrivialClone,
|
||||
{
|
||||
fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
|
||||
let slice = iterator.as_slice();
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#![feature(slice_range)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(temporary_niche_types)]
|
||||
#![feature(trivial_clone)]
|
||||
#![feature(trusted_fused)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(trusted_random_access)]
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
#![stable(feature = "core_array", since = "1.35.0")]
|
||||
|
||||
use crate::borrow::{Borrow, BorrowMut};
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::cmp::Ordering;
|
||||
use crate::convert::Infallible;
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::hash::{self, Hash};
|
||||
use crate::intrinsics::transmute_unchecked;
|
||||
use crate::iter::{UncheckedIterator, repeat_n};
|
||||
|
|
@ -18,6 +18,7 @@ use crate::ops::{
|
|||
};
|
||||
use crate::ptr::{null, null_mut};
|
||||
use crate::slice::{Iter, IterMut};
|
||||
use crate::{fmt, ptr};
|
||||
|
||||
mod ascii;
|
||||
mod drain;
|
||||
|
|
@ -451,6 +452,9 @@ impl<T: Clone, const N: usize> Clone for [T; N] {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T: TrivialClone, const N: usize> TrivialClone for [T; N] {}
|
||||
|
||||
trait SpecArrayClone: Clone {
|
||||
fn clone<const N: usize>(array: &[Self; N]) -> [Self; N];
|
||||
}
|
||||
|
|
@ -462,10 +466,12 @@ impl<T: Clone> SpecArrayClone for T {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> SpecArrayClone for T {
|
||||
impl<T: TrivialClone> SpecArrayClone for T {
|
||||
#[inline]
|
||||
fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
|
||||
*array
|
||||
// SAFETY: `TrivialClone` implies that this is equivalent to calling
|
||||
// `Clone` on every element.
|
||||
unsafe { ptr::read(array) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -250,6 +250,33 @@ pub const trait Clone: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
/// Indicates that the `Clone` implementation is identical to copying the value.
|
||||
///
|
||||
/// This is used for some optimizations in the standard library, which specializes
|
||||
/// on this trait to select faster implementations of functions such as
|
||||
/// [`clone_from_slice`](slice::clone_from_slice). It is automatically implemented
|
||||
/// when using `#[derive(Clone, Copy)]`.
|
||||
///
|
||||
/// Note that this trait does not imply that the type is `Copy`, because e.g.
|
||||
/// `core::ops::Range<i32>` could soundly implement this trait.
|
||||
///
|
||||
/// # Safety
|
||||
/// `Clone::clone` must be equivalent to copying the value, otherwise calling functions
|
||||
/// such as `slice::clone_from_slice` can have undefined behaviour.
|
||||
#[unstable(
|
||||
feature = "trivial_clone",
|
||||
reason = "this isn't part of any API guarantee",
|
||||
issue = "none"
|
||||
)]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
// SAFETY:
|
||||
// It is sound to specialize on this because the `clone` implementation cannot be
|
||||
// lifetime-dependent. Therefore, if `TrivialClone` is implemented for any lifetime,
|
||||
// its invariant holds whenever `Clone` is implemented, even if the actual
|
||||
// `TrivialClone` bound would not be satisfied because of lifetime bounds.
|
||||
#[rustc_unsafe_specialization_marker]
|
||||
pub const unsafe trait TrivialClone: [const] Clone {}
|
||||
|
||||
/// Derive macro generating an impl of the trait `Clone`.
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
|
|
@ -569,6 +596,7 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr {
|
|||
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||
/// in `rustc_trait_selection`.
|
||||
mod impls {
|
||||
use super::TrivialClone;
|
||||
use crate::marker::PointeeSized;
|
||||
|
||||
macro_rules! impl_clone {
|
||||
|
|
@ -582,6 +610,10 @@ mod impls {
|
|||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
unsafe impl const TrivialClone for $t {}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
|
@ -602,6 +634,10 @@ mod impls {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
unsafe impl const TrivialClone for ! {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl<T: PointeeSized> const Clone for *const T {
|
||||
|
|
@ -611,6 +647,10 @@ mod impls {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
unsafe impl<T: PointeeSized> const TrivialClone for *const T {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl<T: PointeeSized> const Clone for *mut T {
|
||||
|
|
@ -620,6 +660,10 @@ mod impls {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
unsafe impl<T: PointeeSized> const TrivialClone for *mut T {}
|
||||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
|
|
@ -631,6 +675,10 @@ mod impls {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
unsafe impl<T: PointeeSized> const TrivialClone for &T {}
|
||||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: PointeeSized> !Clone for &mut T {}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use super::TrivialClone;
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
use crate::ptr;
|
||||
|
||||
|
|
@ -49,9 +50,9 @@ unsafe impl<T: Clone> CopySpec for T {
|
|||
}
|
||||
}
|
||||
|
||||
// Specialized implementation for types that are [`Copy`], not just [`Clone`],
|
||||
// Specialized implementation for types that are [`TrivialClone`], not just [`Clone`],
|
||||
// and can therefore be copied bitwise.
|
||||
unsafe impl<T: Copy> CopySpec for T {
|
||||
unsafe impl<T: TrivialClone> CopySpec for T {
|
||||
#[inline]
|
||||
unsafe fn clone_one(src: &Self, dst: *mut Self) {
|
||||
// SAFETY: The safety conditions of clone_to_uninit() are a superset of those of
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ pub use self::variance::{
|
|||
PhantomInvariant, PhantomInvariantLifetime, Variance, variance,
|
||||
};
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::cmp;
|
||||
use crate::fmt::Debug;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
|
|
@ -454,12 +455,8 @@ marker_impls! {
|
|||
/// [impls]: #implementors
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "copy"]
|
||||
// FIXME(matthewjasper) This allows copying a type that doesn't implement
|
||||
// `Copy` because of unsatisfied lifetime bounds (copying `A<'_>` when only
|
||||
// `A<'static>: Copy` and `A<'_>: Clone`).
|
||||
// We have this attribute here for now only because there are quite a few
|
||||
// existing specializations on `Copy` that already exist in the standard
|
||||
// library, and there's no way to safely have this behavior right now.
|
||||
// This is unsound, but required by `hashbrown`
|
||||
// FIXME(joboet): change `hashbrown` to use `TrivialClone`
|
||||
#[rustc_unsafe_specialization_marker]
|
||||
#[rustc_diagnostic_item = "Copy"]
|
||||
pub trait Copy: Clone {
|
||||
|
|
@ -861,6 +858,9 @@ impl<T: PointeeSized> Clone for PhantomData<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T: ?Sized> TrivialClone for PhantomData<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
|
||||
impl<T: PointeeSized> const Default for PhantomData<T> {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use super::PhantomData;
|
||||
use crate::any::type_name;
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
|
|
@ -60,6 +61,8 @@ macro_rules! phantom_type {
|
|||
|
||||
impl<T> Copy for $name<T> where T: ?Sized {}
|
||||
|
||||
unsafe impl<T> TrivialClone for $name<T> where T: ?Sized {}
|
||||
|
||||
impl<T> PartialEq for $name<T>
|
||||
where T: ?Sized
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::any::type_name;
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::marker::Destruct;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::{fmt, intrinsics, ptr, slice};
|
||||
|
|
@ -356,6 +357,10 @@ impl<T: Copy> Clone for MaybeUninit<T> {
|
|||
}
|
||||
}
|
||||
|
||||
// SAFETY: the clone implementation is a copy, see above.
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T> TrivialClone for MaybeUninit<T> where MaybeUninit<T>: Clone {}
|
||||
|
||||
#[stable(feature = "maybe_uninit_debug", since = "1.41.0")]
|
||||
impl<T> fmt::Debug for MaybeUninit<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
@ -1599,8 +1604,12 @@ impl<T: Clone> SpecFill<T> for [MaybeUninit<T>] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> SpecFill<T> for [MaybeUninit<T>] {
|
||||
impl<T: TrivialClone> SpecFill<T> for [MaybeUninit<T>] {
|
||||
fn spec_fill(&mut self, value: T) {
|
||||
self.fill(MaybeUninit::new(value));
|
||||
// SAFETY: because `T` is `TrivialClone`, this is equivalent to calling
|
||||
// `T::clone` for every element. Notably, `TrivialClone` also implies
|
||||
// that the `clone` implementation will not panic, so we can avoid
|
||||
// initialization guards and such.
|
||||
self.fill_with(|| MaybeUninit::new(unsafe { ptr::read(&value) }));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::alloc::Layout;
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::marker::{Destruct, DiscriminantKind};
|
||||
use crate::panic::const_assert;
|
||||
use crate::{clone, cmp, fmt, hash, intrinsics, ptr};
|
||||
|
|
@ -1070,6 +1071,9 @@ impl<T> clone::Clone for Discriminant<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T> TrivialClone for Discriminant<T> {}
|
||||
|
||||
#[stable(feature = "discriminant_value", since = "1.21.0")]
|
||||
impl<T> cmp::PartialEq for Discriminant<T> {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! Definitions of integer that is known not to equal zero.
|
||||
|
||||
use super::{IntErrorKind, ParseIntError};
|
||||
use crate::clone::UseCloned;
|
||||
use crate::clone::{TrivialClone, UseCloned};
|
||||
use crate::cmp::Ordering;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::marker::{Destruct, Freeze, StructuralPartialEq};
|
||||
|
|
@ -199,6 +199,9 @@ impl<T> UseCloned for NonZero<T> where T: ZeroablePrimitive {}
|
|||
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||
impl<T> Copy for NonZero<T> where T: ZeroablePrimitive {}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T> TrivialClone for NonZero<T> where T: ZeroablePrimitive {}
|
||||
|
||||
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
|
||||
impl<T> const PartialEq for NonZero<T>
|
||||
|
|
|
|||
|
|
@ -581,6 +581,7 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::iter::{self, FusedIterator, TrustedLen};
|
||||
use crate::marker::Destruct;
|
||||
use crate::ops::{self, ControlFlow, Deref, DerefMut};
|
||||
|
|
@ -2215,6 +2216,10 @@ where
|
|||
#[unstable(feature = "ergonomic_clones", issue = "132290")]
|
||||
impl<T> crate::clone::UseCloned for Option<T> where T: crate::clone::UseCloned {}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
unsafe impl<T> const TrivialClone for Option<T> where T: [const] TrivialClone + [const] Destruct {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
|
||||
impl<T> const Default for Option<T> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata};
|
||||
|
|
@ -231,6 +232,8 @@ impl<Dyn: PointeeSized> Clone for DynMetadata<Dyn> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<Dyn: ?Sized> TrivialClone for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: PointeeSized> Eq for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: PointeeSized> PartialEq for DynMetadata<Dyn> {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::clone::TrivialClone;
|
||||
use crate::cmp::Ordering;
|
||||
use crate::marker::{Destruct, PointeeSized, Unsize};
|
||||
use crate::mem::{MaybeUninit, SizedTypeProperties};
|
||||
|
|
@ -1653,6 +1654,9 @@ impl<T: PointeeSized> Clone for NonNull<T> {
|
|||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: PointeeSized> Copy for NonNull<T> {}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T: ?Sized> TrivialClone for NonNull<T> {}
|
||||
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::clone::TrivialClone;
|
||||
use crate::fmt;
|
||||
use crate::marker::{PhantomData, PointeeSized, Unsize};
|
||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||
|
|
@ -165,6 +166,9 @@ impl<T: PointeeSized> Clone for Unique<T> {
|
|||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: PointeeSized> Copy for Unique<T> {}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T: ?Sized> TrivialClone for Unique<T> {}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::clone::TrivialClone;
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use crate::intrinsics::{exact_div, unchecked_sub};
|
||||
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
|
||||
|
|
@ -3890,30 +3891,8 @@ impl<T> [T] {
|
|||
where
|
||||
T: Copy,
|
||||
{
|
||||
// The panic code path was put into a cold function to not bloat the
|
||||
// call site.
|
||||
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate-abort", inline)]
|
||||
#[track_caller]
|
||||
const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
|
||||
const_panic!(
|
||||
"copy_from_slice: source slice length does not match destination slice length",
|
||||
"copy_from_slice: source slice length ({src_len}) does not match destination slice length ({dst_len})",
|
||||
src_len: usize,
|
||||
dst_len: usize,
|
||||
)
|
||||
}
|
||||
|
||||
if self.len() != src.len() {
|
||||
len_mismatch_fail(self.len(), src.len());
|
||||
}
|
||||
|
||||
// SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was
|
||||
// checked to have the same length. The slices cannot overlap because
|
||||
// mutable references are exclusive.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
|
||||
}
|
||||
// SAFETY: `T` implements `Copy`.
|
||||
unsafe { copy_from_slice_impl(self, src) }
|
||||
}
|
||||
|
||||
/// Copies elements from one part of the slice to another part of itself,
|
||||
|
|
@ -5123,6 +5102,38 @@ impl [f64] {
|
|||
}
|
||||
}
|
||||
|
||||
/// Copies `src` to `dest`.
|
||||
///
|
||||
/// # Safety
|
||||
/// `T` must implement one of `Copy` or `TrivialClone`.
|
||||
#[track_caller]
|
||||
const unsafe fn copy_from_slice_impl<T: Clone>(dest: &mut [T], src: &[T]) {
|
||||
// The panic code path was put into a cold function to not bloat the
|
||||
// call site.
|
||||
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate-abort", inline)]
|
||||
#[track_caller]
|
||||
const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
|
||||
const_panic!(
|
||||
"copy_from_slice: source slice length does not match destination slice length",
|
||||
"copy_from_slice: source slice length ({src_len}) does not match destination slice length ({dst_len})",
|
||||
src_len: usize,
|
||||
dst_len: usize,
|
||||
)
|
||||
}
|
||||
|
||||
if dest.len() != src.len() {
|
||||
len_mismatch_fail(dest.len(), src.len());
|
||||
}
|
||||
|
||||
// SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was
|
||||
// checked to have the same length. The slices cannot overlap because
|
||||
// mutable references are exclusive.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(src.as_ptr(), dest.as_mut_ptr(), dest.len());
|
||||
}
|
||||
}
|
||||
|
||||
trait CloneFromSpec<T> {
|
||||
fn spec_clone_from(&mut self, src: &[T]);
|
||||
}
|
||||
|
|
@ -5147,11 +5158,14 @@ where
|
|||
|
||||
impl<T> CloneFromSpec<T> for [T]
|
||||
where
|
||||
T: Copy,
|
||||
T: TrivialClone,
|
||||
{
|
||||
#[track_caller]
|
||||
fn spec_clone_from(&mut self, src: &[T]) {
|
||||
self.copy_from_slice(src);
|
||||
// SAFETY: `T` implements `TrivialClone`.
|
||||
unsafe {
|
||||
copy_from_slice_impl(self, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
use crate::clone::TrivialClone;
|
||||
use crate::ptr;
|
||||
|
||||
pub(super) trait SpecFill<T> {
|
||||
fn spec_fill(&mut self, value: T);
|
||||
}
|
||||
|
|
@ -14,10 +17,12 @@ impl<T: Clone> SpecFill<T> for [T] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> SpecFill<T> for [T] {
|
||||
impl<T: TrivialClone> SpecFill<T> for [T] {
|
||||
default fn spec_fill(&mut self, value: T) {
|
||||
for item in self.iter_mut() {
|
||||
*item = value;
|
||||
// SAFETY: `TrivialClone` indicates that this is equivalent to
|
||||
// calling `Clone::clone`
|
||||
*item = unsafe { ptr::read(&value) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//! Defines [`Exclusive`].
|
||||
|
||||
use core::clone::TrivialClone;
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::future::Future;
|
||||
|
|
@ -261,6 +262,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trivial_clone", issue = "none")]
|
||||
unsafe impl<T> TrivialClone for Exclusive<T> where T: Sync + TrivialClone {}
|
||||
|
||||
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||
impl<T> Copy for Exclusive<T> where T: Sync + Copy {}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue