Skip to content

delegation: add support for infers in generics#157960

Open
aerooneqq wants to merge 15 commits into
rust-lang:mainfrom
aerooneqq:delegation-infers-in-generics
Open

delegation: add support for infers in generics#157960
aerooneqq wants to merge 15 commits into
rust-lang:mainfrom
aerooneqq:delegation-infers-in-generics

Conversation

@aerooneqq

@aerooneqq aerooneqq commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

This PR adds support for generating generic params for lifetimes and types/consts infers ('_. _). We support only single infers, if they are nested then we do nothing and eventually an error will be emitted after inheriting this unsound signature (i.e., reuse foo::<Vec<_>> is not supported).

The basic idea is:

fn foo<'a, 'b: 'b, T, const N: usize>() {}

reuse foo::<'_, String, _> as bar;

// Desugaring:
fn bar<'b, const N: usize>() {
  foo::<'b, String, N>()
}

So we generated params and lifetimes for provided infers. Note that in case of lifetimes we may have early and late bound lifetimes in child segment. We process only early-bound lifetimes as they are present in signature function generics (tcx.generics_of(sig_id)). Moreover since this PR we started to explicitly propagate early-bound lifetimes in generated delegation's call, so the warning about specifying lifetimes when late-bound lifetimes are present is suppressed for delegation segments.

Next, we limit the number of processed infers with the number of generic params in the signature function, so if we have fn foo<X, Y>() {} and we wrote reuse foo::<_, _, _, _>; we will not generate 4 generic params in delegation, we will generate 2 (X and Y), two remaining infers will not be processed and this will result in an error.

Considering free-to-trait reuses this PR extends the number of supported cases, as now we always generate Self generic param when needed:

trait Trait<'a, X> {
    fn method<'b, const M: usize>(&self) where 'b:'b { }
    fn r#static<'b, Y, const B: bool>() { }
}

impl <'a, X> Trait<'a, X> for () { }

reuse Trait::<'_, _>::method::<'_, _> as foo;
reuse <_ as Trait<'_, _>>::method::<'_, _> as foo1;
reuse <() as Trait<'_, _>>::method::<'_, _> as foo2;
reuse <_ as Trait<'_, _>>::r#static::<_, _> as foo3;
reuse <() as Trait<'_, _>>::r#static::<_, _> as foo4;
reuse Trait::<'_, _>::r#static::<_, _> as foo5;

// Desugaring:
#[attr = Inline(Hint)]
fn foo<'a, 'b, Self, X, const M: _>(self: _) -> _ where 'a:'a,
    'b:'b { <Self as Trait::<'a, X>>::method::<'b, M>(self) }
#[attr = Inline(Hint)]
fn foo1<'a, 'b, Self, X, const M: _>(self: _) -> _ where 'a:'a,
    'b:'b { <Self as Trait::<'a, X>>::method::<'b, M>(self) }
#[attr = Inline(Hint)]
fn foo2<'a, 'b, X, const M: _>(self: _) -> _ where 'a:'a,
    'b:'b { <() as Trait::<'a, X>>::method::<'b, M>(self) }
#[attr = Inline(Hint)]
fn foo3<'a, Self, X, Y, const B: _>() -> _ where
    'a:'a { <Self as Trait::<'a, X>>::r#static::<Y, B>() }
#[attr = Inline(Hint)]
fn foo4<'a, X, Y, const B: _>() -> _ where
    'a:'a { <() as Trait::<'a, X>>::r#static::<Y, B>() }
#[attr = Inline(Hint)]
fn foo5<'a, Self, X, Y, const B: _>() -> _ where
    'a:'a { <Self as Trait::<'a, X>>::r#static::<Y, B>() }

Note that we generated Self in foo5 reuse. With that done the error about self-type specification is removed.

Finally this PR greatly simplifies generic args for signature inheritance generation code.

Part of #118212.
r? @petrochenkov

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jun 16, 2026
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 16, 2026
Comment thread compiler/rustc_ast_lowering/src/lib.rs Outdated
@aerooneqq aerooneqq marked this pull request as ready for review June 17, 2026 08:04
@rustbot

rustbot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

HIR ty lowering was modified

cc @fmease

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 17, 2026
(kw::Underscore, kw::UnderscoreLifetime)
};

self.tcx.dcx().emit_err(DelegationInfersMismatch {

@aerooneqq aerooneqq Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we need this diagnostic? Other option is to skip incorrect infers and error will be emitted later during signature inheritance.

View changes since the review

let generate_self = free_to_trait_delegation && is_method && delegation.qself.is_none();

let qself_is_infer =
delegation.qself.as_ref().is_some_and(|qself| qself.ty.is_maybe_parenthesised_infer());

@aerooneqq aerooneqq Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we need to care about ast::TyKind::Paren or we can just use matches!(ty.kind, ast::TyKind::Infer)?

View changes since the review

@aerooneqq aerooneqq force-pushed the delegation-infers-in-generics branch from 7d84842 to 1da6864 Compare June 17, 2026 09:03
@rustbot

rustbot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main 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.

@petrochenkov petrochenkov added the F-fn_delegation `#![feature(fn_delegation)]` label Jun 17, 2026
//~| ERROR: function takes 3 generic arguments but 2 generic arguments were supplied
//~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature
//~| ERROR: function takes 3 generic arguments but 1 generic argument was supplied
//~| ERROR: function takes 2 lifetime arguments but 6 lifetime arguments were supplied

@petrochenkov petrochenkov Jun 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: the annotations were reordered, and it makes the changes look larger than they actually are.
(Same below.)

View changes since the review

#[derive(Debug, Clone, Copy, PartialEq, Eq, StableHash)]
pub enum DelegationSelfTyPropagationKind {
SelfTy(HirId /* Self ty id */),
SelfParam,

@petrochenkov petrochenkov Jun 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you add comments telling what the variants mean?

View changes since the review

pub propagate_self_ty: bool,
pub child_seg_id: HirId,
pub parent_seg_id_for_sig: Option<HirId>,
pub child_seg_id_for_sig: Option<HirId>,

@petrochenkov petrochenkov Jun 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you add comments telling what the fields mean?
E.g. what is the difference between child_seg_id and child_seg_id_for_sig.

View changes since the review

@petrochenkov

Copy link
Copy Markdown
Contributor

(I started reviewing, will continue tomorrow.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-fn_delegation `#![feature(fn_delegation)]` 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants