3 ms·
I ran into a borrow check error on code like this[0]: enum Inner { A(i32), B(i32) } enum Outer { Foo{ fiel
by Measter 4y ago
I ran into a borrow check error on code like this[0]:
enum Inner {
A(i32),
B(i32)
}
enum Outer {
Foo{
field: Inner
}
}
fn do_foo(val: &mut Outer) {
match val {
Outer::Foo{field: f @ Inner::A(id)} if *id == 3 => {
*f = Inner::B(25);
},
_ => {}
}
}
The compiler is seeing the `id` and `f` references as overlapping for the entire arm, even though the use of `id` and `f` are not interleaved. Bearing in mind that I don't actually know how the compiler works here, but I don't think this is a borrow checker limitation in and of itself, rather what I think is happening is that in the match expression the compiler is creating both `id` and `f` directly from `val`, creating the overlapping borrow.
The reason I believe that is that this equivalent code results in the same error[1]:
fn do_foo(val: &mut Outer) {
let f = val.get_inner();
let id = val.get_inner().get_a();
if *id == 3 {
*f = Inner::B(25);
}
}
Whereas if you create the `id` reference from `f` instead of from `val` the compiler accepts it because `f` is not used between `id`s creation and death[2]:
fn do_foo(val: &mut Outer) {
let f = val.get_inner();
let id = f.get_a();
if *id == 3 {
*f = Inner::B(25);
}
}
[0] Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=28a84770cb1f0eaadb9695284d974e41 https://play.rust-lang.org/?version=stable&mode=debug&editio...
[1] https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=55dd6b79a94eaccc81a126281a96015c https://play.rust-lang.org/?version=stable&mode=debug&editio...
[2] https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3115af527960a3cf9f763e38fa55e70e https://play.rust-lang.org/?version=stable&mode=debug&editio...