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.