Skip to content

Borrow checker is confused by return statements #6613

@Blei

Description

@Blei

Unless I'm misunderstanding something, the following code should work (it's a minimized example based on code from cscottnet on irc):

fn insert_and_get_borrow<'r>(arr: &'r mut ~[int], i: int) -> &'r int {
    for arr.each |j| {
        if *j == i { return j; }
    }
    // If not included yet, add it
    arr.push(i);
    &arr[arr.len() - 1]
}

Instead it results in this error:

bar.rs:6:4: 6:7 error: cannot borrow `*arr` as mutable because it is also borrowed as immutable
bar.rs:6     arr.push(i);
             ^~~
bar.rs:2:8: 2:11 note: second borrow of `*arr` occurs here
bar.rs:2     for arr.each |j| {
                 ^~~
error: aborting due to previous error

I don't know about the underlying code, but it looks like the borrow checker is confused by the return statement and assumes that the argument to return (the j) is borrowed for the rest of the function, thus making the new immutable borrow fail.

The following workaround compiles without problems:

fn insert_and_get_borrow_workaround<'r>(arr: &'r mut ~[int], i: int) -> &'r int {
    let mut found_index = None;
    for uint::range(0, arr.len()) |index| {
        if arr[index] == i { found_index = Some(index); }
    }
    match found_index {
        Some(index) => &arr[index],
        None => {
            // If not included yet, add it
            arr.push(i);
            &arr[arr.len() - 1]
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions