Skip to content

Commit 0296838

Browse files
committed
Beef up Copy documentation
Fixes #21249 Fixes #11540
1 parent 433ea0b commit 0296838

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

src/libcore/marker.rs

+98
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,104 @@ pub trait Sized {
4242
}
4343

4444
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
45+
///
46+
/// By default, variable bindings have 'move semantics.' In other
47+
/// words:
48+
///
49+
/// ```
50+
/// #[derive(Show)]
51+
/// struct Foo;
52+
///
53+
/// let x = Foo;
54+
///
55+
/// let y = x;
56+
///
57+
/// // `x` has moved into `y`, and so cannot be used
58+
///
59+
/// // println!("{:?}", x); // error: use of moved value
60+
/// ```
61+
///
62+
/// However, if a type implements `Copy`, it instead has 'copy semantics':
63+
///
64+
/// ```
65+
/// // we can just derive a `Copy` implementation
66+
/// #[derive(Show, Copy)]
67+
/// struct Foo;
68+
///
69+
/// let x = Foo;
70+
///
71+
/// let y = x;
72+
///
73+
/// // `y` is a copy of `x`
74+
///
75+
/// println!("{:?}", x); // A-OK!
76+
/// ```
77+
///
78+
/// It's important to note that in these two examples, the only difference is if you are allowed to
79+
/// access `x` after the assignment: a move is also a bitwise copy under the hood.
80+
///
81+
/// ## When can my type be `Copy`?
82+
///
83+
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
84+
/// `struct` can be `Copy`:
85+
///
86+
/// ```
87+
/// struct Point {
88+
/// x: i32,
89+
/// y: i32,
90+
/// }
91+
/// ```
92+
///
93+
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
94+
///
95+
/// ```
96+
/// # struct Point;
97+
/// struct PointList {
98+
/// points: Vec<Point>,
99+
/// }
100+
/// ```
101+
///
102+
/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
103+
/// attempt to derive a `Copy` implementation, we'll get an error.
104+
///
105+
/// ```text
106+
/// error: the trait `Copy` may not be implemented for this type; field `points` does not implement
107+
/// `Copy`
108+
/// ```
109+
///
110+
/// ## How can I implement `Copy`?
111+
///
112+
/// There are two ways to implement `Copy` on your type:
113+
///
114+
/// ```
115+
/// #[derive(Copy)]
116+
/// struct MyStruct;
117+
/// ```
118+
///
119+
/// and
120+
///
121+
/// ```
122+
/// struct MyStruct;
123+
/// impl Copy for MyStruct {}
124+
/// ```
125+
///
126+
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
127+
/// bound on type parameters, which isn't always desired.
128+
///
129+
/// ## When can my type _not_ be `Copy`?
130+
///
131+
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
132+
/// mutable reference, and copying `String` would result in two attempts to free the same buffer.
133+
///
134+
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
135+
/// managing some resource besides its own `size_of::<T>()` bytes.
136+
///
137+
/// ## When should my type be `Copy`?
138+
///
139+
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
140+
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
141+
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
142+
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
45143
#[stable]
46144
#[lang="copy"]
47145
pub trait Copy {

0 commit comments

Comments
 (0)