Skip to content

Commit 27164fa

Browse files
committed
Move some implementations of Clone and Copy to libcore
Add implementations of `Clone` and `Copy` for some primitive types to libcore so that they show up in the documentation. The concerned types are the following: * All primitive signed and unsigned integer types (`usize`, `u8`, `u16`, `u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`, `i128`); * All primitive floating point types (`f32`, `f64`) * `bool` * `char` * `!` * Raw pointers (`*const T` and `*mut T`) * Shared references (`&'a T`) These types already implemented `Clone` and `Copy`, but the implementation was provided by the compiler. The compiler no longer provides these implementations and instead tries to look them up as normal trait implementations. The goal of this change is to make the implementations appear in the generated documentation. For `Copy` specifically, the compiler would reject an attempt to write an `impl` for the primitive types listed above with error `E0206`; this error no longer occurs for these types, but it will still occur for the other types that used to raise that error. The trait implementations are guarded with `#[cfg(not(stage0))]` because they are invalid according to the stage0 compiler. When the stage0 compiler is updated to a revision that includes this change, the attribute will have to be removed, otherwise the stage0 build will fail because the types mentioned above no longer implement `Clone` or `Copy`. For type variants that are variadic, such as tuples and function pointers, and for array types, the `Clone` and `Copy` implementations are still provided by the compiler, because the language is not expressive enough yet to be able to write the appropriate implementations in Rust. The initial plan was to add `impl` blocks guarded by `#[cfg(dox)]` to make them apply only when generating documentation, without having to touch the compiler. However, rustdoc's usage of the compiler still rejected those `impl` blocks. This is a [breaking-change] for users of `#![no_core]`, because they will now have to supply their own implementations of `Clone` and `Copy` for the primitive types listed above. The easiest way to do that is to simply copy the implementations from `src/libcore/clone.rs` and `src/libcore/marker.rs`. Fixes #25893
1 parent 989b257 commit 27164fa

File tree

11 files changed

+176
-30
lines changed

11 files changed

+176
-30
lines changed

src/libcore/clone.rs

+60
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,63 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData
135135
reason = "deriving hack, should not be public",
136136
issue = "0")]
137137
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
138+
139+
/// Implementations of `Clone` for primitive types.
140+
///
141+
/// Implementations that cannot be described in Rust
142+
/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
143+
#[cfg(not(stage0))]
144+
mod impls {
145+
146+
use super::Clone;
147+
148+
macro_rules! impl_clone {
149+
($($t:ty)*) => {
150+
$(
151+
#[stable(feature = "rust1", since = "1.0.0")]
152+
impl Clone for $t {
153+
fn clone(&self) -> Self {
154+
*self
155+
}
156+
}
157+
)*
158+
}
159+
}
160+
161+
impl_clone! {
162+
usize u8 u16 u32 u64 u128
163+
isize i8 i16 i32 i64 i128
164+
f32 f64
165+
bool char
166+
}
167+
168+
#[stable(feature = "never_type", since = "1.26.0")]
169+
impl Clone for ! {
170+
fn clone(&self) -> Self {
171+
*self
172+
}
173+
}
174+
175+
#[stable(feature = "rust1", since = "1.0.0")]
176+
impl<T: ?Sized> Clone for *const T {
177+
fn clone(&self) -> Self {
178+
*self
179+
}
180+
}
181+
182+
#[stable(feature = "rust1", since = "1.0.0")]
183+
impl<T: ?Sized> Clone for *mut T {
184+
fn clone(&self) -> Self {
185+
*self
186+
}
187+
}
188+
189+
// Shared references can be cloned, but mutable references *cannot*!
190+
#[stable(feature = "rust1", since = "1.0.0")]
191+
impl<'a, T: ?Sized> Clone for &'a T {
192+
fn clone(&self) -> Self {
193+
*self
194+
}
195+
}
196+
197+
}

src/libcore/marker.rs

+40
Original file line numberDiff line numberDiff line change
@@ -593,3 +593,43 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
593593
/// This trait is automatically implemented for almost every type.
594594
#[unstable(feature = "pin", issue = "49150")]
595595
pub unsafe auto trait Unpin {}
596+
597+
/// Implementations of `Copy` for primitive types.
598+
///
599+
/// Implementations that cannot be described in Rust
600+
/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
601+
#[cfg(not(stage0))]
602+
mod copy_impls {
603+
604+
use super::Copy;
605+
606+
macro_rules! impl_copy {
607+
($($t:ty)*) => {
608+
$(
609+
#[stable(feature = "rust1", since = "1.0.0")]
610+
impl Copy for $t {}
611+
)*
612+
}
613+
}
614+
615+
impl_copy! {
616+
usize u8 u16 u32 u64 u128
617+
isize i8 i16 i32 i64 i128
618+
f32 f64
619+
bool char
620+
}
621+
622+
#[stable(feature = "never_type", since = "1.26.0")]
623+
impl Copy for ! {}
624+
625+
#[stable(feature = "rust1", since = "1.0.0")]
626+
impl<T: ?Sized> Copy for *const T {}
627+
628+
#[stable(feature = "rust1", since = "1.0.0")]
629+
impl<T: ?Sized> Copy for *mut T {}
630+
631+
// Shared references can be copied, but mutable references *cannot*!
632+
#[stable(feature = "rust1", since = "1.0.0")]
633+
impl<'a, T: ?Sized> Copy for &'a T {}
634+
635+
}

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
@@ -1918,16 +1918,16 @@ differs from the behavior for `&T`, which is always `Copy`).
19181918

