Skip to content

Tracking issue for RFC 3519: arbitrary_self_types #44874

Open

Description

@arielb1

View all comments

This is the tracking issue for RFC 3519: Arbitrary self types v2.

The feature gate for this issue is #![feature(arbitrary_self_types)].

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.

Steps

Current plan is:

Unresolved Questions

None.

Notable for Stabilization

Related

Implementation history


(Below follows content that predated the accepted Arbitrary Self Types v2 RFC.)

Details
  • figure out the object safety situation
  • figure out the handling of inference variables behind raw pointers
  • decide whether we want safe virtual raw pointer methods

Object Safety

See #27941 (comment)

Handling of inference variables

Calling a method on *const _ could now pick impls of the form

impl RandomType {
    fn foo(*const Self) {}
}

Because method dispatch wants to be "limited", this won't really work, and as with the existing situation on &_ we should be emitting an "the type of this value must be known in this context" error.

This feels like fairly standard inference breakage, but we need to check the impact of this before proceeding.

Safe virtual raw pointer methods

e.g. this is UB, so we might want to force the call <dyn Foo as Foo>::bar to be unsafe somehow - e.g. by not allowing dyn Foo to be object safe unless bar was an unsafe fn

trait Foo {
    fn bar(self: *const Self);
}

fn main() {
    // creates a raw pointer with a garbage vtable
    let foo: *const dyn Foo = unsafe { mem::transmute([0usize, 0x1000usize]) };
    // and call it
    foo.bar(); // this is UB
}

However, even today you could UB in safe code with mem::size_of_val(foo) on the above code, so this might not be actually a problem.

More information

There's no reason the self syntax has to be restricted to &T, &mut T and Box<T>, we should allow for more types there, e.g.

trait MyStuff {
    fn do_async_task(self: Rc<Self>);
}

impl MyStuff for () {
    fn do_async_task(self: Rc<Self>) {
        // ...
    }
}

Rc::new(()).do_async_stuff();

Activity

  1. changed the title [-]Allow methods with arbitrary self-types[/-] [+]Allow trait methods with arbitrary self-types[/+] on Sep 26, 2017
  2. added
    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
    on Sep 28, 2017
  3. porky11 commented on Sep 28, 2017

    @porky11

    Why would you need this?
    Why wouldn't you write an impl like this:

    impl MyStuff for Rc<()> {
        fn do_async_task(self) {
            // ...
        }
    }
    

    I'd rather define the trait different. Maybe like this:

    trait MyStuff: Rc {
        fn do_async_task(self);
    }
    

    In this case, Rc would be a trait type. If every generic type implemented a specific trait (this could be implemented automatically for generic types) this seems more understandable to me.

  4. cuviper commented on Sep 28, 2017

    @cuviper
    Member

    This could only be allowed for trait methods, right?

    For inherent methods, I can't impl Rc<MyType>, but if impl MyType can add methods with self: Rc<Self>, it seems like that would enable weird method shadowing.

  5. arielb1 commented on Oct 1, 2017

    @arielb1
    ContributorAuthor

    @cuviper

    This is still pending lang team decisions (I hope there will be at least 1 RFC) but I think it will only be allowed for trait method impls.

  6. arielb1 commented on Oct 1, 2017

    @arielb1
    ContributorAuthor

    @porky11

    You can't implement anything for Rc<YourType> from a crate that does not own the trait.

  7. arielb1 commented on Oct 2, 2017

    @arielb1
    ContributorAuthor

    So changes needed:

    • remove the current error message for trait methods only, but still have a feature gate.
    • make sure fn(self: Rc<Self>) doesn't accidentally become object-safe
    • make sure method dispatch woks for Rc<Self> methods
    • add tests
  8. added
    E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
    and removed on Oct 2, 2017
  9. SimonSapin commented on Oct 2, 2017

    @SimonSapin
    Contributor

    I’ll look into this.

  10. arielb1 commented on Oct 2, 2017

    @arielb1
    ContributorAuthor

    Note that this is only supported to work with trait methods (and trait impl methods), aka

    trait Foo {
        fn foo(self: Rc<Self>);
    }
    impl Foo for () {
        fn foo(self: Rc<Self>) {}
    }

    and is NOT supposed to work for inherent impl methods:

    struct Foo;
    impl Foo {
        fn foo(self: Rc<Self>) {}
    }
  11. SimonSapin commented on Oct 6, 2017

    @SimonSapin
    Contributor

    I got caught in some more Stylo work that's gonna take a while, so if someone else wants to work on this in the meantime feel free.

  12. kennytm commented on Oct 6, 2017

    @kennytm
    Member

    Is this supposed to allow any type as long as it involves Self? Or must it impl Deref<Target=Self>?

    trait MyStuff {
        fn a(self: Option<Self>);
        fn b(self: Result<Self, Self>);
        fn c(self: (Self, Self, Self));
        fn d(self: Box<Box<Self>>);
    }
    
    impl MyStuff for i32 {
       ...
    }
    
    Some(1).a();  // ok?
    Ok(2).b();  // ok?
    (3, 4, 5).c(); // ok?
    (box box 6).d(); // ok?
  13. 277 remaining items

  14. added a commit that references this issue on Mar 5, 2025
  15. added a commit that references this issue on Mar 5, 2025
  16. programmerjake commented on Aug 7, 2025

    @programmerjake
    Member

    There's a Zulip thread discussing if Deref and Receiver should be related at all via trait bounds or blanket impls. I now think they should be unrelated.

  17. programmerjake commented on Aug 26, 2025

    @programmerjake
  18. programmerjake commented on May 7, 2026

    @programmerjake
    Member

    we might have our first std user of this feature (rather than just being another Deref type): Simd<T, N>: Receiver<Target = T>

  19. clarfonthey commented on Oct 10, 2026

    @clarfonthey
    Contributor

    Before I just offer a PR to do this, is there anything particularly stopping us from adding Receiver impls for rc::Weak and sync::Weak?

    These seem perfectly in line with this RFC, and also cannot implement Deref.

  20. programmerjake commented on Oct 10, 2026

    @programmerjake
    Member

    26. Before I just offer a PR to do this, is there anything particularly stopping us from adding Receiver impls for rc::Weak and sync::Weak?
    These seem perfectly in line with this RFC, and also cannot implement Deref.

    like *mut T, they have a bunch of methods taking self, so those could conflict with user-provided methods

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-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.B-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-arbitrary_self_types`#![feature(arbitrary_self_types)]`S-tracking-needs-summaryStatus: It's hard to tell what's been done and what hasn't! Someone should do some investigation.S-types-deferredStatus: Identified as a valid potential future enhancement that is not currently being worked onT-langRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions