Match let with ref vs &

What is the difference between

while let Some(ref node) = head {...}

and

while let Some(node) = &head {...}
1 Like

They are the same, but the second form was only added to the language in Rust 1.26. You can read more about the design and motivation of that feature in RFC 2005.

3 Likes

Thanks! Can you kind of help me understand how I should read this. Like "destructuring an option into node from a reference to head?"

Hmm, I would say that node is binding a reference within head. I don't really think of it as destructuring unless the pattern is actually moving the pieces out. That's a fuzzy distinction though, because a single pattern can borrow some parts and move others.

Another possibility:

while let Some(node) = head.as_ref() {}

This one really is destructuring, because as_ref() returns an Option<&T>, then we take that apart.

1 Like

The way to read the second version is that matching on a reference is like matching on the inner type, except that all fields are turned into references.

2 Likes

Since all the fields are turned to references, am I able to still borrow the BIG type again within that block? LIke does borrowing Struct borrow all of the fields of the struct as well or can I borrow those seperately afterwards?

while let Some(ref mut node) = head {
    let again = &mut head.as_mut().unwrap();

This doesnt compile if I try to use any of the variables but i want to know like how the borrows work.

Are they actually EXACTLY the same? Like it looks like by using "ref" im only borrowing the inner field of the struct. Is is actually borrowing the whole struct?

That's a fair point. The original examples have the same effect, but in something like this:

let opt: Option<(String, String)> = Some(("a".into(), "b".into()));
// ...
if let Some((ref a, b)) = opt {
    // we borrowed `a` and moved `b`
}

You cannot move b with if let Some(...) = &opt.