Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for RFC 3519: arbitrary_self_types #44874

Open
5 of 15 tasks
Tracked by #165
arielb1 opened this issue Sep 26, 2017 · 132 comments
Open
5 of 15 tasks
Tracked by #165

Tracking issue for RFC 3519: arbitrary_self_types #44874

arielb1 opened this issue Sep 26, 2017 · 132 comments
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-arbitrary_self_types `#![feature(arbitrary_self_types)]` S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. S-types-deferred Status: Identified as a valid potential future enhancement that is not currently being worked on T-lang Relevant to the language team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@arielb1
Copy link
Contributor

arielb1 commented Sep 26, 2017

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:

  • Fix the current lifetime elision bugs
  • Search for potentially conflicting method candidates
  • Block generic arbitrary self types.
  • Introduce an arbitrary_self_types_pointers feature gate
  • Rename the old Receiver trait -- currently being run through crater
  • Land the new Receiver trait without it doing anything.
  • Switch over the method resolution to use the Receiver trait, if the arbitrary_self_types feature is enabled. The main event.
  • Add diagnostics for the !Sized case and the NonNull etc. cases.
  • Update the Rust reference.
  • Add documentation to the dev guide. See the instructions.
  • Add formatting for new syntax to the style guide. See the nightly style procedure.
  • Stabilize!

Unresolved Questions

None.

Related

Implementation history

TODO.


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

  • 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();
@arielb1 arielb1 changed the title Allow methods with arbitrary self-types Allow trait methods with arbitrary self-types Sep 26, 2017
@aidanhs aidanhs added the C-feature-request Category: A feature request, i.e: not implemented / a PR. label Sep 28, 2017
@porky11
Copy link

porky11 commented Sep 28, 2017

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.

@cuviper
Copy link
Member

cuviper commented Sep 28, 2017

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.

@arielb1
Copy link
Contributor Author

arielb1 commented Oct 1, 2017

@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.

@arielb1
Copy link
Contributor Author

arielb1 commented Oct 1, 2017

@porky11

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

@arielb1
Copy link
Contributor Author

arielb1 commented Oct 2, 2017

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

@arielb1 arielb1 added E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. and removed E-needs-mentor labels Oct 2, 2017
@SimonSapin
Copy link
Contributor

I’ll look into this.

@arielb1
Copy link
Contributor Author

arielb1 commented Oct 2, 2017

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>) {}
}

@SimonSapin
Copy link
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.

@kennytm
Copy link
Member

kennytm commented Oct 6, 2017

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?

kennytm added a commit to kennytm/rust that referenced this issue Oct 10, 2017
…ents, r=nikomatsakis

Update comments referring to old check_method_self_type

I was browsing the code base, trying to figure out how rust-lang#44874 could be implemented, and noticed some comments that were out of date and a bit misleading (`check_method_self_type` has since been renamed to `check_method_receiver`). Thought it would be an easy first contribution to Rust!
@mikeyhew
Copy link
Contributor

I've started working on this issue. You can see my progress on this branch

@mikeyhew
Copy link
Contributor

mikeyhew commented Nov 2, 2017

@arielb1 You seem adamant that this should only be allowed for traits and not structs. Aside from method shadowing, are there other concerns?

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 2, 2017

@mikeyhew

inherent impl methods are loaded based on the type. You shouldn't be able to add a method to Rc<YourType> that is usable without any use statement.

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 2, 2017

That's it, if you write something like

trait Foo {
    fn bar(self: Rc<Self>);
}

Then it can only be used if the trait Foo is in-scope. Even if you do something like fn baz(self: u32); that only works for modules that use the trait.

If you write an inherent impl, then it can be called without having the trait in-scope, which means we have to be more careful to not allow these sorts of things.

@mikeyhew
Copy link
Contributor

mikeyhew commented Nov 3, 2017

@arielb1 Can you give an example of what we want to avoid? I'm afraid I don't really see what the issue is. A method you define to take &self will still be callable on Rc<Self>, the same as if you define it to take self: Rc<Self>. And the latter only affectsRc<MyStruct>, not Rc<T> in general.

@mikeyhew
Copy link
Contributor

mikeyhew commented Nov 4, 2017

I've been trying to figure out how we can support dynamic dispatch with arbitrary self types. Basically we need a way to take a CustomPointer<Trait>, and do two things: (1) extract the vtable, so we can call the method, and (2) turn it into a CustomPointer<T> without knowing T.

(1) is pretty straightforward: call Deref::deref and extract the vtable from that. For (2), we'll effectively need to do the opposite of how unsized coercions are implemented for ADTs. We don't know T, but we can can coerce to CustomPointer<()>, assuming CustomPointer<()> has the same layout as CustomPointer<T> for all T: Sized. (Is that true?)

The tough question is, how do we get the type CustomPointer<()>? It looks simple in this case, but what if CustomPointer had multiple type parameters and we had a CustomPointer<Trait, Trait>? Which type parameter do we switch with ()? In the case of unsized coercions, it's easy, because the type to coerce to is given to us. Here, though, we're on our own.

@arielb1 @nikomatsakis any thoughts?

@nikomatsakis
Copy link
Contributor

@arielb1

and is NOT supposed to work for inherent impl methods:

Wait, why do you not want it work for inherent impl methods? Because of scoping? I'm confused. =)

@nikomatsakis
Copy link
Contributor

@mikeyhew

I've been trying to figure out how we can support dynamic dispatch with arbitrary self types.

I do want to support that, but I expected it to be out of scope for this first cut. That is, I expected that if a trait uses anything other than self, &self, &mut self, or self: Box<Self> it would be considered no longer object safe.

@mikeyhew
Copy link
Contributor

mikeyhew commented Nov 4, 2017

@nikomatsakis

I do want to support that, but I expected it to be out of scope for this first cut.

I know, but I couldn't help looking into it, it's all very interesting to me :)

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 5, 2017

Wait, why do you not want it work for inherent impl methods? Because of scoping? I'm confused. =)

We need some sort of "orphan rule" to at least prevent people from doing things like this:

struct Foo;
impl Foo {
    fn frobnicate<T>(self: Vec<T>, x: Self) { /* ... */ }
}

Because then every crate in the world can call my_vec.frobnicate(...); without importing anything, so if 2 crates do this there's a conflict when we link them together.

Maybe the best way to solve this would be to require self to be a "thin pointer to Self" in some way (we can't use Deref alone because it doesn't allow for raw pointers - but Deref + deref of raw pointers, or eventually an UnsafeDeref trait that reifies that - would be fine).

I think that if we have the deref-back requirement, there's no problem with allowing inherent methods - we just need to change inherent method search a bit to also look at defids of derefs. So that's probably a better idea than restricting to trait methods only.

Note that the CoerceSized restriction for object safety is orthogonal if we want allocators:

struct Foo;
impl Tr for Foo {
    fn frobnicate<A: Allocator+?Sized>(self: RcWithAllocator<Self, A>) { /* ... */ }
}

Where an RcWithAllocator<Self, A> can be converted to a doubly-fat RcWithAllocator<Tr, Allocator>.

@mikeyhew
Copy link
Contributor

mikeyhew commented Nov 5, 2017

@arielb1

Because then every crate in the world can call my_vec.frobnicate(...); without importing anything, so if 2 crates do this there's a conflict when we link them together.

Are saying is that there would be a "conflicting symbols for architechture x86_64..." linker error?

Maybe the best way to solve this would be to require self to be a "thin pointer to Self" in some way (we can't use Deref alone because it doesn't allow for raw pointers - but Deref + deref of raw pointers, or eventually an UnsafeDeref trait that reifies that - would be fine).

I'm confused, are you still talking about frobnicate here, or have you moved on to the vtable stuff?

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 5, 2017

I'm confused, are you still talking about frobnicate here, or have you moved on to the vtable stuff?

The deref-back requirement is supposed to be for everything, not only object-safety. It prevents the problem when one person does

struct MyType;
impl MyType {
    fn foo<T>(self: Vec<(MyType, T)>) { /* ... */ }
}   

While another person does

struct OurType;
impl OurType {
    fn foo<T>(self: Vec<(T, OurType)>) {/* ... */ }
}   

And now you have a conflict on Vec<(MyType, OurType)>. If you include the deref-back requirement, there is no problem with allowing inherent impls.

bors added a commit to rust-lang-ci/rust that referenced this issue Oct 23, 2024
CI: rfl: use rust-next temporary commit

Commit c95bbb59a9b22f9b838b15d28319185c1c884329 within rust-next contains some changes required to be compatible with upcoming arbitraty self types work. Roll RFL CI forward to the latest rust-next to include that work.

Related:
rust-lang#130225
rust-lang#44874

r? `@ojeda`
bors added a commit to rust-lang-ci/rust that referenced this issue Oct 23, 2024
CI: rfl: use rust-next temporary commit

Commit c95bbb59a9b22f9b838b15d28319185c1c884329 within rust-next contains some changes required to be compatible with upcoming arbitraty self types work. Roll RFL CI forward to the latest rust-next to include that work.

Related:
rust-lang#130225
rust-lang#44874

r? `@ojeda`

try-job: x86_64-rust-for-linux
fmease added a commit to fmease/rust that referenced this issue Oct 23, 2024
CI: rfl: use rust-next temporary commit

Commit c95bbb59a9b22f9b838b15d28319185c1c884329 within rust-next contains some changes required to be compatible with upcoming arbitraty self types work. Roll RFL CI forward to the latest rust-next to include that work.

Related:
rust-lang#130225
rust-lang#44874

r? `@ojeda`

try-job: x86_64-rust-for-linux
fmease added a commit to fmease/rust that referenced this issue Oct 23, 2024
CI: rfl: use rust-next temporary commit

Commit c95bbb59a9b22f9b838b15d28319185c1c884329 within rust-next contains some changes required to be compatible with upcoming arbitraty self types work. Roll RFL CI forward to the latest rust-next to include that work.

Related:
rust-lang#130225
rust-lang#44874

r? ``@ojeda``

try-job: x86_64-rust-for-linux
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 23, 2024
Rollup merge of rust-lang#132058 - adetaylor:use-rust-next-in-ci, r=lqd

CI: rfl: use rust-next temporary commit

Commit c95bbb59a9b22f9b838b15d28319185c1c884329 within rust-next contains some changes required to be compatible with upcoming arbitraty self types work. Roll RFL CI forward to the latest rust-next to include that work.

Related:
rust-lang#130225
rust-lang#44874

r? ``@ojeda``

try-job: x86_64-rust-for-linux
Zalathar added a commit to Zalathar/rust that referenced this issue Oct 24, 2024
…esleywiser

Rename Receiver -> LegacyReceiver

As part of the "arbitrary self types v2" project, we are going to replace the current `Receiver` trait with a new mechanism based on a new, different `Receiver` trait.

This PR renames the old trait to get it out the way. Naming is hard. Options considered included:
* HardCodedReceiver (because it should only be used for things in the standard library, and hence is sort-of hard coded)
* LegacyReceiver
* TargetLessReceiver
* OldReceiver

These are all bad names, but fortunately this will be temporary. Assuming the new mechanism proceeds to stabilization as intended, the legacy trait will be removed altogether.

Although we expect this trait to be used only in the standard library, we suspect it may be in use elsehwere, so we're landing this change separately to identify any surprising breakages.

It's known that this trait is used within the Rust for Linux project; a patch is in progress to remove their dependency.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? `@wesleywiser`
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 24, 2024
Rollup merge of rust-lang#130225 - adetaylor:rename-old-receiver, r=wesleywiser

Rename Receiver -> LegacyReceiver

As part of the "arbitrary self types v2" project, we are going to replace the current `Receiver` trait with a new mechanism based on a new, different `Receiver` trait.

This PR renames the old trait to get it out the way. Naming is hard. Options considered included:
* HardCodedReceiver (because it should only be used for things in the standard library, and hence is sort-of hard coded)
* LegacyReceiver
* TargetLessReceiver
* OldReceiver

These are all bad names, but fortunately this will be temporary. Assuming the new mechanism proceeds to stabilization as intended, the legacy trait will be removed altogether.

Although we expect this trait to be used only in the standard library, we suspect it may be in use elsehwere, so we're landing this change separately to identify any surprising breakages.

It's known that this trait is used within the Rust for Linux project; a patch is in progress to remove their dependency.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? `@wesleywiser`
adetaylor added a commit to adetaylor/rust that referenced this issue Oct 24, 2024
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.

The definition of "generic" was unclear in the RFC, but has been
explored in
rust-lang#129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.

This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
  filter out Rc<Self> and all the other types of smart pointer
  we want to support;
* we can't filter out all type params, because Self itself is a
  type param, and because existing Rust code depends on other
  type params declared on the type (as opposed to the method).

This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.

This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.

This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
adetaylor added a commit to adetaylor/rust that referenced this issue Oct 25, 2024
This commit contains a new Receiver trait, which is the basis for the
Arbitrary Self Types v2 RFC. This allows smart pointers to be method
receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to
use this for method resolution if the arbitrary_self_types feature gate
is enabled. This is being landed first simply to make review
simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
adetaylor added a commit to adetaylor/rust that referenced this issue Oct 25, 2024
This commit contains a new Receiver trait, which is the basis for the
Arbitrary Self Types v2 RFC. This allows smart pointers to be method
receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to
use this for method resolution if the arbitrary_self_types feature gate
is enabled. This is being landed first simply to make review
simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
adetaylor added a commit to adetaylor/rust that referenced this issue Oct 25, 2024
This commit contains a new Receiver trait, which is the basis for the
Arbitrary Self Types v2 RFC. This allows smart pointers to be method
receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to
use this for method resolution if the arbitrary_self_types feature gate
is enabled. This is being landed first simply to make review
simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
@adetaylor
Copy link
Contributor

Another update on progress relative to the plan, as we've got a little further.

  • Step 3 - thanks to @wesleywiser I think it's concluded that the best solution here is in this PR which is, as far as I know, ready to merge.
  • Step 5 - PR has been merged, which allowed me to move onto...
  • Step 6 - just raised a draft PR here. These are the library changes to add the new Receiver trait. I am still not sure if it's best to land this atomically or with the compiler changes that are in step 7. I'm kind of expecting Rust CI to tell me it's a bad idea to land them separately, but I tend to believe that code review time increases with the square of the lines of code changed, so I'd rather land them separately if I can...

My working branch is also updated and contains most of the remaining stuff I'll need to clean up and get merged eventually.

adetaylor added a commit to adetaylor/rust that referenced this issue Oct 30, 2024
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.

The definition of "generic" was unclear in the RFC, but has been
explored in
rust-lang#129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.

This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
  filter out Rc<Self> and all the other types of smart pointer
  we want to support;
* we can't filter out all type params, because Self itself is a
  type param, and because existing Rust code depends on other
  type params declared on the type (as opposed to the method).

This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.

This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.

This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
adetaylor added a commit to adetaylor/rust that referenced this issue Oct 30, 2024
This commit contains a new Receiver trait, which is the basis for the
Arbitrary Self Types v2 RFC. This allows smart pointers to be method
receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to
use this for method resolution if the arbitrary_self_types feature gate
is enabled. This is being landed first simply to make review
simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
jieyouxu added a commit to jieyouxu/rust that referenced this issue Oct 30, 2024
…ck-generics, r=wesleywiser

Reject generic self types.

The RFC for arbitrary self types v2 declares that we should reject "generic" self types. This commit does so.

The definition of "generic" was unclear in the RFC, but has been explored in
rust-lang#129147
and the conclusion is that "generic" means any `self` type which is a type parameter defined on the method itself, or references to such a type.

This approach was chosen because other definitions of "generic" don't work. Specifically,
* we can't filter out generic type _arguments_, because that would filter out Rc<Self> and all the other types of smart pointer we want to support;
* we can't filter out all type params, because Self itself is a type param, and because existing Rust code depends on other type params declared on the type (as opposed to the method).

This PR decides to make a new error code for this case, instead of reusing the existing E0307 error. This makes the code a bit more complex, but it seems we have an opportunity to provide specific diagnostics for this case so we should do so.

This PR filters out generic self types whether or not the 'arbitrary self types' feature is enabled. However, it's believed that it can't have any effect on code which uses stable Rust, since there are no stable traits which can be used to indicate a valid generic receiver type, and thus it would have been impossible to write code which could trigger this new error case. It is however possible that this could break existing code which uses either of the unstable `arbitrary_self_types` or `receiver_trait` features. This breakage is intentional; as we move arbitrary self types towards stabilization we don't want to continue to support generic such types.

This PR adds lots of extra tests to arbitrary-self-from-method-substs. Most of these are ways to trigger a "type mismatch" error which https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519 hopes can be minimized by filtering out generics in this way. We remove a FIXME from confirm.rs suggesting that we make this change. It's still possible to cause type mismatch errors, and a subsequent PR may be able to improve diagnostics in this area, but it's harder to cause these errors without contrived uses of the turbofish.

This is a part of the arbitrary self types v2 project, rust-lang/rfcs#3519
rust-lang#44874

r? `@wesleywiser`
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 30, 2024
Rollup merge of rust-lang#130098 - adetaylor:arbitrary-self-types-block-generics, r=wesleywiser

Reject generic self types.

The RFC for arbitrary self types v2 declares that we should reject "generic" self types. This commit does so.

The definition of "generic" was unclear in the RFC, but has been explored in
rust-lang#129147
and the conclusion is that "generic" means any `self` type which is a type parameter defined on the method itself, or references to such a type.

This approach was chosen because other definitions of "generic" don't work. Specifically,
* we can't filter out generic type _arguments_, because that would filter out Rc<Self> and all the other types of smart pointer we want to support;
* we can't filter out all type params, because Self itself is a type param, and because existing Rust code depends on other type params declared on the type (as opposed to the method).

This PR decides to make a new error code for this case, instead of reusing the existing E0307 error. This makes the code a bit more complex, but it seems we have an opportunity to provide specific diagnostics for this case so we should do so.

This PR filters out generic self types whether or not the 'arbitrary self types' feature is enabled. However, it's believed that it can't have any effect on code which uses stable Rust, since there are no stable traits which can be used to indicate a valid generic receiver type, and thus it would have been impossible to write code which could trigger this new error case. It is however possible that this could break existing code which uses either of the unstable `arbitrary_self_types` or `receiver_trait` features. This breakage is intentional; as we move arbitrary self types towards stabilization we don't want to continue to support generic such types.

This PR adds lots of extra tests to arbitrary-self-from-method-substs. Most of these are ways to trigger a "type mismatch" error which https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519 hopes can be minimized by filtering out generics in this way. We remove a FIXME from confirm.rs suggesting that we make this change. It's still possible to cause type mismatch errors, and a subsequent PR may be able to improve diagnostics in this area, but it's harder to cause these errors without contrived uses of the turbofish.

This is a part of the arbitrary self types v2 project, rust-lang/rfcs#3519
rust-lang#44874

r? `@wesleywiser`
bjorn3 pushed a commit to rust-lang/rustc_codegen_cranelift that referenced this issue Oct 31, 2024
As part of the "arbitrary self types v2" project, we are going to
replace the current `Receiver` trait with a new mechanism based on a
new, different `Receiver` trait.

