Skip to content

[Draft] Supertrait item resolution in subtrait impls #143527

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

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dingxiangfei2009
Copy link
Contributor

r? @ghost

cc @cramertj @petrochenkov

This is pertaining to implementable trait aliases, Deref/Receiver trait migration and supertrait items in subtrait impls.

This is a draft for the resolver and crate metadata changes. Through this patch, the resolver will pick up supertrait items, collected from the trait super-bounds and trait alias in a future extension. This information will be encoded so that the resolver can resolve names in the downstream crates.

I would like to post this draft earlier because there are already significant design changes, which may warrant collecting opinions ahead of time.

Next steps would be

  • teach hir-analysis to collect associated items in subtrait items into implied supertrait impls;
  • adapt the syntax so that associated items can be paths instead of just identifies today, because associate items on paths is essential for the disambiguation of the design.

@rustbot rustbot added A-rustdoc-json Area: Rustdoc JSON backend T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. labels Jul 6, 2025
@rust-log-analyzer
Copy link
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
-    fn get_module_supertraits(self, id: DefIndex, sess: &'a Session) -> impl Iterator<Item = DefId> {
+    fn get_module_supertraits(
+        self,
+        id: DefIndex,
+        sess: &'a Session,
+    ) -> impl Iterator<Item = DefId> {
         let supertraits = self.root.tables.module_supertraits.get(self, id);
         supertraits.decode((self, sess)).into_iter()
     }
fmt: checked 6147 files
Build completed unsuccessfully in 0:00:44
  local time: Sun Jul  6 14:09:05 UTC 2025
  network time: Sun, 06 Jul 2025 14:09:06 GMT

@petrochenkov petrochenkov self-assigned this Jul 6, 2025
impl Sub for S {
//~^ ERROR: the trait bound `S: Sup` is not satisfied
type A = ();
//~^ ERROR: the trait bound `S: Sup` is not satisfied
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not the desired end game, yet. This is rather a demonstration that this patch allows name resolution to associate A with that from trait Sup correctly.

@dingxiangfei2009
Copy link
Contributor Author

dingxiangfei2009 commented Jul 7, 2025

cc @tmandry @tomassedovic

The patch is also to unblock arbitrary_self_types.

The next steps are

  • (before landing this patch) gate the supertrait behaviour behind #[rustc_supertrait_in_subtrait_impl]
  • Teach hir-analysis to generate an impl for supertraits
  • Mark Deref with a builtin attribute #[rustc_supertrait_in_subtrait_impl], move Target from Deref to Receiver
    • Test the set up with crater

@petrochenkov petrochenkov added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 7, 2025
/// The source of this trait ref
/// and whether this trait ref should be regarded as
/// a nominal subtrait-supertrait relation.
pub source: TraitRefSource,
Copy link
Contributor

Choose a reason for hiding this comment

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

We probably don't need this in AST.
This flag is needed after HIR->Ty lowering, I guess, and instead of parser it's equally simple to calculate it at any stage before that (e.g. in AST->HIR lowering, or HIR->Ty lowering).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see that PolyTraitRef is used in several AST nodes including dyn, where bounds and the trait superbounds. Where would a better place be, to record whether the trait superbound has the auto impl modifier?

Copy link
Contributor Author

@dingxiangfei2009 dingxiangfei2009 Jul 10, 2025

Choose a reason for hiding this comment

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

How about switching out parse_generic_bounds parser in fn parse_item_trait and we record the supertrait modifier, ie. with auto impl or not, on the trait item level?

Copy link
Contributor

Choose a reason for hiding this comment

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

The auto impl modifier is in AST, yes.
Parser generally shouldn't be too context-sensitive and use things like in_supertrait_context, so it would typically parse auto impl everywhere and then later passes would reject it semantically in inappropriate positions.
Otherwise we have two separate but similar grammars for bound lists.

Copy link
Contributor

@petrochenkov petrochenkov Jul 10, 2025

Choose a reason for hiding this comment

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

But for a prototype both ways are ok, and if we need to track in_supertrait_context in the parser anyway for auto impl, then we can store it into AST too.

@@ -52,15 +53,15 @@ pub enum BoundKind {

/// Super traits of a trait.
/// E.g., `trait A: B`
SuperTraits,
SuperTraits { subtrait: LocalDefId },
Copy link
Contributor

Choose a reason for hiding this comment

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

LocalDefId shouldn't be a part of AST or AST visitors.
If it's needed by some specific visitor, it's better to pass it in some other way.

leading_token: &Token,
) -> PResult<'a, GenericBound> {
let auto_impl = if in_supertrait_context && self.eat_keyword(exp!(Auto)) {
self.expect_keyword(exp!(Impl))?;
Copy link
Contributor

Choose a reason for hiding this comment

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

What is auto impl Trait?
I don't see it in tests.
Is it a part of the "supertrait items in subtrait impls" feature, or some other related feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it was not included in the the "supertrait items in subtrait impls" feature but it is in the next proposal to handle the marker trait case.

Suppose that we have a marker trait trait Marker {} which has no associated items. The lang team discussion prefers the option to not automatically fill in an implicit impl Marker. Rather, we will first not fill it out and let the user to explicitly do impl Marker for .., unless the user writes trait Subtrait: auto impl Marker to allow the auto-impl.

@@ -580,6 +584,9 @@ struct ModuleData<'ra> {
/// Used to memoize the traits in this module for faster searches through all traits in scope.
traits: RefCell<Option<Box<[(Ident, NameBinding<'ra>)]>>>,

/// In case supertraits are relevant in the module, the DefIds are collected, too.
supertraits: RefCell<IndexSet<DefId>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is necessary.
Since use ChildTrait::ItemFromParent; and similar do not work and are not supposed to work, the whole implementation can be localized to compiler\rustc_resolve\src\late.rs.

Perhaps as two passes in late resolver.
Since if the first (regular) pass we do not always have trait Parent late-resolved when late-resolving

trait Child: Parent { ... }

, but we may need trait Parent late-resolved here.
So maybe the first pass can just keep a hole and some bookkeeping, so that the hole can be filled in a second pass.

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rustdoc-json Area: Rustdoc JSON backend S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants