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
Sub
implementsCopy
,arg
remains fully accessible. - If
Sub
implements neitherCopy
norReborrow
,arg
is permanently inaccessible. - New: if
Sub
implementsReborrow
(lifetime does not matter) but notCopy
, andSuper: Reborrow<'a>
(pick the shortest'a
for which this holds),arg
is inaccessible for'a
.
Because Reborrow
's semantics are defined in terms of subtyping, we get proper handling of invariance "for free".