This PR renames the old trait to get it out the way. Naming is hard.
Options considered included:
* HardCodedReceiver (because it should only be used for things in the
  standard library, and hence is sort-of hard coded)
* LegacyReceiver
* TargetLessReceiver
* OldReceiver

These are all bad names, but fortunately this will be temporary.
Assuming the new mechanism proceeds to stabilization as intended, the
legacy trait will be removed altogether.

Although we expect this trait to be used only in the standard library,
we suspect it may be in use elsehwere, so we're landing this change
separately to identify any surprising breakages.

It's known that this trait is used within the Rust for Linux project; a
patch is in progress to remove their dependency.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang/rust#44874

r? @wesleywiser
adetaylor added a commit to adetaylor/rust that referenced this issue Oct 31, 2024
This commit contains a new Receiver trait, which is the basis for the
Arbitrary Self Types v2 RFC. This allows smart pointers to be method
receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to
use this for method resolution if the arbitrary_self_types feature gate
is enabled. This is being landed first simply to make review
simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project,
rust-lang/rfcs#3519
rust-lang#44874

r? @wesleywiser
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Nov 11, 2024
…=wesleywiser

Arbitrary self types v2: (unused) Receiver trait

This commit contains a new `Receiver` trait, which is the basis for the Arbitrary Self Types v2 RFC. This allows smart pointers to be method receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to use this for method resolution if the `arbitrary_self_types` feature gate is enabled. This is being landed first simply to make review simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project, rust-lang/rfcs#3519
rust-lang#44874

r? `@wesleywiser`
alistair23 pushed a commit to alistair23/linux that referenced this issue Nov 11, 2024
The term "receiver" means that a type can be used as the type of `self`,
and thus enables method call syntax `foo.bar()` instead of
`Foo::bar(foo)`. Stable Rust as of today (1.81) enables a limited
selection of types (primitives and types in std, e.g. `Box` and `Arc`)
to be used as receivers, while custom types cannot.

We want the kernel `Arc` type to have the same functionality as the Rust
std `Arc`, so we use the `Receiver` trait (gated behind `receiver_trait`
unstable feature) to gain the functionality.

The `arbitrary_self_types` RFC [1] (tracking issue [2]) is accepted and
it will allow all types that implement a new `Receiver` trait (different
from today's unstable trait) to be used as receivers. This trait will be
automatically implemented for all `Deref` types, which include our `Arc`
type, so we no longer have to opt-in to be used as receiver. To prepare
us for the change, remove the `Receiver` implementation and the
associated feature. To still allow `Arc` and others to be used as method
receivers, turn on `arbitrary_self_types` feature instead.

This feature gate is introduced in 1.23.0. It used to enable both
`Deref` types and raw pointer types to be used as receivers, but the
latter is now split into a different feature gate in Rust 1.83 nightly.
We do not need receivers on raw pointers so this change would not affect
us and usage of `arbitrary_self_types` feature would work for all Rust
versions that we support (>=1.78).

Cc: Adrian Taylor <ade@hohum.me.uk>
Link: rust-lang/rfcs#3519 [1]
Link: rust-lang/rust#44874 [2]
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240915132734.1653004-1-gary@garyguo.net
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Nov 12, 2024
Rollup merge of rust-lang#132144 - adetaylor:receiver-trait-itself, r=wesleywiser

Arbitrary self types v2: (unused) Receiver trait

This commit contains a new `Receiver` trait, which is the basis for the Arbitrary Self Types v2 RFC. This allows smart pointers to be method receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to use this for method resolution if the `arbitrary_self_types` feature gate is enabled. This is being landed first simply to make review simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project, rust-lang/rfcs#3519
rust-lang#44874

r? `@wesleywiser`
@adetaylor
Copy link
Contributor

Latest update relative to the plan.

  • Step 6 PR has been merged
  • Step 7 - the big one - draft PR here
    • This has already shown up an unexpected issue with the deshadowing algorithm which I need to do some thinking about, that's the next step!

alistair23 pushed a commit to alistair23/linux that referenced this issue Nov 12, 2024
The term "receiver" means that a type can be used as the type of `self`,
and thus enables method call syntax `foo.bar()` instead of
`Foo::bar(foo)`. Stable Rust as of today (1.81) enables a limited
selection of types (primitives and types in std, e.g. `Box` and `Arc`)
to be used as receivers, while custom types cannot.

We want the kernel `Arc` type to have the same functionality as the Rust
std `Arc`, so we use the `Receiver` trait (gated behind `receiver_trait`
unstable feature) to gain the functionality.

The `arbitrary_self_types` RFC [1] (tracking issue [2]) is accepted and
it will allow all types that implement a new `Receiver` trait (different
from today's unstable trait) to be used as receivers. This trait will be
automatically implemented for all `Deref` types, which include our `Arc`
type, so we no longer have to opt-in to be used as receiver. To prepare
us for the change, remove the `Receiver` implementation and the
associated feature. To still allow `Arc` and others to be used as method
receivers, turn on `arbitrary_self_types` feature instead.

This feature gate is introduced in 1.23.0. It used to enable both
`Deref` types and raw pointer types to be used as receivers, but the
latter is now split into a different feature gate in Rust 1.83 nightly.
We do not need receivers on raw pointers so this change would not affect
us and usage of `arbitrary_self_types` feature would work for all Rust
versions that we support (>=1.78).

Cc: Adrian Taylor <ade@hohum.me.uk>
Link: rust-lang/rfcs#3519 [1]
Link: rust-lang/rust#44874 [2]
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240915132734.1653004-1-gary@garyguo.net
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
herrnst pushed a commit to herrnst/linux-asahi that referenced this issue Nov 21, 2024
The term "receiver" means that a type can be used as the type of `self`,
and thus enables method call syntax `foo.bar()` instead of
`Foo::bar(foo)`. Stable Rust as of today (1.81) enables a limited
selection of types (primitives and types in std, e.g. `Box` and `Arc`)
to be used as receivers, while custom types cannot.

We want the kernel `Arc` type to have the same functionality as the Rust
std `Arc`, so we use the `Receiver` trait (gated behind `receiver_trait`
unstable feature) to gain the functionality.

The `arbitrary_self_types` RFC [1] (tracking issue [2]) is accepted and
it will allow all types that implement a new `Receiver` trait (different
from today's unstable trait) to be used as receivers. This trait will be
automatically implemented for all `Deref` types, which include our `Arc`
type, so we no longer have to opt-in to be used as receiver. To prepare
us for the change, remove the `Receiver` implementation and the
associated feature. To still allow `Arc` and others to be used as method
receivers, turn on `arbitrary_self_types` feature instead.

This feature gate is introduced in 1.23.0. It used to enable both
`Deref` types and raw pointer types to be used as receivers, but the
latter is now split into a different feature gate in Rust 1.83 nightly.
We do not need receivers on raw pointers so this change would not affect
us and usage of `arbitrary_self_types` feature would work for all Rust
versions that we support (>=1.78).

Cc: Adrian Taylor <ade@hohum.me.uk>
Link: rust-lang/rfcs#3519 [1]
Link: rust-lang/rust#44874 [2]
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240915132734.1653004-1-gary@garyguo.net
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
madsmtm added a commit to madsmtm/objc2 that referenced this issue Nov 21, 2024
Tracking issue rust-lang/rust#44874.

Especially useful to allow `self: Allocated<Self>` in the future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-arbitrary_self_types `#![feature(arbitrary_self_types)]` S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. S-types-deferred Status: Identified as a valid potential future enhancement that is not currently being worked on T-lang Relevant to the language team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests