The problem
This works:
fn foo<T>(param: &mut T) {}
fn foo_twice<T>(param: &mut T) {
foo(param);
foo(param);
}
This doesn't:
fn foo<T>(param: Pin<&mut T>) {}
fn foo_twice<T>(param: Pin<&mut T>) {
foo(param);
foo(param);
}
That's a problem.
Why this should be a priority
The language and library teams want to stabilize AsyncIterator within the next few months. Ideally, convenience methods like next() should soon follow. For maximum flexibility, these methods should take Pin<&mut Self>. But if Pin<&mut Self> is painful to use, that defeats the whole purpose of convenience methods!
Prior work
RFC 2364 (postponed) proposed to formalize a Reborrow trait. But the definition of the trait had a problem:
We introduce the following trait, as member of
std::marker:trait Reborrow { fn reborrow(&self) -> ???; }Unfortunately the return type of
fn reborrowisn't representable in general; the return type must beSelfbut with different lifetime(s) (and note that there will be multiple lifetimes if the type has multiple fields with lifetimes). It is not possible to use an associated typetype Result: ???because the return type includes a lifetime (or multiple) bound by the caller.
Let's try again.
Reborrow take 2
EDIT: see new design here
Signature
Here's the definition of Reborrow:
#[lang = "reborrow"]
#[marker]
pub trait Reborrow {}
impl<T: Copy + ?Sized> Reborrow for T { }
impl<'a, T: ?Sized> Reborrow for &'a mut T { }
And here's the new definition of Copy:
#[lang = "copy"]
#[marker]
pub trait Copy: Clone + Reborrow { }
Just as with Copy:
- A type can implement
Reborrowiff the types of all its fields implement it. - There is a built-in
derivemacro for implementingReborrow. Reborrowtypes cannot also beDrop.
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
SubimplementsReborrowbut notCopy,argis inaccessible only untilSuper's lifetime ends.
That is all.
Wait, how do you reborrow Wrapper<&mut T> as Wrapper<&T> with this proposal?
You don't
. At least, not until &mut T becomes a subtype of &T. But that's a problem for another day…