I'd have imagined a pattern match where there is a bind-by-move on one hand, and a bind-by-ref on the other, such as in:
fn main ()
{
let mut it = (Some(vec![42]), Some(vec![]));
if let (Some(v), Some(ref mut vs)) = it {
vs.push(v);
}
dbg!(&it.1);
}
but sadly this currently fails with:
error[E0009]: cannot bind by-move and by-ref in the same pattern
And yet, there is a:
This limitation may be removed in a future version of Rust
in the detailed error message.
(And yes, replacing = it by = (it.0, it.1.as_mut()) works, and does not require refs, but that is implicitely performing one more nested pattern match on the .1 field, so I think it would qualify as less expressive).
A similar code that works right now is when the by-move is Copy (since it can still be by-ref under the hood, I imagine):
let mut it = (Some(42), Some(vec![]));
if let (Some(v), Some(ref mut vs)) = it {
vs.push(v);
}
dbg!(&it.1);
which, imho, is a bit more expressive than:
let mut it = (Some(42), Some(vec![]));
if let (Some(v), Some(vs)) = (it.0, &mut it.1) {
vs.push(v);
}
dbg!(&it.1);
which has required explicitly splitting the matched expression.
-
to my surprise, the following does not work despite match ergonomics:
if let (Some(&mut v), Some(v)) = &mut it {
- and even if it did, that would still be 2 x
&mut vs. 1 x ref mut.