user103716
user103716

Reputation: 312

mutable borrow starts here in previous iteration of loop

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).

playground

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

Answers (1)

pretzelhammer
pretzelhammer

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);
    }
}

playground

Upvotes: 4

Related Questions