Hmm, so let me bring in a bit more context. The main time that I think this problem strikes people is sort of mundane:
pub struct MyStruct {
some_data: Data,
some_more_data: MoreData,
}
impl MyStruct {
pub fn some_function(&mut self) {
let ref1 = self.ref_to_some_data(); // borrows self
self.modify_some_more_data(ref1); // error, self is still borrowed
}
fn ref_to_some_data(&self) -> &u32 {
&self.some_data.some_field
}
fn modify_some_more_data(&mut self, ref: &u32) {
self.some_more_data.modify(ref)
}
}
Here the key point is that ref_to_some_data
and modify_some_more_data
access disjoint fields. (As I wrote earlier, I would like code this to “just compile” – with no syntactic changes – but let’s discuss that a bit later and focus instead on how you would write out something more explicit if you wanted to.)
I was thinking that maybe “views” might be that you get into via coercions or casts. Basically a &mut Foo
could be coerced to a &mut FooView
, where FooView
is some view on Foo
that selects a subset of its fields. Similarly, borrows like &mut foo
would have not only a lifetime 'a
of the borrow, but a view V
that is being borrowed, so that the final type is &'a mut V
.
(Note that we don’t presently allow you to write the lifetime of a borrow explicitly; we probably wouldn’t let you write the lifetime of a view either, but instead use context, meaning you might do something like this to select a view explicitly:
let x: &mut View = &mut foo
(&mut foo) as &mut View
Most of the time, though, I imagine you’d be getting your view via the self
type of a method that is being called:
fn foo(self: &mut View, ...) { ... }
and when we insert the “autoref” for x.foo()
, we would insert one with the appropriate view.