Skip to content

Allow reassigning a &mut to an inner pointer #11558

@huonw

Description

@huonw
#[crate_type="lib"];

struct List {
    x: int,
    next: Option<~List>
}

#[cfg(invalid)]
pub fn each_loop(mut thing: &mut List, f: |&mut int|) {
    loop {
        f(&mut thing.x);

        match thing.next {
            None => break,
            // borrowck errors:
            Some(~ref mut next) => thing = next,
        }
    }
}

pub fn each_rec(thing: &mut List, f: |&mut int|) {
    f(&mut thing.x);

    match thing.next {
        None => {},
        Some(ref mut next) => each_rec(*next, f),
    }
}

each_loop is invalid, but each_rec is ok.

My feeling is that the loop form should be valid, since the thing object is erased, and so the thing and next borrows do not overlap or alias (that is, the old object to which thing pointed is inaccessible). However I could easily be wrong.

Allowing the first would allow us to write code that is guaranteed to be efficient; although LLVM does perform TCO often so it isn't completely necessary. (That said, LLVM doesn't TCO each_rec, the closure seems to be interfering: with the closure call it is still recursive, but with just thing.x += 1 it is optimised to a loop)

(The equivalent thing with & instead of &mut is already valid.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lifetimesArea: Lifetimes / regions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions