3 ms·
> Can you show me a "valid program" that Rust rejects? #[derive(Debug)] struct Foo { a: i32 } fn thing(foo: &mut Foo) { ma
by Measter 4y ago
> Can you show me a "valid program" that Rust rejects?
#[derive(Debug)]
struct Foo {
a: i32
}
fn thing(foo: &mut Foo) {
match foo {
f @ Foo { a } if *a > 5 => {
println!("{:?}", f)
}
_ => {}
}
}
There's no reason it should reject that, as the use of the `a` reference doesn't interleave with the use of `f`.
- Klonoar 4y agoBy creating `f` you're in essence trying to borrow something that's mutably borrowed already, which the borrow checker doesn't allow. I guess I could see some logic for this being possible, but in practice I've never encountered this in any Rust codebase I've gone through. The trivial example fix is just to... ensure it can copy, and tweak the match line: #[derive(Copy, Clone, Debug)] struct Foo { a: i32 } fn thing(foo: &mut Foo) { match *foo { f @ Foo { a } if a > 5 => { println!("{:?}", f) } _ => {} } } fn main() { let mut x = Foo { a: 1 }; thing(&mut x); } If the struct was bigger and/or had types that couldn't copy, I'd refrain from trying to shoehorn matching like that entirely.
- Measter 4y agoThe borrow checker does allow that, though, as long the uses don't interleave and the references created correctly. As long as `f` is not used between `a`'s creation and last use, and `a` comes from `f`, it's valid for that alias to exist. You can see that with this code example, which is accepted: #[derive(Debug)] pub struct Foo { a: i32 } impl Foo { fn get_a(&mut self) -> &mut i32 { &mut self.a } } pub fn thing(mut foo: &mut Foo) { let f = &mut foo; let a = f.get_a(); if *a > 5 { println!("{:?}", f); } } That's why I was so surprised the compiler rejected it.