Recently I was faced with a simple problem where I had a struct with two vecs within, and I wanted to filter one against the other. I wrote a simple call to retain
and used direct references to the attributes of the struct. It all more or less worked.
I then had the need to slightly abstract what I was doing and try to use a function that provides the vectors. In the simplest case, its just a wrapper around the same struct, so the references are ultimately pointing back to the same thing. This ends up not working because I am doing two different borrows. What I'm wondering is if there's some way to mark this up in a way that lets the borrow checker behave the same as the direct attribute references?
I tried to make a small reproduction (playground):
#[derive(Debug)]
struct Wrapper {
thing1: Vec<u32>,
thing2: Vec<u32>,
}
impl Wrapper {
fn get_thing1(&self) -> &Vec<u32> {
&self.thing1
}
fn get_thing2(&mut self) -> &mut Vec<u32> {
&mut self.thing2
}
}
fn de_dupe(w: &mut Wrapper) {
let thing1 = w.get_thing1();
let thing2 = w.get_thing2();
thing2.retain(|v| thing1.contains(v));
}
fn de_dupe_without_impl(w: &mut Wrapper) {
w.thing2.retain(|v| w.thing1.contains(v));
}
fn main() {
let mut w = Wrapper {
thing1: vec![1, 2, 3, 4, 5],
thing2: vec![4, 5, 6, 7],
};
de_dupe(&mut w);
de_dupe_without_impl(&mut w);
dbg!(w);
}
This generates:
Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `*w` as mutable because it is also borrowed as immutable
--> src/main.rs:19:18
|
18 | let thing1 = w.get_thing1();
| -------------- immutable borrow occurs here
19 | let thing2 = w.get_thing2();
| ^^^^^^^^^^^^^^ mutable borrow occurs here
20 | thing2.retain(|v| thing1.contains(v));
| ------ immutable borrow later captured here by closure
For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground` (bin "playground") due to previous error
My actual use case has a slightly more involved check than the contains
used here, but ultimately it just boils down to "i need a variable from thing2 and all of thing1".
Any hints/tips? I'm sure theres some alternative way to write the logic that could avoid this scenario outright, too.
I'm sure I'm using the wrong terminology here, so I'd love to learn what the proper terms for some of these concepts are, too.