# \[Pre-RFC\] Reborrow trait

**URL:** <https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972>\
**Category:** language design\
**Created:** [May 22, 2025, 1:09pm UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972 "2025-05-22T13:09:24Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 27, 2025, 2:14am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/21 "2025-05-27T02:14:42Z")

</div>

If you don't mind / want me to do a full editing / rewrite pass for readability, I can and am willing to do so, if you ask. I wouldn't do that without prompting, though; that's too close to being intellectual theft\[1\].

Although, as a disclaimer, I'd end up rewriting pretty much everything into my voice instead of preserving yours, for my own convenience. ~~(I'm _capable_ of copyediting that isn't a content rewrite, but I don't do that for free generally, it takes too much effort.)~~

* * *

1. Although one allowable by an assumed MIT OR APACHE-2.0 license, given attribution.

---

<div class="post-metadata">

**Author:** ![aapoalas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aapoalas/32/12492_2.png) [@aapoalas](https://internals.rust-lang.org/u/aapoalas)\
**Post date:** [May 27, 2025, 4:49am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/22 "2025-05-27T04:49:40Z")

</div>

If you're willing to go that far, I absolutely will not say no! Of course, I'm the biggest fan of my own voice\[1\] but I'm an even bigger fan of the idea of having a Reborrow RFC accepted and implemented\[2\].

Some notes on the current draft that I think are worth considering:

1. As currently devised, the `Reborrow` and `CoerceShared` both look and feel very much like derive-traits. Maybe they should be proposed as such?
2. The current formulation allows `Reborrow + CoerceShared: Clone + !Copy + !Drop` types and would not call their `Clone` impl on reborrow. This seems weird; why does reborrowing disable the value temporarily, but you're free to `Clone` it to get an extra copy? Could we somehow force the "reborrowable typespace" into two distinct halves: `Copy` and `!Clone`?
3. An alternative to the proposed logic for finding the "terminal" or "leaf" reborrowable (as opposed to `Copy`) fields in a reborrowable struct would be the `PhantomExclusive` and `PhantomShared` marker types I mentioned above. This is a "stronger" definition in the sense that it can define `&mut` and `&`, whereas the current draft's definition implicitly relies on `PhantomData<&()>` kind of fields taking care of holding the lifetime.
4. There are some places where I might still be talking about lifetime narrowing, which is of course wrong. True reborrowing doesn't narrow the lifetime, eg. in `&mut T -> &mut T` both references have the same lifetime. It's just the implied, "outer" `'a` in `'a &mut T` that is a different, smaller one on the right side.
5. I did not fully think out the method resolution algorithm and where to slot `CoerceShared` into it. There's probably an interaction with `Deref`, and maybe even with `DerefMut`, that we'd want to get but might not be there right now. eg. maybe we'd want `Mut<'_, T>` to automatically coerce itself into `Mut<'_, U>` through a `DerefMut` chain of `Mut<T> -> Mut<U>`\[3\]? And the same for `Deref` chaining from `Mut<T>` or `Ref<T>` to `Ref<U>`.

* * *

1. Honestly, why do I re-read my own blog posts and re-watch my own talks so frequently? It doesn't seem normal or healthy. 

2. I've been looking into the rustc code a little so that I could start at least a basic implementation scaffold for it, maybe to go with the RFC. I don't plan on just getting the RFC accepted and then waiting on my laurels for someone else to do the compiler work; pair programming would be ideal. 

3. This would probably appear from to have a blanket `DerefMut<Target = Mut<U>> for Mut<T>` where `T: DerefMut<Target = U>`.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 27, 2025, 4:53am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/23 "2025-05-27T04:53:49Z")

</div>

> [@aapoalas](#):
>
> The correct formulation for transitive reborrowing is then this: for each field in the reborrowed type that is `!Copy`, recurse into the type and check if it has any `!Copy` fields. If it does, recurse into it. If not, then mark that field used.

The way you've explained this seems overly complicated. It's _almost_ equivalent to:

> To **transitive-reborrow** a place, for each direct subplace:
> 
> - If the type of that subplace implements `Copy`, mark it as borrowed. (By-`mut` for `Reborrow`, by-`ref` for `CoerceShared`).
> - Otherwise, **transitive-reborrow** the subplace.
> 
> If there are no subplaces, mark the entire place as borrowed.

But this feels _really_ odd. Essentially, we mark all types as borrowed, except we do so fieldwise? Plus, there's the exception for the top-level, e.g.:

> [@aapoalas](#):
>
> The important bit there is that the resulting `scope` should not keep the original `source` used at all.

So… IIUC, if I have `struct A(());` and reborrow a place `a: A`, then `a` is marked as borrowed, because all of its fields impl `Copy`. If I have `struct B { a: A, b: () }` and reborrow a place `b: B`, we _ignore_ `b.b` and borrow `b.a.0`. Then for `struct C { b: B }`, we borrow `c.b.a.0` _and_ `c.b.b`.

_Whatever_ the reborrowing algorithm is, it should be compositional; reborrowing a type _should_ be equivalent to reborrowing (or copying) its fields. The special case for a type with mixed `Copy` and non-`Copy` fields only at the top level is extremely odd.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 27, 2025, 4:56am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/24 "2025-05-27T04:56:58Z")

</div>

> [@aapoalas](#):
>
> The current formulation allows `Reborrow + CoerceShared: Clone + !Copy + !Drop` types and would not call their `Clone` impl on reborrow.

FWIW, this is also an issue with `Copy` — copying a value does not clone it. And there's technically-unsound specialization in the compiler because of this: e.g. when you `Clone` a `Vec`, it'll `Copy` its contents if it can, not `Clone` them.

---

<div class="post-metadata">

**Author:** ![aapoalas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aapoalas/32/12492_2.png) [@aapoalas](https://internals.rust-lang.org/u/aapoalas)\
**Post date:** [May 27, 2025, 5:14am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/25 "2025-05-27T05:14:44Z")

</div>

Mmm, I at least did not intend to write a top-level-only special case. The algorithm in the reference level explanation should be fully independent of the "level" it's on. And it was my intention that the special case of mixed `Copy` and non-`Copy` fields works on any level of the struct, no matter how shallow or deep.

What I intended with the "`scope` does not keep/mark original `source` used" and the algorithm was that reborrowing is a full FRU on the entire structure of the type being borrowed, recursively. This means that "higher levels" of a deep type structure are created from individual fields, and only the deepest levels actually "borrow" / reborrow from the source struct. eg. with the struct `C` there we'd perform the memory level creation of the reborrowed `C` like so:

```rust
struct C {
  b: B {
    a: A(source.b.a.0),
    b: source.b.b,
  }
}

```

But if we write this in Rust today, it would of course not keep `source` used because both the fields that we refer to in `source` are just `()` and can be copied from the source. The intention of the algorithm is to find the fields of the source struct that need to be marked as used, even though we've simply copied `Copy` data out of them. In this case, assuming `A`, `B`, and `C` are all `!Copy`, then the only one marked as used would be `source.b.a`. We indeed effectively ignore `source.b.b` / do not mark `source.b` as used by the new `B` that we create, because the `()` field in it is not really something that reborrows anything.

Compare this to a hypothetical custom reborrowable Vec type made out of a `Mut: Reborrow + !Copy` of some kind:

```rust
struct Vec<'a, T> {
  ptr: Mut<'a, T>,
  len: usize,
  cap: usize,
}

```

When we reborrow this `Vec`, we only effectively reborrow the `ptr` field and just copy the rest. If we did also reborrow the other fields, and then proceeded to destructure the `Vec` into its component parts while dropping `ptr`, the remaining `len` and `cap` values should not keep the source `Vec` used. Not even if someone for some reason made the fields be custom `LifetimeUsize<'a>(usize, PhantomData<&usize>)` types that implement `Copy`.

---

<div class="post-metadata">

**Author:** ![aapoalas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aapoalas/32/12492_2.png) [@aapoalas](https://internals.rust-lang.org/u/aapoalas)\
**Post date:** [May 27, 2025, 5:18am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/26 "2025-05-27T05:18:28Z")

</div>

> [@CAD97](#):
>
> FWIW, this is also an issue with `Copy` — copying a value does not clone it. And there's technically-unsound specialization in the compiler because of this: e.g. when you `Clone` a `Vec`, it'll `Copy` its contents if it can, not `Clone` them.

I was more pondering about the weirdness around a custom exclusive reference type that is still `Clone`, and what that might mean. But maybe it's not a problem? Turning that `Mut<'_, T>` into a `&mut T` through eg. `DerefMut` would anyway require `unsafe {}`, and if your `Mut: Clone` then that `DerefMut` can trigger UB if you've made clones of the `Mut` but that's on your `DerefMut` impl's internal `unsafe {}` block. not on the `DerefMut` itself.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 30, 2025, 1:09am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/27 "2025-05-30T01:09:47Z")

</div>

> [@aapoalas](#):
>
> Mmm, I at least did not intend to write a top-level-only special case. The algorithm in the reference level explanation should be fully independent of the "level" it's on.

The underlying issue, though, is that _every_ type is, at some level, made up of `Copy` data. Let's look at that example:

```rust
struct Vec<'a, T> {
    ptr: Mut<'a, T>,
    len: usize,
    cap: usize,
}

```

To reborrow `v: Vec`, we copy `v.len` and `v.cap` and reborrow `v.ptr`. Ok, so what is `Mut`?

```rust
struct Mut<'a, T> {
    ptr: NonNull<T>,
    _lt: PhantomCovariantLifetime<'a>,
}

```

To reborrow `m: Mut`, we… copy `m.ptr` and `m._lt`.

The only base case is to copy data. If we mark the source of a non-`Copy` reborrow as used, then reborrowing `v: Vec` marks `v` as used.

I _think_ your “if it has any `!Copy` fields” clause is supposed to be the base case; if a type has only `Copy` fields (but isn't itself `Copy`), instead of copying each field, we mark the entire place as used.

There's at least some logic to this special case, as it makes implementing `Copy` or not actually impact what a place-to-value conversion does. But it makes the operation feel strangely ad-hoc, because it isn't properly compositional anymore; reborrowing isn't just reborrowing each of the fields, like copying and moving each are.

Perhaps a possible resolution is to say that reborrowing reborrows the source place as a single unit by default, but when you derive `Reborrow` you can mark fields as `#[reborrow]`, in which case those fields are transitively reborrowed and the other fields are copied.

The other "clean" option I can think of is a lang item wrapper type which doesn't get recursed through for the purpose of reborrowing. But that feels like the wrong default to me.

Another more involved resolution could be to make decisions based on what field(s) capture a lifetime parameter? If any `Copy` fields capture a lifetime, mark all fields that capture that lifetime as used, and recurse on any fields that don't capture such a lifetime. The reborrowing operation _is_ fundamentally tied to the concept of lifetimes, after all.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [June 5, 2025, 2:30am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/28 "2025-06-05T02:30:25Z")

</div>

> [@aapoalas](#):
>
> If you're willing to [rewrite the RFC], I absolutely will not say no!

FYI I'm still thinking about and planning to do this, I'm just passively trying to come up with (what I can see as being) a more “principled” way of handling the reborrowing semantics, or at least of explaining them.

I _think_ basing it on lifetime capture works as we want it to. But the tricky part to principlize _is_ the ability for shared reborrows. I'll use the [polonius method of discussing _regions_ and _loans_ here](https://smallcultfollowing.com/babysteps/blog/2018/04/27/an-alias-based-formulation-of-the-borrow-checker/).

First, we need to determine what exactly a reborrow of `&mut` looks like. `x: &'a mut i32` captures a single lifetime. As this region parameter is covariant, the place to value operation for `x` loads a value of type `&'b mut i32` where `'a <: 'b`\[1\]. For a simple place to value, `x` is moved from and whether this covariance actually applies is unobservable, as any attempt to do so adds a new site for the variance to be applied. Coercion

For a simple place to value, `x` is moved from and uninitialized, and while `'b` is _allowed_ to contain a larger set of loans\[2\], no new loans are naturally introduced. When this conversion is done at a coercion site\[3\], however, things get a bit more interesting, or when reborrowing is done manually.

```rust
error[E0382]: use of moved value: `x`
 --> src/lib.rs:3:5
  |
1 | pub fn f(x: &mut i32) -> &mut i32 {
  | - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
2 | let out = x;
  | - value moved here
3 | *x;
  | ^^ value used here after move

error[E0503]: cannot use `*x` because it was mutably borrowed
 --> src/lib.rs:3:5
  |
1 | pub fn f<'a: 'b, 'b>(x: &'a mut i32) -> &'b mut i32 {
  | -- lifetime `'b` defined here
2 | let out = &mut *x;
  | ------- `*x` is borrowed here
3 | *x;
  | ^^ use of borrowed `*x`
4 | out
  | --- returning this value requires that `*x` is borrowed for `'b`

```

Unlike a move, `x` is not moved from, but instead, it's reborrowed. Critically to how reborrowing works, though, `x` itself isn't borrowed; the place `*x` is loaned. The region `b` requires all of `'a`'s loans to remain valid (`'a <: 'b`), as well as requiring that (as it's a mutable reborrow) `*x` remain unreferenced.

If `'b`'s loans reference `x`, then, how come `out` can be returned from the function without referencing any function local values/temporaries (`'b <: fn`)? It's actually quite simple: `'b` doesn't care about the `x` place expiring, just that the place accessed at `*x` isn't inspected in a way that invalidates the mut loan. Most uses of `x` are considered as invalidating the loan of `*x` immediately, _but not all_:

```rust
pub fn f<'a>(mut x: &'a mut i32, y: &'a mut i32) -> &'a mut i32 {
    let out = &mut *x;
    x = y;
    out
}

```

For a principled approach using the existing borrow region language and framework, I think we want a lang type `PhantomMut<'a>` which acts like `&mut ()` except that it's zero sized. Then reborrowing can just work with loans on `*p`. The other alternative is to allow loans to block place reads but not writes as a "first class" concept (instead of derived from not allowing dereference of that place's current value) and utilize that… but we'd still need some avenue to distinguish copied fields from reborrowed fields at the base case. And "if all fields are `Copy`, reborrow them" just doesn't feel like a principled solution\[4\].

(In effect, compiler messages don't ever say "`x` is reborrowed," they say "`*x` is borrowed.")

Then the final wrinkle is that this adds new hidden inferred type-level distinctions between type lifetime parameters, similar to variance and implied bounds. Unlike those, however, the effect is restricted to opt in via `impl Reborrow`, so shouldn't be that big of a deal imo. But how it interacts with privacy, and in particular for types with only partially public fields, isn't straightforward. It's purely restrictions that API could already imply, IIUC, but it should still be noted.

* * *

1. This notation means the same as `'a: 'b` in Rust source code, but it emphasizes the subset-equal relation. Specifically, a _region_ `'a` is a set of _loans_ where invalidating any of the loans that a value captures in its region parameters invalidates the value. As the `b` lifetime has a superset of _restrictions_, invalidating `'a` must invalidate `'b`, but invalidating `'b` may not invalidate `'a`, thus we can say colloquially that `'a` "outlives" `'b`.

2. It might if, for example, unifying `'b` with some other lifetime(s), in which case the region with (at least) the union of the sets of loans is selected. 

3. Caveat: if the mutable reference is covered by a generic (e.g. `std::convert::identity(x)`), then `x` is _not_ at a conversion site. However, if the mutable reference is _not_ fully contained in a generic type inference variable _at the use site_ (e.g. `identity::<&mut _>(x)`), then it _is_ a valid coercion site.

4. Yes, if you want all fields to be copied, you can and should impl `Copy` instead of just `Reborrow`. But it's weird for reborrow to be a mostly structural operation except for one special case. Plus then there's the possibility of polonius or some other smarter borrow checking that's more control flow sensitive refining how precise local borrowck is beyond today's NLL (e.g. `&x` but known to only access `x.field`, i.e. implicit local borrow splitting), so framing user type reborrowing in working terms of phantom places is more useful to future work. Instead of baking in exactly how reborrows currently function.

---

<div class="post-metadata">

**Author:** ![aapoalas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aapoalas/32/12492_2.png) [@aapoalas](https://internals.rust-lang.org/u/aapoalas)\
**Post date:** [June 9, 2025, 9:00am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/29 "2025-06-09T09:00:30Z")

</div>

Hi, sorry it's taken me a bit of time to get back here. I was traveling for a week.

```quote
I think your “if it has any !Copy fields” clause is supposed to be the base case; if a type has only Copy fields (but isn't itself Copy), instead of copying each field, we mark the entire place as used.

```

Yeah, I think this is what I was at least trying to say. A reborrowable type that is internally fully Copy but is not itself `!Copy` should mark its "reborrow source" as used for the duration of the reborrow result's lifetime (existence, not the captured lifetime).

So when reborrowing `Vec` we find a field that is not `!Copy`; ie. the `Vec` itself will not get marked as used. We recurse into the `ptr: Mut` field and that type is made out of fully `Copy` fields so we mark the `vec.ptr` as used.

I'm not sure if this makes the operation not-compositional, though. Any `Mut` field in any type will always be marked as used on reborrow since its internals will always all be `Copy` (generics could change that though). The only "non-compositional" part is that any type's reborrowing logic is dependent on its field types in a sort of "boolean or" sort of way, maybe?

I'd argue that something like a `#[reborrow]` trait would make things less compositional, as then you could have two types `Vec` and `Vec2` where in one case `Mut` is recursed into and in another it isn't.

Regarding lifetime capture, I am very interested in figuring out if we could make that work as the basis of the reborrow. I'm just wondering about my use-case example of `GcScope<'a, 'b>` where `'a` is an exclusive lifetime and `'b` is a shared lifetime. Since `GcScope` wouldn't be `Copy`, we'd have to recurse into the type to separate the two lifetimes from one another. But then inside of it, the two lifetimes are currently both captured by `PhantomData: Copy` fields: how do we now figure out that the field carrying `'a` should be marked as used and `'b` should be left unused.

Note: I think your

```quote
If any Copy fields capture a lifetime, mark all fields that capture that lifetime as used, and recurse on any fields that don't capture such a lifetime.

```

is the wrong way around: reborrowing `&'a T` is just a copy and should not mark the original reference as used (disabled for reads and writes). Capturing a lifetime on a field that is `!Copy` is the interesting case, ie. `&'a mut T`.

> [@CAD97](#):
>
> First, we need to determine what exactly a reborrow of `&mut` looks like.

I'm not sure that thinking of a `'a <: 'b` lifetime "subset-equal" relation is useful here. AFAIU, rustc does not perform any lifetime subsetting during reborrowing, so trying to introduce such an operation is just reference-level fiction that leads one astray. The `'a` in `&'a mut T` is effectively the lifetime of the `T` anyways, the validity of the data or as you and the compiler puts it, a borrow on `T`. Reborrowing `&mut T` never changes that validity.

I prefer thinking of the reference type's "owned lifetime" (capitalised here for effect), so eg. `let original: 'A &'a mut T`; this is the same exclusive reference to `T` as before where `T` is valid for `'a`, but the exclusive reference is valid for `'A`. Reborrowing this creates a new exclusive reference `let derived: 'B &'a mut T` where `'A <: 'B`, and the `original` gets disabled for the lifetime `'B`.

Conceptually I think of this as the same as `let original: Vec<T>;` and `let derived = original;`, ie. a move, just with a "return move" happening automatically when `derived` is dropped: the value we're acting upon here is a move-only value, and it happens to hold within it an exclusive reference to data that is valid for some duration of time. Moving the value doesn't change validity of the data.

But, of course this is all the same stuff as you're saying as well, just in different words and perhaps a slightly different viewpoint.

> [@CAD97](#):
>
> For a principled approach using the existing borrow region language and framework, I think we want a lang type `PhantomMut<'a>` which acts like `&mut ()` except that it's zero sized.

This may indeed be the best choice; this is then the `PhantomExclusive` and `PhantomShared` that I suggested earlier. The hidden type-level distinction on lifetimes is definitely a pain, but luckily it's a pain that already somewhat exists in the compiler (with exclusive references and Pin reborrowing), so maybe it's not that bad?

Regarding privacy, my immediate thought is that reborrowing does not relate to field publicity at all. Implementing Reborrow for a type can only be done in the crate that defines said type, so all of its fields can (conceptually) be accessed by the reborrow action. The compiler of course also sees all the fields and cares not one whit about the publicity of the fields. In my `GcScope<'a, 'b>` case none of the fields are public to users, but reborrowing the type should still work equally well. Even if the fields were public and users could eg. destructure the `GcScope<'a, 'b>` into `Gc<'a>` and `Scope<'b>`, the reborrowing should still work the same.

As for destructuring a type that has some private reborrowed fields and some public reborrowed or copy fields, the public reborrowed fields of course stay alive past the destructuring while the private fields effectively drop at the destructuring site. Or so I'd expect things to work.

---

<div class="post-metadata">

**Author:** ![unknownMusician](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/unknownmusician/32/14421_2.png) [@unknownMusician](https://internals.rust-lang.org/u/unknownMusician)\
**Post date:** [June 24, 2026, 11:44am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/30 "2026-06-24T11:44:51Z")

</div>

Hey, I hope you're doing well. I was playing with the ideas of reborrowing and I want to share here what I have found.

I think that reborrowing is a temporary "borrowing" of the same value for a short(-er) action with the borrowed data without consuming it - blocking a previous lifetime while the new one exists. Such behavior is already implemented for the rust references. If the reference is "borrowed" for a short time, the original reference is temporarily blocked and a new lifetime is created by covariance.

I assume that the types that can benefit from the reborrow feature are non-static types. And non-static types contain fields of references or fields of another non-static types - that's where they take their lifetime from (even the artificial lifetimes from PhantomData - they can be treated as standard non-static types).

So in the root of lifetimes reborrowing lie shared and mutable references - all the other types depend on them.

So I suggest using lifetimes covariance as a core instrument of the Reborrowing. Thus, I have implemented a suggested Reborrow and ReborrowMut traits sugnature, default impls and an example for custom non-static types that use the reborrow traits.

The use-case is sound as of the latest available rust version. The feature only makes the compiler inject the `reborrow()` and `reborrow_mut` calls where applicable. (well, it also provides is the traits, default impls and macros, but these are a lot easier to implement, I think).

```rs
// traits

trait Reborrow<'a>: 'a {
    type Reborrowed<'r> where 'a: 'r;

    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r>;
}

trait ReborrowMut<'a>: 'a {
    type Reborrowed<'r> where 'a: 'r;

    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r>;
}

// Default impls

impl<'a, T> Reborrow<'a> for &'a T {
    type Reborrowed<'r> = &'r T where 'a: 'r;

    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r> {
        self
    }
}

impl<'a, T> ReborrowMut<'a> for &'a T {
    type Reborrowed<'r> = &'r T where 'a: 'r;

    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r> {
        self
    }
}

impl<'a, T> Reborrow<'a> for &'a mut T {
    type Reborrowed<'r> = &'r T where 'a: 'r;

    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r> {
        self
    }
}

impl<'a, T> ReborrowMut<'a> for &'a mut T {
    type Reborrowed<'r> = &'r T where 'a: 'r;

    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r> {
        self
    }
}

impl<'a, T> Reborrow<'a> for Option<&'a T> {
    type Reborrowed<'r> = Option<&'r T> where 'a: 'r;

    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r> {
        match self {
            None => None,
            Some(val) => Some(val),
        }
    }
}

impl<'a, T> ReborrowMut<'a> for Option<&'a T> {
    type Reborrowed<'r> = Option<&'r T> where 'a: 'r;

    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r> {
        match self {
            None => None,
            Some(val) => Some(val),
        }
    }
}

impl<'a, T> Reborrow<'a> for Option<&'a mut T> {
    type Reborrowed<'r> = Option<&'r T> where 'a: 'r;

    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r> {
        match self {
            None => None,
            Some(val) => Some(val),
        }
    }
}

impl<'a, T> ReborrowMut<'a> for Option<&'a mut T> {
    type Reborrowed<'r> = Option<&'r mut T> where 'a: 'r;

    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r> {
        match self {
            None => None,
            Some(val) => Some(val),
        }
    }
}

// Example

fn main() {
    let mut num = 0;
    
    let mut custom_mut = CustomMut::new(&mut num);
    
    // compiler-inserted `reborrow_mut()`
    custom_mut.reborrow_mut().increment();
    // compiler-inserted `reborrow_mut()`
    custom_mut.reborrow_mut().increment();
    // compiler-inserted `reborrow()`
    custom_mut.reborrow().print();
    // no need for the reborrow, because the value can be moved.
    // (the same logic as with the Copy trait).
    custom_mut.increment();

    
    println!("{num}");
}

struct CustomMut<'a> {
    num: &'a mut i32,
}

impl<'a> CustomMut<'a> {
    pub fn new(num: &'a mut i32) -> Self {
        Self {
            num,
        }
    }

    pub fn increment(self) {
        *self.num += 1;
    }
}

#[derive(Copy, Clone)]
struct CustomRef<'a> {
    num: &'a i32,
}

impl<'a> CustomRef<'a> {
    pub fn new(num: &'a i32) -> Self {
        Self {
            num,
        }
    }

    pub fn print(self) {
        println!("Custom: {}", self.num);
    }
}

impl<'a> Reborrow<'a> for CustomMut<'a> {
    type Reborrowed<'r> = CustomRef<'r> where 'a: 'r;
    
    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r> {
        CustomRef {
            num: self.num,
        }
    }
}

impl<'a> ReborrowMut<'a> for CustomMut<'a> {
    type Reborrowed<'r> = CustomMut<'r> where 'a: 'r;
    
    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r> {
        CustomMut {
            num: self.num,
        }
    }
}

impl<'a> Reborrow<'a> for CustomRef<'a> {
    type Reborrowed<'r> = CustomRef<'r> where 'a: 'r;
    
    fn reborrow<'r>(&'r self) -> Self::Reborrowed<'r> {
        CustomRef {
            num: self.num,
        }
    }
}

impl<'a> ReborrowMut<'a> for CustomRef<'a> {
    type Reborrowed<'r> = CustomRef<'r> where 'a: 'r;
    
    fn reborrow_mut<'r>(&'r mut self) -> Self::Reborrowed<'r> {
        CustomRef {
            num: self.num,
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![aapoalas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aapoalas/32/12492_2.png) [@aapoalas](https://internals.rust-lang.org/u/aapoalas)\
**Post date:** [July 19, 2026, 10:03am UTC](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972/31 "2026-07-19T10:03:01Z")

</div>

This is indeed roughly the standard "user-space reborrowing" formulation, see f.ex. the [reborrow crate](https://crates.io/crates/reborrow).

It's a fine enough formulation for a library, but it does not capture the same thing that actual `&mut T` reborrowing does. Compare these two snippets of code.

```rust
fn reborrow(a: &mut ()) -> &mut () {
  let b = &mut *a; // this is forced reborrowing
  b
}

```

```rust
fn reborrow(a: CustomMut) -> CustomMut {
  let b = a.reborrow_mut(); // again force reborrowing
  b
}

```

The first one compiles, the second one doesn't. Why? Because the `reborrow_mut` captures a local variable `a`'s address, ie. it captures a pointer to the stack as reference (or from a lifetime perspective it is allowed to do so). Returning that reference from the function would allow the caller to read the stack data from safe Rust, but since the stack has already been torn down at the end of the `fn reborrow` function that would be reading uninitialised memory. That would be UB in safe Rust, a big no-no.

Hence, the usual library formulation of reborrowing cannot be used as the starting point for generic reborrowing as a language feature.

[Previous page](https://internals.rust-lang.org/t/pre-rfc-reborrow-trait/22972.md?page=1)