19191919
E0206: r##"
19201920
You can only implement `Copy` for a struct or enum. Both of the following
1921-
examples will fail, because neither `i32` (primitive type) nor `&'static Bar`
1922-
(reference to `Bar`) is a struct or enum:
1921+
examples will fail, because neither `[u8; 256]` nor `&'static mut Bar`
1922+
(mutable reference to `Bar`) is a struct or enum:
19231923
19241924
```compile_fail,E0206
1925-
type Foo = i32;
1925+
type Foo = [u8; 256];
19261926
impl Copy for Foo { } // error
19271927
19281928
#[derive(Copy, Clone)]
19291929
struct Bar;
1930-
impl Copy for &'static Bar { } // error
1930+
impl Copy for &'static mut Bar { } // error
19311931
```
19321932
"##,
19331933

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() {
+43-17
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,61 @@
1-
error[E0206]: the trait `Copy` may not be implemented for this type
2-
--> $DIR/coherence-impls-copy.rs:29:15
1+
error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`:
2+
--> $DIR/coherence-impls-copy.rs:15:1
33
|
4-
LL | impl Copy for &'static mut MyType {}
5-
| ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
4+
LL | impl Copy for i32 {}
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: conflicting implementation in crate `core`:
8+
- impl std::marker::Copy for i32;
9+
10+
error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`:
11+
--> $DIR/coherence-impls-copy.rs:41:1
12+
|
13+
LL | impl Copy for &'static NotSync {}
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: conflicting implementation in crate `core`:
17+
- impl<'a, T> std::marker::Copy for &'a T
18+
where T: ?Sized;
19+
20+
error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`:
21+
--> $DIR/coherence-impls-copy.rs:48:1
22+
|
23+
LL | impl Copy for &'static [NotSync] {}
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
|
26+
= note: conflicting implementation in crate `core`:
27+
- impl<'a, T> std::marker::Copy for &'a T
28+
where T: ?Sized;
629

730
error[E0206]: the trait `Copy` may not be implemented for this type
831
--> $DIR/coherence-impls-copy.rs:33:15
932
|
10-
LL | impl Copy for (MyType, MyType) {}
11-
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
33+
LL | impl Copy for &'static mut MyType {}
34+
| ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
1235

1336
error[E0206]: the trait `Copy` may not be implemented for this type
1437
--> $DIR/coherence-impls-copy.rs:37:15
1538
|
16-
LL | impl Copy for &'static NotSync {}
39+
LL | impl Copy for (MyType, MyType) {}
1740
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
1841

1942
error[E0206]: the trait `Copy` may not be implemented for this type
20-
--> $DIR/coherence-impls-copy.rs:40:15
43+
--> $DIR/coherence-impls-copy.rs:44:15
2144
|
2245
LL | impl Copy for [MyType] {}
2346
| ^^^^^^^^ type is not a structure or enumeration
2447

25-
error[E0206]: the trait `Copy` may not be implemented for this type
26-
--> $DIR/coherence-impls-copy.rs:44:15
48+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
49+
--> $DIR/coherence-impls-copy.rs:15:1
2750
|
28-
LL | impl Copy for &'static [NotSync] {}
29-
| ^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
51+
LL | impl Copy for i32 {}
52+
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
53+
|
54+
= note: the impl does not reference any types defined in this crate
55+
= note: define and implement a trait or new type instead
3056

3157
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
32-
--> $DIR/coherence-impls-copy.rs:33:1
58+
--> $DIR/coherence-impls-copy.rs:37:1
3359
|
3460
LL | impl Copy for (MyType, MyType) {}
3561
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
@@ -38,7 +64,7 @@ LL | impl Copy for (MyType, MyType) {}
3864
= note: define and implement a trait or new type instead
3965

4066
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
41-
--> $DIR/coherence-impls-copy.rs:40:1
67+
--> $DIR/coherence-impls-copy.rs:44:1
4268
|
4369
LL | impl Copy for [MyType] {}
4470
| ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
@@ -47,15 +73,15 @@ LL | impl Copy for [MyType] {}
4773
= note: define and implement a trait or new type instead
4874

4975
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
50-
--> $DIR/coherence-impls-copy.rs:44:1
76+
--> $DIR/coherence-impls-copy.rs:48:1
5177
|
5278
LL | impl Copy for &'static [NotSync] {}
5379
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
5480
|
5581
= note: the impl does not reference any types defined in this crate
5682
= note: define and implement a trait or new type instead
5783

58-
error: aborting due to 8 previous errors
84+
error: aborting due to 10 previous errors
5985

60-
Some errors occurred: E0117, E0206.
86+
Some errors occurred: E0117, E0119, E0206.
6187
For more information about an error, try `rustc --explain E0117`.

src/test/ui/error-codes/E0206.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
type Foo = i32;
11+
type Foo = [u8; 256];
1212

1313
impl Copy for Foo { }
1414
//~^ ERROR the trait `Copy` may not be implemented for this type
@@ -17,7 +17,7 @@ impl Copy for Foo { }
1717
#[derive(Copy, Clone)]
1818
struct Bar;
1919

20-
impl Copy for &'static Bar { }
20+
impl Copy for &'static mut Bar { }
2121
//~^ ERROR the trait `Copy` may not be implemented for this type
2222

2323
fn main() {

src/test/ui/error-codes/E0206.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ LL | impl Copy for Foo { }
77
error[E0206]: the trait `Copy` may not be implemented for this type
88
--> $DIR/E0206.rs:20:15
99
|
10-
LL | impl Copy for &'static Bar { }
11-
| ^^^^^^^^^^^^ type is not a structure or enumeration
10+
LL | impl Copy for &'static mut Bar { }
11+
| ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
1212

1313
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
1414
--> $DIR/E0206.rs:13:1

0 commit comments

Comments
 (0)