What I was originally going for was "the longest 'a such that Super: 'a holds". But I'm now realizing that this doesn't work. For struct Foo<'a>(&'a mut i32, &'static mut i32);, the lifetime of Foo<'a> is 'a, but it must remain borrowed for 'static.
Revised design
Here's what I think we have to do instead. First, we redefine Reborrow like so:
#[lang = "reborrow"]
#[marker]
pub trait Reborrow<'a> {}
impl<'a, T: Copy> Reborrow<'a> for T { }
impl<'a, T: ?Sized> Reborrow<'a> for &'a mut T { }
impl<'short, 'long: 'short, T: Reborrow<'short>> Reborrow<'long> for T { }
- A type can implement
Reborrow<'a>iff the types of all its fields implementReborrow<'a>. - Other requirements are unchanged.
New semantics
For any two types Super and Sub, such that Super is a supertype of Sub:
fn foo(arg: Sub) {
let local: Super = arg;
// HERE
}
At the point marked HERE:
- If
SubimplementsCopy,argremains fully accessible. - If
Subimplements neitherCopynorReborrow,argis permanently inaccessible. - New: if
SubimplementsReborrow(lifetime does not matter) but notCopy, andSuper: Reborrow<'a>(pick the shortest'afor which this holds),argis inaccessible for'a.
Because Reborrow's semantics are defined in terms of subtyping, we get proper handling of invariance "for free".