ref
is used in patterns to bind a reference to an lvalue (an lvalue is a value you can take the address of, more or less).
It's important to understand that patterns go "backwards" from normal expressions, since they're used to deconstruct values.
Here's a simple example. Suppose we have this:
let value = 42;
We can bind a reference to value
in two ways:
let reference1 = &value;
let ref reference2 = value;
In the first case, we use &
as an operator to take the address of value
. In the second case, we use the ref
pattern to "deconstruct" an lvalue. In both cases, the type of the variable is &i32
.
&
can also be used in patterns, but it does the opposite: it deconstructs a reference by dereferencing it. Suppose we have:
let value = 42;
let reference = &value;
We can dereference reference
in two ways:
let deref1 = *reference;
let &deref2 = reference;
Here, the type of both deref1
and deref2
is i32
.
It's not always possible to write the same expression in two ways as shown here, however. For example, you cannot use &
to take a reference to a value stored in an enum variant: you need to match on it. For example, if you want to take a reference to the value in a Some
, you need to write:
match option {
Some(ref value) => { /* stuff */ }
None => { /* stuff */ }
}
since there's no way in Rust you can use the &
operator to access the value otherwise.