struct NoCopy;
fn this_one_compiles() {
let a = Some(5);
let b = Some(NoCopy);
loop {
if let Some(a) = a && let Some(b) = b {
break (a, b)
}
};
}
fn then_why_doesnt_this_one_compile() {
let a = Some(NoCopy);
let b = Some(NoCopy);
loop {
if let Some(a) = a && let Some(b) = b {
break (a, b)
}
};
}
the first function compiles and shows that rust understands that if let Some(foo) = opt { break foo },
the second function shows that it doesn't.
my guess is that only the last let can consume, but why?
if let Some(myOptionValue) = myOption effectively moves the value out from the option.
The reason why it works on the first function but doesn't in the second, is that you're dealing with two variables, and both need to be Some for the loop to break.
For the first function, if the value of a moves out, it doesn't matter, because it's copy, so the loop can continue until b is Some.
This doesn't work for the second function, because as soon as the value of a moves out in one of the loop iterations, the loop can't keep going. That is, think of the case of a being Some and b being None.
oh, i thought it'd first check if all the patterns match (which just requires references), then move all values at once once (not a typo) the branch is taken.
It's not a pattern per se (or as you say, a and b would be new, distinct bindings (variables), and not overwrite existing variables). It's a destructuring assignment. They were stabilized in Rust 1.59 (Feb. 2022).