Reputation: 312
Rust newbie here, I've looked for similar cases in StackOverflow (and there are quite a few), but they all had slightly different scenarios, and I couldn't figure out a way to fix this.
I'm trying to loop over some strings, pass them to a function that applies some operation on them and eventually push the result into a vector. (the actual case is too complex for a map
scenario).
mod lifetime_test {
fn parse_line<'a>(item: &'a str, target: &'a mut Vec<&'a str>) {
// ... use item to compute a result
target.push("result");
}
fn parse_file() {
let mut target: Vec<&str> = Vec::new();
let source: Vec<&str> = Vec::new();
// ... fill source with strings from file
for item in source {
parse_line(item, &mut target);
}
}
}
fn main() {}
The above doesn't compile: mutable borrow starts here in previous iteration of loop
at the parse_line
call.
I think I understand why it complains about the multiple mutable borrows, but I cannot find a way to pass the string and the vector, and have the parse_line
function store its results into the passed vector.
In the actual case the parse_line
function is complex and it might or might not add values to a couple of vectors so I think making parse_line
return the multiple values would make it more complex to understand. So I'd rather pass the vector(2) and have parse_line
decide if it needs or no adding a new value to it.
Upvotes: 1
Views: 1477
Reputation: 15155
Change:
fn parse_line<'a>(item: &'a str, target: &'a mut Vec<&'a str>)
To:
fn parse_line<'a>(item: &'a str, target: &mut Vec<&'a str>)
Just because you have a function which is generic over some lifetime 'a
that doesn't mean that literally every reference used by the function must have the 'a
lifetime. The lifetime of the mutable borrow of target
must be shorter than or equal to 'a
, but you don't want it to be equal because it would heavily restrict your code (and is just plain unnecessary), so as long as you remove the 'a
annotation from mutable borrow of target
the compiler infers the appropriate lifetime for the mutable borrow and the code compiles:
fn parse_line<'a>(item: &'a str, target: &mut Vec<&'a str>) {
// ... use item to compute a result
target.push("result");
}
fn parse_file() {
let mut target: Vec<&str> = Vec::new();
let source: Vec<&str> = Vec::new();
// ... fill source with strings from file
for item in source {
parse_line(item, &mut target);
}
}
Upvotes: 4