I have problems understanding the ref
pattern in Rust. I am referring to https://rustbyexample.com/scope/borrow/ref.html
Here is the code I don\'t under
ref
creates a pointer into the piece of memory that is being matched on, in this case, ref_to_x
is pointing directly to the memory that stores point.x
, it is the same as writing let ref_to_x = &point.x
in this case.
The pattern is extremely important, as it allows one to reach deep inside complicated data-structures without disturbing the ownership hierarchy. For example, if one has val: &Option<String>
, writing
match *val {
Some(s) => println!("the string is {}", s),
None => println!("no string"
}
is not legal, it gives an error like:
<anon>:3:11: 3:15 error: cannot move out of borrowed content
<anon>:3 match *val {
^~~~
<anon>:4:14: 4:15 note: attempting to move value to here
<anon>:4 Some(s) => {}
^
<anon>:4:14: 4:15 help: to prevent the move, use `ref s` or `ref mut s` to capture value by reference
<anon>:4 Some(s) => {}
^
It is not legal to take ownership (move) out of a borrowed value, because that would possibly damage the thing from which the value was borrowed (violating its invariants, causing data to disappear unexpectedly, etc.).
So, one can instead use a reference to just point in the memory with a borrowing &
reference.
There's a slight subtlety here because (a) point
isn't borrowed, so it is OK to move out of point
(which consumes ownership of point
too, meaning it can't be used later unless reinitialised), and (b) the type int
is Copy
, so doesn't move ownership when used by value. This is why using myx
instead works fine. If the type of x
was, say, String
(which isn't Copy
) and point
was borrowed, then the ref
will be necessary.
A reference created with ref
is exactly the same as reference taken with &
.
The difference is where they're allowed in the syntax. ref
on the left side of an assignment is like adding &
on the right side.
These expressions are equivalent:
let ref x1 = y;
let x2 = &y;
This redundancy exists because in pattern matching &
is used to require that a reference exists already, rather than to make a new one:
let foo = 1;
match foo {
ref x => {
/* x == &1 */
match x {
&y => /* y == 1 */
}
},
}
(discussion)