-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Beef up Copy documentation #21261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Beef up Copy documentation #21261
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,104 @@ pub trait Sized { | |
} | ||
|
||
/// Types that can be copied by simply copying bits (i.e. `memcpy`). | ||
/// | ||
/// By default, variable bindings have 'move semantics.' In other | ||
/// words: | ||
/// | ||
/// ``` | ||
/// #[derive(Show)] | ||
/// struct Foo; | ||
/// | ||
/// let x = Foo; | ||
/// | ||
/// let y = x; | ||
/// | ||
/// // `x` has moved into `y`, and so cannot be used | ||
/// | ||
/// // println!("{:?}", x); // error: use of moved value | ||
/// ``` | ||
/// | ||
/// However, if a type implements `Copy`, it instead has 'copy semantics': | ||
/// | ||
/// ``` | ||
/// // we can just derive a `Copy` implementation | ||
/// #[derive(Show, Copy)] | ||
/// struct Foo; | ||
/// | ||
/// let x = Foo; | ||
/// | ||
/// let y = x; | ||
/// | ||
/// // `y` is a copy of `x` | ||
/// | ||
/// println!("{:?}", x); // A-OK! | ||
/// ``` | ||
/// | ||
/// It's important to note that in these two examples, the only difference is if you are allowed to | ||
/// access `x` after the assignment: a move is also a bitwise copy under the hood. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe "a move is also duplicating the value bitwise", to try to avoid overloading "copy" so much. |
||
/// | ||
/// ## When can my type be `Copy`? | ||
/// | ||
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this | ||
/// `struct` can be `Copy`: | ||
/// | ||
/// ``` | ||
/// struct Point { | ||
/// x: i32, | ||
/// y: i32, | ||
/// } | ||
/// ``` | ||
/// | ||
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's very informative to say that a struct can be Copy; it kind-of implies that there might be some other user-defined type that can't be Copy. |
||
/// | ||
/// ``` | ||
/// # struct Point; | ||
/// struct PointList { | ||
/// points: Vec<Point>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it would be better to use |
||
/// } | ||
/// ``` | ||
/// | ||
/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we | ||
/// attempt to derive a `Copy` implementation, we'll get an error. | ||
/// | ||
/// ```text | ||
/// error: the trait `Copy` may not be implemented for this type; field `points` does not implement | ||
/// `Copy` | ||
/// ``` | ||
/// | ||
/// ## How can I implement `Copy`? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this should go before "when can my type be copy", especially as that places the that section next to "when can my type not be copy". |
||
/// | ||
/// There are two ways to implement `Copy` on your type: | ||
/// | ||
/// ``` | ||
/// #[derive(Copy)] | ||
/// struct MyStruct; | ||
/// ``` | ||
/// | ||
/// and | ||
/// | ||
/// ``` | ||
/// struct MyStruct; | ||
/// impl Copy for MyStruct {} | ||
/// ``` | ||
/// | ||
/// There is a small difference between the two: the `derive` strategy will also place a `Copy` | ||
/// bound on type parameters, which isn't always desired. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NB. it is often necessary for type params to be |
||
/// | ||
/// ## When can my type _not_ be `Copy`? | ||
/// | ||
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased | ||
/// mutable reference, and copying `String` would result in two attempts to free the same buffer. | ||
/// | ||
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't a generalisation: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's generalizing the case of |
||
/// managing some resource besides its own `size_of::<T>()` bytes. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "and, it is by far the most common case that a shallow bitwise duplication of the handle will not duplicate the resource, or will otherwise be invalid". (Strictly speaking we could support |
||
/// | ||
/// ## When should my type be `Copy`? | ||
/// | ||
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing | ||
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might also want to mention that it is sometimes useful to have types with no Drop impl but which shouldn't be Copy because they represent some kind of unique logical token or otherwise require more than just a bitwise copy to semantically copy them. |
||
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking | ||
/// change: that second example would fail to compile if we made `Foo` non-`Copy`. | ||
#[stable] | ||
#[lang="copy"] | ||
pub trait Copy { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every value has move semantics by default, not just variable bindings, maybe "by default, types have 'move semantics."?