Allow reading of a mutable reference after it's reborrowed as immutable

I think what would be necessary for writing the kind of code you want to get working would be some new kind of “downgradable mutable reference”. I’d imagine a type with two lifetime arguments, one (longer) for the duration of immutable borrow, and one (shorter) for the duration of mutable borow.

This could possibly even be a generalization of the existing &'a mut T type, which would be the special case of both lifetimes being the same. Assume the new type is for example written as &'a mut<'b> T, where 'a is the (longer) duration of immutable borrow, and 'b is the (shorter) duration of mutable borrow, and &'a mut T is a shorthand of &'a mut<'a> T, then your code would work if add_score is re-written as

impl Foo {
    fn add_score<'a, 'b>(&'a mut<'b> self) -> &'a u32 {
        self.score += 1;
        &self.score
    }
}

Or with some lifetime elision,

impl Foo {
    fn add_score<'a>(&'a mut<'_> self) -> &'a u32 {
        self.score += 1;
        &self.score
    }
}

Perhaps, the existing lifetime-elision rules that favor the lifetime of &self or &mut self would be extended to also favor the first/outer/longer/immutable lifetime 'a in &'a mut<'b> self, then the same thing would be written

impl Foo {
    fn add_score(&mut<'_> self) -> &u32 {
        self.score += 1;
        &self.score
    }
}
8 Likes