Skip to content

Commit 9dfb210

Browse files
authored
Rollup merge of rust-lang#45082 - jacwah:explain-E0382, r=steveklabnik
Mention Clone and refs in --explain E0382 I followed the discussion in rust-lang#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 ✨
2 parents ebdfe33 + 47ea51e commit 9dfb210

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

src/librustc_mir/diagnostics.rs

+57-9
Original file line numberDiff line numberDiff line change
@@ -320,20 +320,68 @@ Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
320320
of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
321321
of workarounds like `Rc`, a value cannot be owned by more than one variable.
322322
323-
If we own the type, the easiest way to address this problem is to implement
324-
`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
325-
information in `x`, while leaving the original version owned by `x`. Subsequent
326-
changes to `x` will not be reflected when accessing `y`.
323+
Sometimes we don't need to move the value. Using a reference, we can let another
324+
function borrow the value without changing its ownership. In the example below,
325+
we don't actually have to move our string to `calculate_length`, we can give it
326+
a reference to it with `&` instead.
327+
328+
```
329+
fn main() {
330+
let s1 = String::from("hello");
331+
332+
let len = calculate_length(&s1);
333+
334+
println!("The length of '{}' is {}.", s1, len);
335+
}
336+
337+
fn calculate_length(s: &String) -> usize {
338+
s.len()
339+
}
340+
```
341+
342+
A mutable reference can be created with `&mut`.
343+
344+
Sometimes we don't want a reference, but a duplicate. All types marked `Clone`
345+
can be duplicated by calling `.clone()`. Subsequent changes to a clone do not
346+
affect the original variable.
347+
348+
Most types in the standard library are marked `Clone`. The example below
349+
demonstrates using `clone()` on a string. `s1` is first set to "many", and then
350+
copied to `s2`. Then the first character of `s1` is removed, without affecting
351+
`s2`. "any many" is printed to the console.
352+
353+
```
354+
fn main() {
355+
let mut s1 = String::from("many");
356+
let s2 = s1.clone();
357+
s1.remove(0);
358+
println!("{} {}", s1, s2);
359+
}
360+
```
361+
362+
If we control the definition of a type, we can implement `Clone` on it ourselves
363+
with `#[derive(Clone)]`.
364+
365+
Some types have no ownership semantics at all and are trivial to duplicate. An
366+
example is `i32` and the other number types. We don't have to call `.clone()` to
367+
clone them, because they are marked `Copy` in addition to `Clone`. Implicit
368+
cloning is more convienient in this case. We can mark our own types `Copy` if
369+
all their members also are marked `Copy`.
370+
371+
In the example below, we implement a `Point` type. Because it only stores two
372+
integers, we opt-out of ownership semantics with `Copy`. Then we can
373+
`let p2 = p1` without `p1` being moved.
327374
328375
```
329376
#[derive(Copy, Clone)]
330-
struct MyStruct { s: u32 }
377+
struct Point { x: i32, y: i32 }
331378
332379
fn main() {
333-
let mut x = MyStruct{ s: 5u32 };
334-
let y = x;
335-
x.s = 6;
336-
println!("{}", x.s);
380+
let mut p1 = Point{ x: -1, y: 2 };
381+
let p2 = p1;
382+
p1.x = 1;
383+
println!("p1: {}, {}", p1.x, p1.y);
384+
println!("p2: {}, {}", p2.x, p2.y);
337385
}
338386
```
339387

0 commit comments

Comments
 (0)