I have a function that will either return a reference to existing item from a Vec, or push a new item onto the Vec and return a reference to that existing item. I created a basic exmple that illustrates what I want to do:
struct F {
x: Vec<Vec<String>>,
}
impl F {
fn foo(&mut self, s: String) -> &[String] {
for strings in &self.x {
if strings.contains(&s) {
return &strings;
}
}
self.x.push(vec![s]);
&self.x[self.x.len() - 1]
}
}
But when I try to compile this, I get an error about lifetimes:
error[E0502]: cannot borrow `self.x` as mutable because it is also borrowed as immutable
--> src/lib.rs:13:9
|
6 | fn foo(&mut self, s: String) -> &[String] {
| - let's call the lifetime of this reference `'1`
7 | for strings in &self.x {
| ------- immutable borrow occurs here
8 | if strings.contains(&s) {
9 | return &strings;
| -------- returning this value requires that `self.x` is borrowed for `'1`
...
13 | self.x.push(vec![s]);
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
I don't understand this error, because in my mind the immutable borrow on line 7 is guaranteed to no longer exist by line 13, since the function will either have returned before line 13, or the for loop will have ended, and the borrow should end with it. What am I missing?
I think this is a limitation of current borrow checker, you can do this instead:
struct F {
x: Vec<Vec<String>>,
}
impl F {
fn foo(&mut self, s: String) -> &[String] {
let ret = self.x.iter().position(|strings| strings.contains(&s));
if let Some(ret) = ret {
&self.x[ret]
} else {
self.x.push(vec![s]);
&self.x.last().unwrap()
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With