arbitrary_self_types: Split the Autoderef chain by dingxiangfei2009 · Pull Request #146095 · rust-lang/rust (original) (raw)

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 andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})

@dingxiangfei2009

Receiver chain has been an extension of Deref chain, but the consequence has been questioned as this would admit method signatures that are deemed dubious.

It is also debatable that Receiver trait which determines applicable Self type should have anything to do with dereference operation in general.

This patch separate the two traits and isolate their use in the language. This means that in method probing, we will chase down a Deref chain for an applicable type for the variable self, from which we additionally chase down a Receiver chain for an applicable Self type from a list of methods that accepts one of these possible types of self.

To facilitate discussion, we can use the Zulip thread #t-lang > Consequences of making Deref a subtrait of Receiver.

Pending items

@rustbot

r? @jackh726

rustbot has assigned @jackh726.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

T-compiler

Relevant to the compiler team, which will review and decide on the PR/issue.

T-libs

Relevant to the library team, which will review and decide on the PR/issue.

labels

Sep 1, 2025

@rustbot

This PR changes a file inside tests/crashes. If a crash was fixed, please move into the corresponding ui subdir and add 'Fixes #' to the PR description to autoclose the issue upon merge.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@dingxiangfei2009

@rustbot

The Miri subtree was changed

cc @rust-lang/miri

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@jackh726

Is this waiting on discussion and a decision from the lang team?

@ojeda ojeda mentioned this pull request

Aug 31, 2025

@dingxiangfei2009

@jackh726 Sorry I was not very clear. Indeed it would need a lang team discussion.

To support the discussion, I am writing a report to describe what changes this would bring to the feature.

cc @traviscross @tmandry

@traviscross traviscross added S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

S-waiting-on-team

DEPRECATED: Use the team-based variants `S-waiting-on-t-lang`, `S-waiting-on-t-compiler`, ...

I-lang-radar

Items that are on lang's radar and will need eventual work or consideration.

T-lang

Relevant to the language team

and removed T-libs

Relevant to the library team, which will review and decide on the PR/issue.

labels

Sep 4, 2025

@bors

@dingxiangfei2009

The report is a bit overdue. I would like to just publish a partial text while I need more time to restore some diagnostics.

Acceptable receivers

Landing #146095 means that types implementing Deref are not automatically acceptable receiver types anymore.

Before #146095 After #146095
struct A; struct B; impl Deref for A { type Target = B; fn deref(&self) -> &B { &B } } impl B { fn recv(self: &A); } A.recv(); // resolves to B::recv struct A; struct B; impl Deref for A { type Target = B; fn deref(&self) -> &B { &B } } // This is needed ... impl Receiver for A { type Target = B; } impl B { fn recv(self: &A); } A.recv(); // ^ ... in order to resolve this to B::recv
// The following passes checking in our surprises impl Trait for str { fn recv(self: &String) {} } "hello".to_string().recv(); impl Trait for MyType { fn recv(self: MutexGuard<'_, Self>) {} } let my_mutex = Mutex::new(MyType); my_mutex.lock().recv(); // The following stops to compile for good reasons impl Trait for str { fn recv(self: &String) {} // `String: Deref<Target = str>` but without `Receiver<Target = str>` } "hello".to_string().recv(); //~ ERROR impl Trait for MyType { fn recv(self: MutexGuard<'_, Self>) {} // `MutexGuard<'_, MyType>: Deref<Target = MyType>` but without `Receiver<Target = MyType>` } let my_mutex = Mutex::new(MyType); my_mutex.lock().recv(); //~ ERROR

Library changes

This patch demonstrates that we now explicitly mark types like Rc, Arc, Box, Pin as valid receivers regardless of whether a Deref is applicable.

This is particularly important for Pin as we want to conditionally make it Derefable but unconditionally a valid method receiver just like the stable Rust.

Shadowing

