Hm.. might not be enough yet, since, apparently, you can tell that the immutable reference you get to see in the guard is really the same one as you get in the body of the match arm. This is possible through them having the same lifetime; it’s e.g possible to keep immutable re-borrows from the guard around and get effects such as in the following example:
#![feature(box_patterns)]
fn foo() {
let (mut x, y) = ((1,), 2);
let mut x_r = Box::new(x);
let mut y_r = &y;
let _v = *y_r;
match x_r {
box (ref mut r,)
if {
y_r = &*r;
true
} => {
let _v = *y_r;
*r = 1;
// not okay here
// let _v = *y_r;
}
_ => {}
}
}
This cannot be compiled in the fashion I suggested above.
On the other hand, what sane code needs to rely on the fact that a by-reference capture has a particularly long lifetime in a guard? What I’m saying is: I wouldn’t be sad if the above code stopped compiling for a deref-based pattern-matching feature (instead of the box pattern).
Edit: fun fact, I didn’t even know it was possible that multiple subsequent patterns in a guard can create conflicts in the borrow checker, but here we go
let mut x = Some(42);
let mut z = &0;
match &mut x {
Some(ref y) if {
z = y;
false
} => {}
Some(ref mut _y) => {
println!("{}", *z);
}
_ => {}
}
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> src/main.rs:9:10
|
5 | Some(ref y) if {
| ----- immutable borrow occurs here
...
9 | Some(ref mut _y) => {
| ^^^^^^^^^^ mutable borrow occurs here
10 | println!("{}", *z);
| -- immutable borrow later used here
Also noteworthy is how this code
let mut x = Some(42);
let mut z = &0;
match &mut x {
Some(ref y) if {
z = y;
false
} => {}
Some(ref _y) => {
println!("{}", *z);
}
_ => {}
}
prints 42, yet still complains (incorrectly, I guess) about
Compiling playground v0.0.1 (/playground)
warning: value assigned to `z` is never read
--> src/main.rs:6:9
|
6 | z = y;
| ^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?