Skip to content

Tracking Issue for Reborrow trait lang experiment #145612

Open

Description

@aapoalas

This is a tracking issue for the lang experiment into a Reborrow trait and its dual CoerceShared trait.
The feature gate for the issue is #![feature(reborrow)].

For more information, see rust-lang/goals#399.

About tracking issues

Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Discussion comments will get marked as off-topic or deleted.
Repeated discussions on the tracking issue may lead to the tracking issue getting locked.

Steps

  • Land a feature gate, and possibly an empty trait.
  • Land an empty Reborrow trait.
  • Land an empty CoerceShared trait.
  • Land a test battery for basic Reborrow trait usage.
  • Land a test battery for basic CoerceShared trait usage
  • Land a test battery for complex Reborrow trait usage.
  • Land a test battery for complex CoerceShared trait usage.
  • Implement the Reborrow trait internals (probably a rustc builtin macro)
  • Implement the CoerceShared trait internals (ditto)
  • Start the RFC process based on the learnings

Unresolved Questions

The implementation of the Reborrow trait is likely something like this:

struct Example<'a, 'b> {
  a: A<'a>,
  b: B<'b>
}

fn reborrow(e: Example) {
  let Example { a, b } = e;
  reborrow(Example { a, b });
}

This allows the compiler to see the individual field usages and, eventually, enables the correct lifetimes to be "used as exclusive". But the question is; where does this bottom out? Is any field that implements Reborrow (but not Copy, if Reborrow is blanket-implemented for Copy types) a point where the recursion into structs stops? That stops composing of reborrowable types to a depth of 2. Is a PhantomReborrowable<'a> marker type needed? If so, then what is the variance of the lifetime there?

Implementation history

Activity

  1. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Aug 19, 2025
  2. added
    I-lang-nominatedNominated for discussion during a lang team meeting.
    B-experimentalBlocker: In-tree experiment; RFC pending, not yet approved or unneeded (requires FCP to stabilize).
    F-reborrow`#![feature(reborrow)]`; see #145612
    on Aug 19, 2025
  3. moved this to Exploration in Lang team featureson Aug 19, 2025
  4. added
    P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang
    on Aug 20, 2025
  5. joshtriplett commented on Aug 20, 2025

    @joshtriplett
    Member

    👍 for a lang experiment here.

  6. added
    P-lang-drag-2Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang.
    T-langRelevant to the language team
    I-lang-radarItems that are on lang's radar and will need eventual work or consideration.
    and removed
    P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang
    on Aug 20, 2025
  7. tmandry commented on Aug 21, 2025

    @tmandry
    Member

    I'm happy to champion this.

  8. added 2 commits that reference this issue on Aug 22, 2025
  9. 28 remaining items

  10. tvsfx commented on Jul 8, 2026

    @tvsfx

    Is supporting Reborrow/CoerceShared for method receivers without UFCS just a matter of doing the implementation work? I was just playing with the implementation on current nightly and noticed that I need UFCS to make code like this work:

    struct Foo<'a>(PhantomData<&'a ()>);
    #[derive(Clone, Copy)]
    struct FooRef<'a>(PhantomData<&'a ()>);
    
    impl FooRef<'_> {
        fn eat_foo_ref(self) {
        }
    }
    
    impl Foo<'_> {
        fn eat_foo(self) {
        }
    }
    
    impl<'a> Reborrow for Foo<'a> {}
    
    impl<'a> CoerceShared<FooRef<'a>> for Foo<'a> {}
    
    fn main() {
        let x = Foo(PhantomData);
        
        let _works = (<Foo>::eat_foo(x), <FooRef>::eat_foo_ref(x));
        // let _coerce_shared_does_not_work = x.eat_foo_ref();
        // let _reborrow_does_not_work = (x.eat_foo(), <FooRef>::eat_foo_ref(x));
    }

    But I cannot find any mention of this not working.

    https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=a573cbc6ecc099044f89f98b0b958f0f

  11. aapoalas commented on Jul 8, 2026

    @aapoalas
    ContributorAuthor

    Is supporting Reborrow/CoerceShared for method receivers without UFCS just a matter of doing the implementation work? I was just playing with the implementation on current nightly and noticed that I need UFCS to make code like this work:

    We haven't really gotten around to looking at this side of the equation yet - so far the compiler only inserts Reborrow/CoerceShared at assignment locations, but the method call location is not one. This ties in with #44874 and might (or probably will) affect the method resolution algorithm, which is a bit of a ... complication. As such, unfortunately for now this is unsupported.

    If you're interested in looking into this, I'd be happy to help (with what meager knowledge I have)!

  12. added a commit that references this issue on Jul 21, 2026
  13. added a commit that references this issue on Aug 11, 2026
  14. added a commit that references this issue on Aug 11, 2026
  15. Jules-Bertholet commented on Sep 29, 2026

    @Jules-Bertholet
    Contributor

    #145612 (comment)

    Is supporting Reborrow/CoerceShared for method receivers without UFCS just a matter of doing the implementation work? […]

    My PR #163494 partially fixes this—it ensures that a method call on a Reborrow type performs a reborrow.

  16. added 4 commits that reference this issue on Sep 30, 2026
  17. added a commit that references this issue on Oct 1, 2026
  18. added a commit that references this issue on Oct 1, 2026
  19. added a commit that references this issue on Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    B-experimentalBlocker: In-tree experiment; RFC pending, not yet approved or unneeded (requires FCP to stabilize).C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-reborrow`#![feature(reborrow)]`; see #145612I-lang-radarItems that are on lang's radar and will need eventual work or consideration.T-langRelevant to the language team

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions