Skip to content

delegation: do not always generate first argument#156798

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
aerooneqq:delegation-dont-generate-first-arg
Jun 5, 2026
Merged

delegation: do not always generate first argument#156798
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
aerooneqq:delegation-dont-generate-first-arg

Conversation

@aerooneqq
Copy link
Copy Markdown
Contributor

@aerooneqq aerooneqq commented May 21, 2026

View all comments

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

  • If there is a single delegation and source function has first param, otherwise error is emitted,
  • If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes #154427. Part of #118212.
r? @petrochenkov

@rustbot rustbot added 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. labels May 21, 2026
@aerooneqq aerooneqq force-pushed the delegation-dont-generate-first-arg branch 5 times, most recently from 303d29a to c400cb5 Compare May 22, 2026 06:49
struct F(S);
// In glob delegations silently remove first arg if no params or generate default
// first arg (`arg0`) if it is a static function.
reuse impl Trait for F { self.0 }
Copy link
Copy Markdown
Contributor Author

@aerooneqq aerooneqq May 22, 2026

Choose a reason for hiding this comment

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

Desugaring:

impl Trait for F {
    #[attr = Inline(Hint)]
    fn value(self: _) -> _ { self.0.value() }
    #[attr = Inline(Hint)]
    fn r#ref(self: _) -> _ { self.0.r#ref() }
    #[attr = Inline(Hint)]
    fn mut_ref(self: _) -> _ { self.0.mut_ref() }
    #[attr = Inline(Hint)]
    fn static_empty() -> _ { Trait::static_empty() }
    #[attr = Inline(Hint)]
    fn static_one_param(arg0: _) -> _ { Trait::static_one_param(arg0) } 
}

First arg transformation is not generated even if a static function has first param.

View changes since the review

struct F2(S);
impl F2 {
// In list delegations silently remove first arg if it is not a method.
reuse <S as Trait>::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 }
Copy link
Copy Markdown
Contributor Author

@aerooneqq aerooneqq May 22, 2026

Choose a reason for hiding this comment

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

Desugaring:

#[attr = Inline(Hint)]
fn value(self: _) -> _ { <S as Trait>::value(self.0) }
#[attr = Inline(Hint)]
fn r#ref(self: _) -> _ { <S as Trait>::r#ref(self.0) }
#[attr = Inline(Hint)]
fn mut_ref(self: _) -> _ { <S as Trait>::mut_ref(self.0) }
#[attr = Inline(Hint)]
fn static_empty() -> _ { <S as Trait>::static_empty() }
#[attr = Inline(Hint)]
fn static_one_param(arg0: _) -> _ { <S as Trait>::static_one_param(arg0) }

First arg transformation is not generated even if a static function has first param.

View changes since the review

reuse to_reuse::one_param { self + 1 }

// In list delegations silently remove first arg if there are no params.
reuse to_reuse::{empty as empty1, one_param as one_param1} { self + 1 }
Copy link
Copy Markdown
Contributor Author

@aerooneqq aerooneqq May 22, 2026

Choose a reason for hiding this comment

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

Desugaring:

// In list delegations silently remove first arg if there are no params.
#[attr = Inline(Hint)]
fn empty1() -> _ { to_reuse::empty() }
#[attr = Inline(Hint)]
fn one_param1(arg0: _) -> _ { to_reuse::one_param(self + 1) }

We generated first arg transformation as it is a free function.

View changes since the review

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.

After updates we emit error if target expression is specified for list free functions delegations with parameterless functions.

Comment thread compiler/rustc_resolve/src/build_reduced_graph.rs Outdated
@aerooneqq aerooneqq force-pushed the delegation-dont-generate-first-arg branch from c400cb5 to 3983a7b Compare May 22, 2026 07:15

struct F3(S);
impl Trait for F3 {
reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 }
Copy link
Copy Markdown
Contributor Author

@aerooneqq aerooneqq May 22, 2026

Choose a reason for hiding this comment

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

Desugaring:

#[attr = Inline(Hint)]
fn value(self: _) -> _ { trait_to_reuse::value(self.0) }
#[attr = Inline(Hint)]
fn r#ref(self: _) -> _ { trait_to_reuse::r#ref(self.0) }
#[attr = Inline(Hint)]
fn mut_ref(self: _) -> _ { trait_to_reuse::mut_ref(self.0) }
#[attr = Inline(Hint)]
fn static_empty() -> _ { trait_to_reuse::static_empty() }
#[attr = Inline(Hint)]
fn static_one_param(arg0: _)
    -> _ { trait_to_reuse::static_one_param(arg0) }
//~^ ERROR: mismatched types
//~| ERROR: mismatched types

self resolves to F3.

View changes since the review


struct F4(S);
impl F4 {
reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 }
Copy link
Copy Markdown
Contributor Author

@aerooneqq aerooneqq May 22, 2026

Choose a reason for hiding this comment

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

Desugaring:

#[attr = Inline(Hint)]
fn value<impl Trait>(arg0: _) -> _ { trait_to_reuse::value(self.0) }
#[attr = Inline(Hint)]
fn r#ref<impl Trait>(arg0: _) -> _ { trait_to_reuse::r#ref(self.0) }
#[attr = Inline(Hint)]
fn mut_ref<impl Trait>(arg0: _) -> _ { trait_to_reuse::mut_ref(self.0) }
#[attr = Inline(Hint)]
fn static_empty() -> _ { trait_to_reuse::static_empty() }
#[attr = Inline(Hint)]
fn static_one_param(arg0: _)
    -> _ { trait_to_reuse::static_one_param(self.0) }

self resolves to first argument, as it is a plain impl and sig_id resolves to free functions not to a trait method in contrast to case with F3. We generated block for static_one_param as it is a free function, in F3 it is an associated function so we generate arg0.

View changes since the review

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.

After updates we emit error if target expression is specified for list free functions delegations with parameterless functions.

@aerooneqq aerooneqq marked this pull request as ready for review May 22, 2026 07:22
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 22, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 22, 2026

The parser was modified, potentially altering the grammar of (stable) Rust
which would be a breaking change.

cc @fmease

@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 22, 2026
@petrochenkov petrochenkov added the F-fn_delegation `#![feature(fn_delegation)]` label May 22, 2026
@petrochenkov
Copy link
Copy Markdown
Contributor

I think the solution for the dead code problem here brings much worse problems than the initial problem itself.

If the target expression is unused, we can generate something like

fn static_method() {
  let _ = target_expr;
  static_method()
}

instead of messing with the definition hierarchy.

@rustbot author

@rustbot rustbot 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 May 22, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 22, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@petrochenkov
Copy link
Copy Markdown
Contributor

Ah, the question is what self in target_expr refers to, if there's no first parameter in the signature.
Let's keep it an error for now, we'll come up with something, anything is better than messing with the definition hierarchy.

@petrochenkov
Copy link
Copy Markdown
Contributor

Ah, the question is what self in target_expr refers to, if there's no first parameter in the signature. Let's keep it an error for now, we'll come up with something, anything is better than messing with the definition hierarchy.

Although leaving e.g. self.field as dead code will be almost as harmful as passing it, 99% chance that it won't pass type checking.
I think need to discuss this in more detail on Monday before doing anything.

@petrochenkov
Copy link
Copy Markdown
Contributor

I just realized that removing code here is a future compatibility hazard.
Consider this:

reuse {foo} { std::something_unstable() };

If std::something_unstable() is removed at AST lowering stage, then it will go through name resolution, but won't go through stability checking, and the code will compile.
If later the API is removed instead of being stabilized, then the code will stop compiling due to failing at name resolution stage.

@petrochenkov
Copy link
Copy Markdown
Contributor

Also, removing or not removing the target expression depending on whether the delegation is a part of the list or not is probably not a good language design.

// now do two different things.
reuse foo;
reuse {foo};

I think we'll eventually need to remove the target expression either always, or always for associated functions.
But now we are in experimentation phase, so can try the single-or-not criterion too, it still goes into the right direction.

@rust-bors

This comment has been minimized.

@aerooneqq aerooneqq force-pushed the delegation-dont-generate-first-arg branch from fee11df to 31e3588 Compare June 5, 2026 05:38
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Jun 5, 2026

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.

@aerooneqq
Copy link
Copy Markdown
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-blocked Status: Blocked on something else such as an RFC or other implementation work. labels Jun 5, 2026
@aerooneqq aerooneqq changed the title delegation: do not always generate first argument (pt. 1) delegation: do not always generate first argument Jun 5, 2026
@petrochenkov
Copy link
Copy Markdown
Contributor

@bors r+

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Jun 5, 2026

📌 Commit 31e3588 has been approved by petrochenkov

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 5, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jun 5, 2026
…-first-arg, r=petrochenkov

delegation: do not always generate first argument

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

- If there is a single delegation and source function has first param, otherwise error is emitted,
- If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes rust-lang#154427. Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Jun 5, 2026
…uwer

Rollup of 8 pull requests

Successful merges:

 - #157467 (stdarch subtree update)
 - #156798 (delegation: do not always generate first argument)
 - #157450 (mark `Encode`, `Decode`, `Mark` impls as `#[inline]`)
 - #157190 (Silence recursive RUSTC_LOG_FORMAT_JSON messages)
 - #157447 (Move cross crate tests into the appropriate folder)
 - #157470 (Avoid ICE when emitting TargetMachine config errors)
 - #157474 (Forbid optimize(none) with inline(always) or inline.)
 - #157475 (Add a smoke test for the optimize attribute.)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jun 5, 2026
…-first-arg, r=petrochenkov

delegation: do not always generate first argument

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

- If there is a single delegation and source function has first param, otherwise error is emitted,
- If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes rust-lang#154427. Part of rust-lang#118212.
r? @petrochenkov
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jun 5, 2026
…-first-arg, r=petrochenkov

delegation: do not always generate first argument

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

- If there is a single delegation and source function has first param, otherwise error is emitted,
- If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes rust-lang#154427. Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Jun 5, 2026
…uwer

Rollup of 12 pull requests

Successful merges:

 - #157467 (stdarch subtree update)
 - #155453 (apply Cortex-A53 errata 843419 mitigation to the AArch64 Linux targets)
 - #156798 (delegation: do not always generate first argument)
 - #157016 (add `extern "tail"` calling convention)
 - #157450 (mark `Encode`, `Decode`, `Mark` impls as `#[inline]`)
 - #148183 (rustdoc: Test & document `test_harness` code block attribute)
 - #157190 (Silence recursive RUSTC_LOG_FORMAT_JSON messages)
 - #157470 (Avoid ICE when emitting TargetMachine config errors)
 - #157474 (Forbid optimize(none) with inline(always) or inline.)
 - #157475 (Add a smoke test for the optimize attribute.)
 - #157479 (Warn when `#[macro_use]` or `#[macro_escape]` is used on the crate root)
 - #157486 (Remove unused attributes from issue-29485.rs.)

Failed merges:

 - #157485 (Rename `errors.rs` file to `diagnostics.rs`)
jhpratt added a commit to jhpratt/rust that referenced this pull request Jun 5, 2026
…-first-arg, r=petrochenkov

delegation: do not always generate first argument

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

- If there is a single delegation and source function has first param, otherwise error is emitted,
- If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes rust-lang#154427. Part of rust-lang#118212.
r? @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Jun 5, 2026
Rollup of 12 pull requests

Successful merges:

 - #155453 (apply Cortex-A53 errata 843419 mitigation to the AArch64 Linux targets)
 - #156798 (delegation: do not always generate first argument)
 - #157438 (rustdoc: don't link doc(hidden) associated type projections)
 - #157450 (mark `Encode`, `Decode`, `Mark` impls as `#[inline]`)
 - #148183 (rustdoc: Test & document `test_harness` code block attribute)
 - #157190 (Silence recursive RUSTC_LOG_FORMAT_JSON messages)
 - #157396 (Add @aapoalas to libs review rotation)
 - #157470 (Avoid ICE when emitting TargetMachine config errors)
 - #157474 (Forbid optimize(none) with inline(always) or inline.)
 - #157475 (Add a smoke test for the optimize attribute.)
 - #157479 (Warn when `#[macro_use]` or `#[macro_escape]` is used on the crate root)
 - #157486 (Remove unused attributes from issue-29485.rs.)

Failed merges:

 - #157485 (Rename `errors.rs` file to `diagnostics.rs`)
rust-bors Bot pushed a commit that referenced this pull request Jun 5, 2026
Rollup of 12 pull requests

Successful merges:

 - #157467 (stdarch subtree update)
 - #155453 (apply Cortex-A53 errata 843419 mitigation to the AArch64 Linux targets)
 - #156798 (delegation: do not always generate first argument)
 - #157438 (rustdoc: don't link doc(hidden) associated type projections)
 - #157450 (mark `Encode`, `Decode`, `Mark` impls as `#[inline]`)
 - #157190 (Silence recursive RUSTC_LOG_FORMAT_JSON messages)
 - #157396 (Add @aapoalas to libs review rotation)
 - #157470 (Avoid ICE when emitting TargetMachine config errors)
 - #157474 (Forbid optimize(none) with inline(always) or inline.)
 - #157475 (Add a smoke test for the optimize attribute.)
 - #157479 (Warn when `#[macro_use]` or `#[macro_escape]` is used on the crate root)
 - #157486 (Remove unused attributes from issue-29485.rs.)

Failed merges:

 - #157485 (Rename `errors.rs` file to `diagnostics.rs`)
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Jun 5, 2026
…-first-arg, r=petrochenkov

delegation: do not always generate first argument

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

- If there is a single delegation and source function has first param, otherwise error is emitted,
- If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes rust-lang#154427. Part of rust-lang#118212.
r? @petrochenkov
@rust-bors rust-bors Bot merged commit 13dcb5e into rust-lang:main Jun 5, 2026
12 checks passed
@rustbot rustbot added this to the 1.98.0 milestone Jun 5, 2026
rust-timer added a commit that referenced this pull request Jun 5, 2026
Rollup merge of #156798 - aerooneqq:delegation-dont-generate-first-arg, r=petrochenkov

delegation: do not always generate first argument

This PR supports not generating delegation's "dead code" - situation when there is no parameters in a source function or we expanded a reuse of a static function without self, in this case we do not have to generate delegation's block even if the user has explicitly specified it.

We generate block:

- If there is a single delegation and source function has first param, otherwise error is emitted,
- If there is a glob delegation we generate block if the source function has first param and it is method or free function.

Fixes #154427. Part of #118212.
r? @petrochenkov
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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

[ICE]: Res::Err but no error emitted

3 participants