Reborrow trait

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"]
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 implement Reborrow<'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 implements Copy, arg remains fully accessible.
  • If Sub implements neither Copy nor Reborrow, arg is permanently inaccessible.
  • New: if Sub implements Reborrow (lifetime does not matter) but not Copy, and Super: 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".