Rollup merge of #45082 - jacwah:explain-E0382, r=steveklabnik

Mention Clone and refs in --explain E0382

I followed the discussion in #42446 and came up with these additions.

- Mention references before going into traits. They're probably more likely solutions.
- Mention `Clone` before `Copy`. Cloning has wider applicability and `#derive[Copy, Clone]` makes more sense after learning about `Clone`.

The language is not great, any suggestions there would be appreciated 
This commit is contained in:
kennytm 2017-10-19 01:59:46 +08:00 committed by GitHub
commit 9dfb210761

View File

@ -320,20 +320,68 @@ Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
of `x` when we set `y`. This is fundamental to Rust's ownership system: outside of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
of workarounds like `Rc`, a value cannot be owned by more than one variable. of workarounds like `Rc`, a value cannot be owned by more than one variable.
If we own the type, the easiest way to address this problem is to implement Sometimes we don't need to move the value. Using a reference, we can let another
`Copy` and `Clone` on it, as shown below. This allows `y` to copy the function borrow the value without changing its ownership. In the example below,
information in `x`, while leaving the original version owned by `x`. Subsequent we don't actually have to move our string to `calculate_length`, we can give it
changes to `x` will not be reflected when accessing `y`. a reference to it with `&` instead.
```
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
```
A mutable reference can be created with `&mut`.
Sometimes we don't want a reference, but a duplicate. All types marked `Clone`
can be duplicated by calling `.clone()`. Subsequent changes to a clone do not
affect the original variable.
Most types in the standard library are marked `Clone`. The example below
demonstrates using `clone()` on a string. `s1` is first set to "many", and then
copied to `s2`. Then the first character of `s1` is removed, without affecting
`s2`. "any many" is printed to the console.
```
fn main() {
let mut s1 = String::from("many");
let s2 = s1.clone();
s1.remove(0);
println!("{} {}", s1, s2);
}
```
If we control the definition of a type, we can implement `Clone` on it ourselves
with `#[derive(Clone)]`.
Some types have no ownership semantics at all and are trivial to duplicate. An
example is `i32` and the other number types. We don't have to call `.clone()` to
clone them, because they are marked `Copy` in addition to `Clone`. Implicit
cloning is more convienient in this case. We can mark our own types `Copy` if
all their members also are marked `Copy`.
In the example below, we implement a `Point` type. Because it only stores two
integers, we opt-out of ownership semantics with `Copy`. Then we can
`let p2 = p1` without `p1` being moved.
``` ```
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct MyStruct { s: u32 } struct Point { x: i32, y: i32 }
fn main() { fn main() {
let mut x = MyStruct{ s: 5u32 }; let mut p1 = Point{ x: -1, y: 2 };
let y = x; let p2 = p1;
x.s = 6; p1.x = 1;
println!("{}", x.s); println!("p1: {}, {}", p1.x, p1.y);
println!("p2: {}, {}", p2.x, p2.y);
} }
``` ```