Auto merge of #48171 - FraGag:doc-copy-clone-impls, r=nikomatsakis

Better document the implementors of Clone and Copy

There are two parts to this change. The first part is a change to the compiler and to the standard library (specifically, libcore) to allow implementations of `Clone` and `Copy` to be written for a subset of builtin types. By adding these implementations to libcore, they now show up in the documentation. This is a [breaking-change] for users of `#![no_core]`, because they will now have to supply their own copy of the implementations of `Clone` and `Copy` that were added in libcore.

The second part is purely a documentation change to document the other implementors of `Clone` and `Copy` that cannot be described in Rust code (yet) and are thus provided by the compiler.

Fixes #25893
This commit is contained in:
bors 2018-04-04 18:11:51 +00:00
commit fb44b4c0eb
13 changed files with 223 additions and 44 deletions

View File

@ -63,11 +63,6 @@
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d /// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of [`clone`] calls [`clone`] on each field. /// implementation of [`clone`] calls [`clone`] on each field.
/// ///
/// ## Closures
///
/// Closure types automatically implement `Clone` if they capture no value from the environment
/// or if all such captured values implement `Clone` themselves.
///
/// ## How can I implement `Clone`? /// ## How can I implement `Clone`?
/// ///
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally: /// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
@ -92,6 +87,23 @@
/// fn clone(&self) -> Stats { *self } /// fn clone(&self) -> Stats { *self }
/// } /// }
/// ``` /// ```
///
/// ## Additional implementors
///
/// In addition to the [implementors listed below][impls],
/// the following types also implement `Clone`:
///
/// * Function item types (i.e. the distinct types defined for each function)
/// * Function pointer types (e.g. `fn() -> i32`)
/// * Array types, for all sizes, if the item type also implements `Clone` (e.g. `[i32; 123456]`)
/// * Tuple types, if each component also implements `Clone` (e.g. `()`, `(i32, bool)`)
/// * Closure types, if they capture no value from the environment
/// or if all such captured values implement `Clone` themselves.
/// Note that variables captured by shared reference always implement `Clone`
/// (even if the referent doesn't),
/// while variables captured by mutable reference never implement `Clone`.
///
/// [impls]: #implementors
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[lang = "clone"] #[lang = "clone"]
pub trait Clone : Sized { pub trait Clone : Sized {
@ -135,3 +147,68 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData
reason = "deriving hack, should not be public", reason = "deriving hack, should not be public",
issue = "0")] issue = "0")]
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> } pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
/// 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 {
#[inline]
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 ! {
#[inline]
fn clone(&self) -> Self {
*self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for *const T {
#[inline]
fn clone(&self) -> Self {
*self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for *mut T {
#[inline]
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 {
#[inline]
fn clone(&self) -> Self {
*self
}
}
}

View File

@ -166,11 +166,6 @@ pub trait Unsize<T: ?Sized> {
/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move /// are allowed to access `x` after the assignment. Under the hood, both a copy and a move
/// can result in bits being copied in memory, although this is sometimes optimized away. /// can result in bits being copied in memory, although this is sometimes optimized away.
/// ///
/// ## Closures
///
/// Closure types automatically implement `Copy` if they capture no value from the environment
/// or if all such captured values implement `Copy` themselves.
///
/// ## How can I implement `Copy`? /// ## How can I implement `Copy`?
/// ///
/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`: /// There are two ways to implement `Copy` on your type. The simplest is to use `derive`:
@ -265,6 +260,21 @@ pub trait Unsize<T: ?Sized> {
/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to /// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to
/// avoid a breaking API change. /// avoid a breaking API change.
/// ///
/// ## Additional implementors
///
/// In addition to the [implementors listed below][impls],
/// the following types also implement `Copy`:
///
/// * Function item types (i.e. the distinct types defined for each function)
/// * Function pointer types (e.g. `fn() -> i32`)
/// * Array types, for all sizes, if the item type also implements `Copy` (e.g. `[i32; 123456]`)
/// * Tuple types, if each component also implements `Copy` (e.g. `()`, `(i32, bool)`)
/// * Closure types, if they capture no value from the environment
/// or if all such captured values implement `Copy` themselves.
/// Note that variables captured by shared reference always implement `Copy`
/// (even if the referent doesn't),
/// while variables captured by mutable reference never implement `Copy`.
///
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
/// [`String`]: ../../std/string/struct.String.html /// [`String`]: ../../std/string/struct.String.html
/// [`Drop`]: ../../std/ops/trait.Drop.html /// [`Drop`]: ../../std/ops/trait.Drop.html
@ -272,6 +282,7 @@ pub trait Unsize<T: ?Sized> {
/// [`Clone`]: ../clone/trait.Clone.html /// [`Clone`]: ../clone/trait.Clone.html
/// [`String`]: ../../std/string/struct.String.html /// [`String`]: ../../std/string/struct.String.html
/// [`i32`]: ../../std/primitive.i32.html /// [`i32`]: ../../std/primitive.i32.html
/// [impls]: #implementors
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[lang = "copy"] #[lang = "copy"]
pub trait Copy : Clone { pub trait Copy : Clone {
@ -593,3 +604,43 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
/// This trait is automatically implemented for almost every type. /// This trait is automatically implemented for almost every type.
#[unstable(feature = "pin", issue = "49150")] #[unstable(feature = "pin", issue = "49150")]
pub unsafe auto trait Unpin {} 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<T: ?Sized> Copy for *const T {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> 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 {}
}

@ -1 +1 @@
Subproject commit ed04152aacf5b4798f78ff13396f3c04c0a77144 Subproject commit a7e78a78e17c8776d7780008ccb3ce541ec64ae9

View File

@ -2061,13 +2061,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
match self_ty.sty { match self_ty.sty {
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => {
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
ty::TyRawPtr(..) | ty::TyError | ty::TyNever |
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
Where(ty::Binder(Vec::new())) 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::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) | ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) |
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {

View File

@ -197,7 +197,14 @@ impl<'tcx> ty::ParamEnv<'tcx> {
// FIXME: (@jroesch) float this code up // FIXME: (@jroesch) float this code up
tcx.infer_ctxt().enter(|infcx| { tcx.infer_ctxt().enter(|infcx| {
let (adt, substs) = match self_type.sty { 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), ty::TyAdt(adt, substs) => (adt, substs),
_ => return Err(CopyImplementationError::NotAnAdt), _ => return Err(CopyImplementationError::NotAnAdt),
}; };

View File

@ -1908,16 +1908,16 @@ differs from the behavior for `&T`, which is always `Copy`).
E0206: r##" E0206: r##"
You can only implement `Copy` for a struct or enum. Both of the following 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` examples will fail, because neither `[u8; 256]` nor `&'static mut Bar`
(reference to `Bar`) is a struct or enum: (mutable reference to `Bar`) is a struct or enum:
```compile_fail,E0206 ```compile_fail,E0206
type Foo = i32; type Foo = [u8; 256];
impl Copy for Foo { } // error impl Copy for Foo { } // error
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct Bar; struct Bar;
impl Copy for &'static Bar { } // error impl Copy for &'static mut Bar { } // error
``` ```
"##, "##,

View File

@ -15,9 +15,14 @@
use std::iter; use std::iter;
// CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
#[no_mangle]
pub fn helper(_: usize) {
}
// CHECK-LABEL: @repeat_take_collect // CHECK-LABEL: @repeat_take_collect
#[no_mangle] #[no_mangle]
pub fn repeat_take_collect() -> Vec<u8> { pub fn repeat_take_collect() -> Vec<u8> {
// CHECK: call void @llvm.memset.p0i8 // CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}%{{[0-9]+}}, i8 42, [[USIZE]] 100000, i32 1, i1 false)
iter::repeat(42).take(100000).collect() iter::repeat(42).take(100000).collect()
} }

View File

@ -23,6 +23,8 @@ trait Copy {}
#[lang = "freeze"] #[lang = "freeze"]
trait Freeze {} trait Freeze {}
impl<T: ?Sized> Copy for *mut T {}
#[cfg(target_has_atomic = "8")] #[cfg(target_has_atomic = "8")]
pub unsafe fn atomic_u8(x: *mut u8) { pub unsafe fn atomic_u8(x: *mut u8) {
atomic_xadd(x, 1); atomic_xadd(x, 1);

View File

@ -75,6 +75,9 @@ pub trait Sized { }
#[lang = "copy"] #[lang = "copy"]
pub trait Copy { } pub trait Copy { }
impl Copy for f32 {}
impl Copy for i32 {}
pub mod marker { pub mod marker {
pub use Copy; pub use Copy;
} }

View File

@ -12,6 +12,10 @@
use std::marker::Copy; 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 { enum TestE {
A A
} }
@ -35,14 +39,14 @@ impl Copy for (MyType, MyType) {}
//~| ERROR only traits defined in the current crate can be implemented for arbitrary types //~| ERROR only traits defined in the current crate can be implemented for arbitrary types
impl Copy for &'static NotSync {} 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] {} impl Copy for [MyType] {}
//~^ ERROR the trait `Copy` may not be implemented for this type //~^ 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 //~| ERROR only traits defined in the current crate can be implemented for arbitrary types
impl Copy for &'static [NotSync] {} 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 //~| ERROR only traits defined in the current crate can be implemented for arbitrary types
fn main() { fn main() {

View File

@ -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 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 {} LL | impl Copy for &'static mut MyType {}
| ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
error[E0206]: the trait `Copy` may not be implemented for this type 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) {} LL | impl Copy for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
error[E0206]: the trait `Copy` may not be implemented for this type error[E0206]: the trait `Copy` may not be implemented for this type
--> $DIR/coherence-impls-copy.rs:37:15 --> $DIR/coherence-impls-copy.rs:44: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
| |
LL | impl Copy for [MyType] {} LL | impl Copy for [MyType] {}
| ^^^^^^^^ type is not a structure or enumeration | ^^^^^^^^ type is not a structure or enumeration
error[E0206]: the trait `Copy` may not be implemented for this type error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/coherence-impls-copy.rs:44:15 --> $DIR/coherence-impls-copy.rs:15:1
| |
LL | impl Copy for &'static [NotSync] {} LL | impl Copy for i32 {}
| ^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration | ^^^^^^^^^^^^^^^^^ 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 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) {} LL | impl Copy for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 = 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 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] {} LL | impl Copy for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | ^^^^^^^^^^^^^^^^^^^^^^ 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 = 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 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] {} LL | impl Copy for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead = 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`. For more information about an error, try `rustc --explain E0117`.

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
type Foo = i32; type Foo = [u8; 256];
impl Copy for Foo { } impl Copy for Foo { }
//~^ ERROR the trait `Copy` may not be implemented for this type //~^ ERROR the trait `Copy` may not be implemented for this type
@ -17,7 +17,7 @@ impl Copy for Foo { }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct Bar; struct Bar;
impl Copy for &'static Bar { } impl Copy for &'static mut Bar { }
//~^ ERROR the trait `Copy` may not be implemented for this type //~^ ERROR the trait `Copy` may not be implemented for this type
fn main() { fn main() {

View File

@ -7,8 +7,8 @@ LL | impl Copy for Foo { }
error[E0206]: the trait `Copy` may not be implemented for this type error[E0206]: the trait `Copy` may not be implemented for this type
--> $DIR/E0206.rs:20:15 --> $DIR/E0206.rs:20:15
| |
LL | impl Copy for &'static Bar { } LL | impl Copy for &'static mut Bar { }
| ^^^^^^^^^^^^ type is not a structure or enumeration | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/E0206.rs:13:1 --> $DIR/E0206.rs:13:1