After careful consideration and testing, I believe that splitting the two traits do not change the fundamental reasoning behind method shadowing diagnostics. Before this change, concerns about shadowing items through Deref, and by extension Receiver, are reported by the compiler by picking up inherent methods with the same name on some self receiver down the Receiver chain. Those shadowed items will continue to be reported as they will appear in the same Receiver sub-chain after this PR lands.

@traviscross traviscross added I-lang-nominated

Nominated for discussion during a lang team meeting.

P-lang-drag-1

Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang

labels

Sep 24, 2025

@traviscross

I'm going to go ahead and nominate. This is just a vibe check. We're not making a binding decision at this time. The question on the table is only whether we might have such opposition to this direction that we'd block or discourage its exploration.

For my part, I want to see this explored so we can fully consider it.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@traviscross traviscross removed I-lang-nominated

Nominated for discussion during a lang team meeting.

P-lang-drag-1

Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang

labels

Oct 5, 2025

@traviscross

We talked about this, for a vibe check, in the lang meeting this past week. People certainly aren't yet sold on this approach -- I'm not yet sold myself. However, I feel that the way to work out whether this approach is viable and desirable is to let @dingxiangfei2009 land this and explore it further -- experimentation will hopefully help to answer the kind of questions this approach raises and support the writing of comprehensive design documents for this -- and that went without objection.

Putting on the hat of the lang champion here, then, this PR is OK to land as far as lang is concerned.

We'll want to be careful, in how we do this experimentation, that we still support experimentation of and the ability to answer important design questions for the other model, e.g. to support work on evolving trait hierarchies, reborrowing, autoref, projection, etc., where we might want to compare how the complete solution would look either in the Deref::Target == Receiver::Target world or in the other one. I'm hopeful that we can add additional feature flags as necessary in order to support whatever turns out to be needed here.

@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

jackh726

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`)

consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised by this change. I would expect to only change the diagnostic when the feature is not enabled hir_analysis_invalid_receiver_ty_help

Comment on lines 367 to 368

A(A, PhantomData<fn() -> C>),
B(B, PhantomData<fn() -> C>),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the extra PhantomData<fn() -> C> here? I assume it was to ensure that C is used constrained in the impl below, but it's unnecessary.

}
}
if follow_receiver_chain {
EitherIter::A(fcx.autoderef(span, ty).follow_receiver_chain(), PhantomData)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so if I'm understanding this correctly, for each step in Deref chain, we then try a Receiver chain? That's pretty crazy, and is very likely going to have an effect on perf.

I would really like to evaluate perf before and after this PR (when enabling arbitrary self types).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are already performing quadratic time probing with how Receiver is set up on main branch.

I am thinking of sorting the candidates into bins for each candidate Self type. With this structure we save some search effort. Let me work on a patch on this idea.

Comment on lines +1825 to +1827

// We are in the wf check, so we would like to deref the references in the type head.
// However, we do not want to walk `Deref` chain.
autoderef = autoderef.follow_receiver_chain();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why that is here? But in confirm we do?

&*self.0
}
}
impl<T: ?Sized> Receiver for Ptr<T> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these impls required? I imagine this might be a consequence of my comment in wfcheck?

@rustbot

This comment has been minimized.

@bors

@dingxiangfei2009

Receiver chain has been an extension of Deref chain, but the consequence has been questioned as this would admit method signatures that are deemed dubious.

It is also debatable that Receiver trait which determines applicable Self type should have anything to do with dereference operation in general.

This patch separate the two traits and isolate their use in the language. This means that in method probing, we will chase down a Deref chain for an applicable type for the variable self, from which we additionally chase down a Receiver chain for an applicable Self type from a list of methods that accepts one of these possible types of self.

This patch includes rewording of diagnostics.

@dingxiangfei2009

@rustbot

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Labels

F-arbitrary_self_types

`#![feature(arbitrary_self_types)]`

I-lang-radar

Items that are on lang's radar and will need eventual work or consideration.

S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

T-compiler

Relevant to the compiler team, which will review and decide on the PR/issue.

T-lang

Relevant to the language team