diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index d25f498b99ef..5c83dd79bd7f 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -135,3 +135,63 @@ pub struct AssertParamIsClone { _field: ::marker::PhantomData reason = "deriving hack, should not be public", issue = "0")] pub struct AssertParamIsCopy { _field: ::marker::PhantomData } + +/// Implementations of `Clone` for primitive types. +/// +/// Implementations that cannot be described in Rust +/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc. +#[cfg(not(stage0))] +mod impls { + + use super::Clone; + + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for $t { + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 u128 + isize i8 i16 i32 i64 i128 + f32 f64 + bool char + } + + #[stable(feature = "never_type", since = "1.26.0")] + impl Clone for ! { + fn clone(&self) -> Self { + *self + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for *const T { + fn clone(&self) -> Self { + *self + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for *mut T { + fn clone(&self) -> Self { + *self + } + } + + // Shared references can be cloned, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T: ?Sized> Clone for &'a T { + fn clone(&self) -> Self { + *self + } + } + +} diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 7d0174a178ab..008cb15131d8 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -593,3 +593,43 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// This trait is automatically implemented for almost every type. #[unstable(feature = "pin", issue = "49150")] pub unsafe auto trait Unpin {} + +/// Implementations of `Copy` for primitive types. +/// +/// Implementations that cannot be described in Rust +/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc. +#[cfg(not(stage0))] +mod copy_impls { + + use super::Copy; + + macro_rules! impl_copy { + ($($t:ty)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Copy for $t {} + )* + } + } + + impl_copy! { + usize u8 u16 u32 u64 u128 + isize i8 i16 i32 i64 i128 + f32 f64 + bool char + } + + #[stable(feature = "never_type", since = "1.26.0")] + impl Copy for ! {} + + #[stable(feature = "rust1", since = "1.0.0")] + impl Copy for *const T {} + + #[stable(feature = "rust1", since = "1.0.0")] + impl Copy for *mut T {} + + // Shared references can be copied, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T: ?Sized> Copy for &'a T {} + +} diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 11daa96134c5..8a585d6ac146 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2061,13 +2061,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | - ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | - ty::TyRawPtr(..) | ty::TyError | ty::TyNever | - ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => { Where(ty::Binder(Vec::new())) } + ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | + ty::TyChar | ty::TyRawPtr(..) | ty::TyNever | + ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + // Implementations provided in libcore + None + } + ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) | ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index afe977d10baa..22f851a908b2 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -197,7 +197,14 @@ impl<'tcx> ty::ParamEnv<'tcx> { // FIXME: (@jroesch) float this code up tcx.infer_ctxt().enter(|infcx| { let (adt, substs) = match self_type.sty { + // These types used to have a builtin impl. + // Now libcore provides that impl. + ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | + ty::TyChar | ty::TyRawPtr(..) | ty::TyNever | + ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => return Ok(()), + ty::TyAdt(adt, substs) => (adt, substs), + _ => return Err(CopyImplementationError::NotAnAdt), }; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 1f882676f61a..691e0ffb6a5d 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1918,16 +1918,16 @@ differs from the behavior for `&T`, which is always `Copy`). E0206: r##" You can only implement `Copy` for a struct or enum. Both of the following -examples will fail, because neither `i32` (primitive type) nor `&'static Bar` -(reference to `Bar`) is a struct or enum: +examples will fail, because neither `[u8; 256]` nor `&'static mut Bar` +(mutable reference to `Bar`) is a struct or enum: ```compile_fail,E0206 -type Foo = i32; +type Foo = [u8; 256]; impl Copy for Foo { } // error #[derive(Copy, Clone)] struct Bar; -impl Copy for &'static Bar { } // error +impl Copy for &'static mut Bar { } // error ``` "##, diff --git a/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs index b41e8e9226b3..54f888b3796a 100644 --- a/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs +++ b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs @@ -23,6 +23,8 @@ trait Copy {} #[lang = "freeze"] trait Freeze {} +impl Copy for *mut T {} + #[cfg(target_has_atomic = "8")] pub unsafe fn atomic_u8(x: *mut u8) { atomic_xadd(x, 1); diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs index 94b91c711cce..21411a35e3c3 100644 --- a/src/test/run-make-fulldeps/simd-ffi/simd.rs +++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs @@ -75,6 +75,9 @@ pub trait Sized { } #[lang = "copy"] pub trait Copy { } +impl Copy for f32 {} +impl Copy for i32 {} + pub mod marker { pub use Copy; } diff --git a/src/test/ui/coherence-impls-copy.rs b/src/test/ui/coherence-impls-copy.rs index 51f43d27c34d..f48790d1f403 100644 --- a/src/test/ui/coherence-impls-copy.rs +++ b/src/test/ui/coherence-impls-copy.rs @@ -12,6 +12,10 @@ use std::marker::Copy; +impl Copy for i32 {} +//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `i32`: +//~| ERROR only traits defined in the current crate can be implemented for arbitrary types + enum TestE { A } @@ -35,14 +39,14 @@ impl Copy for (MyType, MyType) {} //~| ERROR only traits defined in the current crate can be implemented for arbitrary types impl Copy for &'static NotSync {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&NotSync`: impl Copy for [MyType] {} //~^ ERROR the trait `Copy` may not be implemented for this type //~| ERROR only traits defined in the current crate can be implemented for arbitrary types impl Copy for &'static [NotSync] {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`: //~| ERROR only traits defined in the current crate can be implemented for arbitrary types fn main() { diff --git a/src/test/ui/coherence-impls-copy.stderr b/src/test/ui/coherence-impls-copy.stderr index 5f9b0c62df2b..24e7e85b1a96 100644 --- a/src/test/ui/coherence-impls-copy.stderr +++ b/src/test/ui/coherence-impls-copy.stderr @@ -1,35 +1,61 @@ +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`: + --> $DIR/coherence-impls-copy.rs:15:1 + | +LL | impl Copy for i32 {} + | ^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl std::marker::Copy for i32; + +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`: + --> $DIR/coherence-impls-copy.rs:41:1 + | +LL | impl Copy for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<'a, T> std::marker::Copy for &'a T + where T: ?Sized; + +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`: + --> $DIR/coherence-impls-copy.rs:48:1 + | +LL | impl Copy for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<'a, T> std::marker::Copy for &'a T + where T: ?Sized; + error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:29:15 + --> $DIR/coherence-impls-copy.rs:33:15 | LL | impl Copy for &'static mut MyType {} | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:33:15 + --> $DIR/coherence-impls-copy.rs:37:15 | LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:37:15 - | -LL | impl Copy for &'static NotSync {} - | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration - -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:40:15 + --> $DIR/coherence-impls-copy.rs:44:15 | LL | impl Copy for [MyType] {} | ^^^^^^^^ type is not a structure or enumeration -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:44:15 +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-copy.rs:15:1 | -LL | impl Copy for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration +LL | impl Copy for i32 {} + | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:33:1 + --> $DIR/coherence-impls-copy.rs:37:1 | LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate @@ -38,7 +64,7 @@ LL | impl Copy for (MyType, MyType) {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:40:1 + --> $DIR/coherence-impls-copy.rs:44:1 | LL | impl Copy for [MyType] {} | ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate @@ -47,7 +73,7 @@ LL | impl Copy for [MyType] {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:44:1 + --> $DIR/coherence-impls-copy.rs:48:1 | LL | impl Copy for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate @@ -55,7 +81,7 @@ LL | impl Copy for &'static [NotSync] {} = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors -Some errors occurred: E0117, E0206. +Some errors occurred: E0117, E0119, E0206. For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/error-codes/E0206.rs b/src/test/ui/error-codes/E0206.rs index da0370b301b5..9b3d1b351ddd 100644 --- a/src/test/ui/error-codes/E0206.rs +++ b/src/test/ui/error-codes/E0206.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type Foo = i32; +type Foo = [u8; 256]; impl Copy for Foo { } //~^ ERROR the trait `Copy` may not be implemented for this type @@ -17,7 +17,7 @@ impl Copy for Foo { } #[derive(Copy, Clone)] struct Bar; -impl Copy for &'static Bar { } +impl Copy for &'static mut Bar { } //~^ ERROR the trait `Copy` may not be implemented for this type fn main() { diff --git a/src/test/ui/error-codes/E0206.stderr b/src/test/ui/error-codes/E0206.stderr index bbc0da2248f6..f2c23b0767af 100644 --- a/src/test/ui/error-codes/E0206.stderr +++ b/src/test/ui/error-codes/E0206.stderr @@ -7,8 +7,8 @@ LL | impl Copy for Foo { } error[E0206]: the trait `Copy` may not be implemented for this type --> $DIR/E0206.rs:20:15 | -LL | impl Copy for &'static Bar { } - | ^^^^^^^^^^^^ type is not a structure or enumeration +LL | impl Copy for &'static mut Bar { } + | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/E0206.rs:13:1