Beginner - &Some(p) and Some(&p)
โ Rust ๐ 2026-02-22 ๐ค surdeus ๐๏ธ 1Hello friendly people, hope I can bother you with a beginner question.
This is the third Option exercise in Rustlings. (full code at the bottom of this post) The idea is to match on a value, and then use the value again after the match. The value is moved to the match, so it does not compile because the println!() thereafter accesses the value too.
So, instead, the match should be on a reference to the value. I would think that this would be the solution:
match &optional_point {
&Some(p) => println!("Coordinates are {},{}", p.x, p.y),
_ => panic!("No match!"),
}
I added a & to the Some(p) because I expected &optional_point to be &Some(p) when optional_point is Some(p). But that gives a compiler error 'cannot move out of a shared reference': p is moved into the &Some(p). My first question is: what does that mean? It has nothing to do with the print statement afterwards, because if that is commented out the error stays the same. And why is this not an issue in the second (correct) solution below?
After trial and error I found the solution is
match &optional_point {
Some(p) => println!("Coordinates are {},{}", p.x, p.y),
_ => panic!("No match!"),
}
My other questions are: how can &optional_point match on Some(p) without &? Is there automatic dereferencing going on? (not a big fan of that, as it feels I can't get a grip on what is happening). In VSCode the types of parameters are automatically shown. In the first, incorrect, solution, the type of p is Point, in the second, correct, solution the type of p is &Point. I donยดt understand how the type of p can have become &Point, when the match is not on a reference. How does that work?
I apologize for the frustration that is probably noticable. The mechanics of borrowing, Option, match etc. are actually clear. But somehow, I can't seem to predict how stuff interacts and this is one of those instances. I mean, it is easy to solve by just following compiler's orders in adding or removing ampersands, but I would love if I could actually predict those orders myself, from the principles of borrowing.
Full code of the exercise:
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let optional_point = Some(Point { x: 100, y: 200 });
// TODO: Fix the compiler error by adding something to this match statement.
match optional_point {
Some(p) => println!("Coordinates are {},{}", p.x, p.y),
_ => panic!("No match!"),
}
println!("{optional_point:?}"); // Don't change this line.
}
4 posts - 3 participants
๐ท๏ธ Rust_feed