Skip to content

Commit fb44b4c

Browse files
committed
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
2 parents 17fea66 + 87c08f9 commit fb44b4c

File tree

13 files changed

+221
-42
lines changed

13 files changed

+221
-42
lines changed

src/libcore/clone.rs

+82-5
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,6 @@
6363
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
6464
/// implementation of [`clone`] calls [`clone`] on each field.
6565
///
66-
/// ## Closures
67-
///
68-
/// Closure types automatically implement `Clone` if they capture no value from the environment
69-
/// or if all such captured values implement `Clone` themselves.
70-
///
7166
/// ## How can I implement `Clone`?
7267
///
7368
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
@@ -92,6 +87,23 @@
9287
/// fn clone(&self) -> Stats { *self }
9388
/// }
9489
/// ```
90+
///
91+
/// ## Additional implementors
92+
///
93+
/// In addition to the [implementors listed below][impls],
94+
/// the following types also implement `Clone`:
95+
///
96+
/// * Function item types (i.e. the distinct types defined for each function)
97+
/// * Function pointer types (e.g. `fn() -> i32`)
98+
/// * Array types, for all sizes, if the item type also implements `Clone` (e.g. `[i32; 123456]`)
99+
/// * Tuple types, if each component also implements `Clone` (e.g. `()`, `(i32, bool)`)
100+
/// * Closure types, if they capture no value from the environment
101+
/// or if all such captured values implement `Clone` themselves.
102+
/// Note that variables captured by shared reference always implement `Clone`
103+
/// (even if the referent doesn't),
104+
/// while variables captured by mutable reference never implement `Clone`.
105+
///
106+
/// [impls]: #implementors
95107
#[stable(feature = "rust1", since = "1.0.0")]
96108
#[lang = "clone"]
97109
pub trait Clone : Sized {
@@ -135,3 +147,68 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData
135147
reason = "deriving hack, should not be public",
136148
issue = "0")]
137149
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
150+
151+
/// Implementations of `Clone` for primitive types.
152+
///
153+
/// Implementations that cannot be described in Rust
154+
/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
155+
#[cfg(not(stage0))]
156+
mod impls {
157+
158+
use super::Clone;
159+
160+
macro_rules! impl_clone {
161+
($($t:ty)*) => {
162+
$(
163+
#[stable(feature = "rust1", since = "1.0.0")]
164+
impl Clone for $t {
165+
#[inline]
166+
fn clone(&self) -> Self {
167+
*self
168+
}
169+
}
170+
)*
171+
}
172+
}
173+
174+
impl_clone! {
175+
usize u8 u16 u32 u64 u128
176+
isize i8 i16 i32 i64 i128
177+
f32 f64
178+
bool char
179+
}
180+
181+
#[stable(feature = "never_type", since = "1.26.0")]
182+
impl Clone for ! {
183+
#[inline]
184+
fn clone(&self) -> Self {
185+
*self
186+
}
187+
}
188+
189+
#[stable(feature = "rust1", since = "1.0.0")]
190+
impl<T: ?Sized> Clone for *const T {
191+
#[inline]
192+
fn clone(&self) -> Self {
193+
*self
194+
}
195+
}
196+
197+
#[stable(feature = "rust1", since = "1.0.0")]
198+
impl<T: ?Sized> Clone for *mut T {
199+
#[inline]
200+
fn clone(&self) -> Self {
201+
*self
202+
}
203+
}
204+
205+
// Shared references can be cloned, but mutable references *cannot*!
206+
#[stable(feature = "rust1", since = "1.0.0")]
207+
impl<'a, T: ?Sized> Clone for &'a T {
208+
#[inline]
209+
fn clone(&self) -> Self {
210+
*self
211+
}
212+
}
213+
214+
}

src/libcore/marker.rs

+56-5
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,6 @@ pub trait Unsize<T: ?Sized> {
166166
/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move
167167
/// can result in bits being copied in memory, although this is sometimes optimized away.
168168
///
169-
/// ## Closures
170-
///
171-
/// Closure types automatically implement `Copy` if they capture no value from the environment
172-
/// or if all such captured values implement `Copy` themselves.
173-
///
174169
/// ## How can I implement `Copy`?
175170
///
176171
/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`:
@@ -265,13 +260,29 @@ pub trait Unsize<T: ?Sized> {
265260
/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to
266261
/// avoid a breaking API change.
267262
///
263+
/// ## Additional implementors
264+
///
265+
/// In addition to the [implementors listed below][impls],
266+
/// the following types also implement `Copy`:
267+
///
268+
/// * Function item types (i.e. the distinct types defined for each function)
269+
/// * Function pointer types (e.g. `fn() -> i32`)
270+
/// * Array types, for all sizes, if the item type also implements `Copy` (e.g. `[i32; 123456]`)
271+
/// * Tuple types, if each component also implements `Copy` (e.g. `()`, `(i32, bool)`)
272+
/// * Closure types, if they capture no value from the environment
273+
/// or if all such captured values implement `Copy` themselves.
274+
/// Note that variables captured by shared reference always implement `Copy`
275+
/// (even if the referent doesn't),
276+
/// while variables captured by mutable reference never implement `Copy`.
277+
///
268278
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
269279
/// [`String`]: ../../std/string/struct.String.html
270280
/// [`Drop`]: ../../std/ops/trait.Drop.html
271281
/// [`size_of::<T>`]: ../../std/mem/fn.size_of.html
272282
/// [`Clone`]: ../clone/trait.Clone.html
273283
/// [`String`]: ../../std/string/struct.String.html
274284
/// [`i32`]: ../../std/primitive.i32.html
285+
/// [impls]: #implementors
275286
#[stable(feature = "rust1", since = "1.0.0")]
276287
#[lang = "copy"]
277288
pub trait Copy : Clone {
@@ -593,3 +604,43 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
593604
/// This trait is automatically implemented for almost every type.
594605
#[unstable(feature = "pin", issue = "49150")]
595606
pub unsafe auto trait Unpin {}
607+
608+
/// Implementations of `Copy` for primitive types.
609+
///
610+
/// Implementations that cannot be described in Rust
611+
/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
612+
#[cfg(not(stage0))]
613+
mod copy_impls {
614+
615+
use super::Copy;
616+
617+
macro_rules! impl_copy {
618+
($($t:ty)*) => {
619+
$(
620+
#[stable(feature = "rust1", since = "1.0.0")]
621+
impl Copy for $t {}
622+
)*
623+
}
624+
}
625+
626+
impl_copy! {
627+
usize u8 u16 u32 u64 u128
628+
isize i8 i16 i32 i64 i128
629+
f32 f64
630+
bool char
631+
}
632+
633+
#[stable(feature = "never_type", since = "1.26.0")]
634+
impl Copy for ! {}
635+
636+
#[stable(feature = "rust1", since = "1.0.0")]
637+
impl<T: ?Sized> Copy for *const T {}
638+
639+
#[stable(feature = "rust1", since = "1.0.0")]
640+
impl<T: ?Sized> Copy for *mut T {}
641+
642+
// Shared references can be copied, but mutable references *cannot*!
643+
#[stable(feature = "rust1", since = "1.0.0")]
644+
impl<'a, T: ?Sized> Copy for &'a T {}
645+
646+
}

src/librustc/traits/select.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -2061,11 +2061,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20612061

20622062
match self_ty.sty {
20632063
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
2064+
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => {
2065+
Where(ty::Binder(Vec::new()))
2066+
}
2067+
20642068
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
2065-
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
2066-
ty::TyRawPtr(..) | ty::TyError | ty::TyNever |
2069+
ty::TyChar | ty::TyRawPtr(..) | ty::TyNever |
20672070
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
2068-
Where(ty::Binder(Vec::new()))
2071+
// Implementations provided in libcore
2072+
None
20692073
}
20702074

20712075
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |

src/librustc/ty/util.rs

+7
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,14 @@ impl<'tcx> ty::ParamEnv<'tcx> {
197197
// FIXME: (@jroesch) float this code up
198198
tcx.infer_ctxt().enter(|infcx| {
199199
let (adt, substs) = match self_type.sty {
200+
// These types used to have a builtin impl.
201+
// Now libcore provides that impl.
202+
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
203+
ty::TyChar | ty::TyRawPtr(..) | ty::TyNever |
204+
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => return Ok(()),
205+
200206
ty::TyAdt(adt, substs) => (adt, substs),
207+
201208
_ => return Err(CopyImplementationError::NotAnAdt),
202209
};
203210

src/librustc_typeck/diagnostics.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1908,16 +1908,16 @@ differs from the behavior for `&T`, which is always `Copy`).
19081908

19091909
E0206: r##"
19101910
You can only implement `Copy` for a struct or enum. Both of the following
1911-
examples will fail, because neither `i32` (primitive type) nor `&'static Bar`
1912-
(reference to `Bar`) is a struct or enum:
1911+
examples will fail, because neither `[u8; 256]` nor `&'static mut Bar`
1912+
(mutable reference to `Bar`) is a struct or enum:
19131913
19141914
```compile_fail,E0206
1915-
type Foo = i32;
1915+
type Foo = [u8; 256];
19161916
impl Copy for Foo { } // error
19171917
19181918
#[derive(Copy, Clone)]
19191919
struct Bar;
1920-
impl Copy for &'static Bar { } // error
1920+
impl Copy for &'static mut Bar { } // error
19211921
```
19221922
"##,
19231923

src/test/codegen/repeat-trusted-len.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@
1515

1616
use std::iter;
1717

18+
// CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
19+
#[no_mangle]
20+
pub fn helper(_: usize) {
21+
}
22+
1823
// CHECK-LABEL: @repeat_take_collect
1924
#[no_mangle]
2025
pub fn repeat_take_collect() -> Vec<u8> {
21-
// CHECK: call void @llvm.memset.p0i8
26+
// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}%{{[0-9]+}}, i8 42, [[USIZE]] 100000, i32 1, i1 false)
2227
iter::repeat(42).take(100000).collect()
2328
}

src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ trait Copy {}
2323
#[lang = "freeze"]
2424
trait Freeze {}
2525

26+
impl<T: ?Sized> Copy for *mut T {}
27+
2628
#[cfg(target_has_atomic = "8")]
2729
pub unsafe fn atomic_u8(x: *mut u8) {
2830
atomic_xadd(x, 1);

src/test/run-make-fulldeps/simd-ffi/simd.rs

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ pub trait Sized { }
7575
#[lang = "copy"]
7676
pub trait Copy { }
7777

78+
impl Copy for f32 {}
79+
impl Copy for i32 {}
80+
7881
pub mod marker {
7982
pub use Copy;
8083
}

src/test/ui/coherence-impls-copy.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212

1313
use std::marker::Copy;
1414

15+
impl Copy for i32 {}
16+
//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `i32`:
17+
//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
18+
1519
enum TestE {
1620
A
1721
}
@@ -35,14 +39,14 @@ impl Copy for (MyType, MyType) {}
3539
//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
3640

3741
impl Copy for &'static NotSync {}
38-
//~^ ERROR the trait `Copy` may not be implemented for this type
42+
//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&NotSync`:
3943

4044
impl Copy for [MyType] {}
4145
//~^ ERROR the trait `Copy` may not be implemented for this type
4246
//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
4347

4448
impl Copy for &'static [NotSync] {}
45-
//~^ ERROR the trait `Copy` may not be implemented for this type
49+
//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`:
4650
//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
4751

4852
fn main() {

0 commit comments

Comments
 (0)