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