Skip to content

Conversation

@WaffleLapkin
Copy link
Member

@WaffleLapkin WaffleLapkin commented Oct 17, 2025

Previously we only used check_expr_coercible_to_type if we had an expectation (using check_expr_with_expectation(NoExpectation) otherwise). Normally that'd be fine, because without an expectation we can't insert a coercion anyway. However, for the case of never-to-any coercion specifically, we do insert it eagerly, so this prevents some code from compiling, for example:

((),) = (loop {},);

With this PR we are always using check_expr_coercible_to_type (using an infer var if there is no expectation), which allows slightly more code to compile.

Fixes #112856

r? BoxyUwU

@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. labels Oct 17, 2025
@rustbot
Copy link
Collaborator

rustbot commented Oct 17, 2025

BoxyUwU is currently at their maximum review capacity.
They may take a while to respond.

@WaffleLapkin WaffleLapkin added A-coercions Area: implicit and explicit `expr as Type` coercions F-never_type `#![feature(never_type)]` T-types Relevant to the types team, which will review and decide on the PR/issue. relnotes Marks issues that should be documented in the release notes of the next release. labels Oct 17, 2025

/// Returns a list of tuple type arguments, or `None` if `self` isn't a tuple.
#[inline]
pub fn tuple(self) -> Option<&'tcx List<Ty<'tcx>>> {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub fn tuple(self) -> Option<&'tcx List<Ty<'tcx>>> {
pub fn opt_tuple_fields(self) -> Option<&'tcx List<Ty<'tcx>>> {

seems like it does the same thing as tuple_fields it just doesnt panic

Copy link
Member Author

@WaffleLapkin WaffleLapkin Oct 26, 2025

Choose a reason for hiding this comment

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

That is indeed the case, is there a problem with that? In the code I wrote I found this a lot more convenient than checking the type first.

Copy link
Member

Choose a reason for hiding this comment

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

no it's fine I just found the differences in the names doesn't really reflect the differences in behaviour

Copy link
Member Author

Choose a reason for hiding this comment

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

If you have a better idea for the names I can rename them

Copy link
Member

Choose a reason for hiding this comment

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

i suggested a different name already :P

Copy link
Member Author

Choose a reason for hiding this comment

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

🤦🏻

I swear I sleep at night sometimes

Comment on lines 15 to 20
// This one can't work without a redesign on the coercion system.
// We currently only eagerly add never-to-any coercions, not any others.
// Thus, because we don't have an expectation when typechecking `&[]`,
// we don't add a coercion => this doesn't work.
let y = (&[],);
let _: (&[u8],) = y; //~ error: mismatched types
Copy link
Member

Choose a reason for hiding this comment

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

can you split the failing cases out to a different test so that the working stuff can be marked // @check-pass . It's also nice because this change probably needs an FCP because we start allowing more code to compile so having a simple "this is the test that now passes" is nice

Copy link
Member Author

Choose a reason for hiding this comment

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

I've split the tests

@BoxyUwU BoxyUwU added needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 25, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Oct 25, 2025

@bors try @rust-timer queue

should crater this as it is theoretically breaking, though I don't actually expect any breakage here 🤔

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Oct 25, 2025
Always make tuple elements a coercion site
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 25, 2025
@BoxyUwU BoxyUwU 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 Oct 25, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Oct 25, 2025

When we stabilize the never type do we intend to change how NeverToAny coercions work? Will we continue unconditionally coercing ! to an inference variable, or will we stop doing that? Or in other words, is the stable behaviour here the behaviour we'd expect to have once never type is stabilized?

@rust-bors
Copy link

rust-bors bot commented Oct 25, 2025

☀️ Try build successful (CI)
Build commit: f77b5bc (f77b5bc6c7c84df104f86b0dd01d9490e3923fa8, parent: 04ff05c9c0cfbca33115c5f1b8bb20a66a54b799)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (f77b5bc): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.1% [0.1%, 0.2%] 3
Regressions ❌
(secondary)
0.1% [0.0%, 0.1%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.0% [-0.0%, -0.0%] 1
All ❌✅ (primary) 0.1% [0.1%, 0.2%] 3

Max RSS (memory usage)

Results (primary 1.4%, secondary -1.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
1.4% [0.8%, 2.1%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.2% [-1.2%, -1.2%] 1
All ❌✅ (primary) 1.4% [0.8%, 2.1%] 2

Cycles

Results (primary -2.1%, secondary -3.8%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-2.1% [-2.1%, -2.1%] 1
Improvements ✅
(secondary)
-3.8% [-5.3%, -2.1%] 4
All ❌✅ (primary) -2.1% [-2.1%, -2.1%] 1

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 473.373s -> 475.58s (0.47%)
Artifact size: 390.48 MiB -> 390.48 MiB (-0.00%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Oct 25, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Oct 25, 2025

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-147834 created and queued.
🤖 Automatically detected try build f77b5bc
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 25, 2025
@WaffleLapkin
Copy link
Member Author

When we stabilize the never type do we intend to change how NeverToAny coercions work? Will we continue unconditionally coercing ! to an inference variable, or will we stop doing that? Or in other words, is the stable behaviour here the behaviour we'd expect to have once never type is stabilized?

I don't expect / haven't heard of any desire to make any changes with how we insert NeverToAny coercions.

@rustbot
Copy link
Collaborator

rustbot commented Oct 26, 2025

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.

@craterbot
Copy link
Collaborator

🚧 Experiment pr-147834 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot
Copy link
Collaborator

🎉 Experiment pr-147834 is completed!
📊 2 regressed and 3 fixed (723906 total)
📊 1851 spurious results on the retry-regessed-list.txt, consider a retry1 if this is a significant amount.
📰 Open the summary report.

⚠️ If you notice any spurious failure please add them to the denylist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

Footnotes

  1. re-run the experiment with crates=https://crater-reports.s3.amazonaws.com/pr-147834/retry-regressed-list.txt

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Oct 28, 2025
@WaffleLapkin
Copy link
Member Author

@craterbot
Copy link
Collaborator

👌 Experiment pr-147834-1 created and queued.
🤖 Automatically detected try build f77b5bc
⚠️ Try build based on commit f43cd30, but latest commit is 74c8722. Did you forget to make a new try build?
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 29, 2025
@craterbot
Copy link
Collaborator

🚧 Experiment pr-147834-1 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot
Copy link
Collaborator

🎉 Experiment pr-147834-1 is completed!
📊 1 regressed and 0 fixed (1783 total)
📊 116 spurious results on the retry-regessed-list.txt, consider a retry1 if this is a significant amount.
📰 Open the summary report.

⚠️ If you notice any spurious failure please add them to the denylist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

Footnotes

  1. re-run the experiment with crates=https://crater-reports.s3.amazonaws.com/pr-147834-1/retry-regressed-list.txt

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Oct 29, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Oct 31, 2025

Hi @rust-lang/types.

Element expressions of tuples are currently coercion sites. The compiler currently assumes that when type checking tuple element exprs, if we have no expectation for what the type should be, that we don't need to try coercing to anything.

For example:

fn foo() {
    // compiles on stable, `a` has type `(!, ())`
    let a = (loop {}, ());
}

Here we have a tuple expr with no expectation for its type as the let has no type hint. This means that we don't try to coerce the ! type, if we were to try to coerce then we would get a NeverToAny coercion and allow the type of a to be a tuple (?x, ()) where ?x can be any type.

This can cause code to fail to compile that should compile:

fn foo() {
    // fails on stable
    let a = (loop {}, ());
    let a: (u8, ()) = a; // `(u8, ())` and `(!, ())` are different types
}

This is inconsistent with every other coercion site where coercions are unconditionally performed, for example array exprs:

// compiles on stable
fn foo() {
    let a = [loop {}];
    let a: [u8; 1] = a;
}

This PR causes us to start coercing tuple element exprs even when there is no expectation, so the previous code example now compiles:

fn foo() {
    // compiles on this PR
    let a = (loop {}, ()); // coerces to `(?x, ())`
    let a: (u8, ()) = a;
}

This is theoretically breaking as is any change where we change the results of type inference. It may also be breaking due to introducing more NeverToAny coercions which in older editions could cause fallback to () to occur when previously it would stay as !. In newer editions (2024+) it may simply cause problems by having inference variables around when previously we'd just have the ! type (even if we'll eventually fallback to !).

There was only one case of breakage actually found by crater. I've looked at it for not too long and couldn't see what the problem was. It occurs in macro code and the breakage went away after hand-expanding macros, I therefore assume this is the second case where fallback is now occuring in an older edition crate causing an () to appear when it shouldnt. I'm not sure why we're getting fallback though.

I think the theoretical breakage here is fine as the change in this PR is a clear bug fix in the current implementation of never type coercions. The actual breakage found by crater also seems somewhat fine to me (1 crate is not that many), though I would like to properly understand the breakage and open a PR fixing the crate before actually landing this.

@rfcbot fcp merge

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Oct 31, 2025

Team member @BoxyUwU has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Oct 31, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Oct 31, 2025

@rfcbot concern investigate and migrate broken crate

@BoxyUwU BoxyUwU added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-coercions Area: implicit and explicit `expr as Type` coercions disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. F-never_type `#![feature(never_type)]` needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. perf-regression Performance regression. proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. T-types Relevant to the types team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tuple elements are not considered a coercion site

6 participants