1A variable was used after its contents have been moved elsewhere.23Erroneous code example:45```compile_fail,E03826struct MyStruct { s: u32 }78fn main() {9 let mut x = MyStruct{ s: 5u32 };10 let y = x;11 x.s = 6;12 println!("{}", x.s);13}14```1516Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out17of `x` when we set `y`. This is fundamental to Rust's ownership system: outside18of workarounds like `Rc`, a value cannot be owned by more than one variable.1920Sometimes we don't need to move the value. Using a reference, we can let another21function borrow the value without changing its ownership. In the example below,22we don't actually have to move our string to `calculate_length`, we can give it23a reference to it with `&` instead.2425```26fn main() {27 let s1 = String::from("hello");2829 let len = calculate_length(&s1);3031 println!("The length of '{}' is {}.", s1, len);32}3334fn calculate_length(s: &String) -> usize {35 s.len()36}37```3839A mutable reference can be created with `&mut`.4041Sometimes we don't want a reference, but a duplicate. All types marked `Clone`42can be duplicated by calling `.clone()`. Subsequent changes to a clone do not43affect the original variable.4445Most types in the standard library are marked `Clone`. The example below46demonstrates using `clone()` on a string. `s1` is first set to "many", and then47copied to `s2`. Then the first character of `s1` is removed, without affecting48`s2`. "any many" is printed to the console.4950```51fn main() {52 let mut s1 = String::from("many");53 let s2 = s1.clone();54 s1.remove(0);55 println!("{} {}", s1, s2);56}57```5859If we control the definition of a type, we can implement `Clone` on it ourselves60with `#[derive(Clone)]`.6162Some types have no ownership semantics at all and are trivial to duplicate. An63example is `i32` and the other number types. We don't have to call `.clone()` to64clone them, because they are marked `Copy` in addition to `Clone`. Implicit65cloning is more convenient in this case. We can mark our own types `Copy` if66all their members also are marked `Copy`.6768In the example below, we implement a `Point` type. Because it only stores two69integers, we opt-out of ownership semantics with `Copy`. Then we can70`let p2 = p1` without `p1` being moved.7172```73#[derive(Copy, Clone)]74struct Point { x: i32, y: i32 }7576fn main() {77 let mut p1 = Point{ x: -1, y: 2 };78 let p2 = p1;79 p1.x = 1;80 println!("p1: {}, {}", p1.x, p1.y);81 println!("p2: {}, {}", p2.x, p2.y);82}83```8485Alternatively, if we don't control the struct's definition, or mutable shared86ownership is truly required, we can use `Rc` and `RefCell`:8788```89use std::cell::RefCell;90use std::rc::Rc;9192struct MyStruct { s: u32 }9394fn main() {95 let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));96 let y = x.clone();97 x.borrow_mut().s = 6;98 println!("{}", x.borrow().s);99}100```101102With this approach, x and y share ownership of the data via the `Rc` (reference103count type). `RefCell` essentially performs runtime borrow checking: ensuring104that at most one writer or multiple readers can access the data at any one time.105106If you wish to learn more about ownership in Rust, start with the107[Understanding Ownership][understanding-ownership] chapter in the Book.108109[understanding-ownership]: https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html
Findings
✓ No findings reported for this file.