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 reborrow
isn't representable in general; the return type must beSelf
but 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
Reborrow
iff the types of all its fields implement it. - There is a built-in
derive
macro for implementingReborrow
. Reborrow
types 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
Sub
implementsCopy
,arg
remains fully accessible. - If
Sub
implements neitherCopy
norReborrow
,arg
is permanently inaccessible. - New: if
Sub
implementsReborrow
but notCopy
,arg
is 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…