Skip to content

Point at unit structs on foreign crates in type errors when they are the pattern of a binding#153894

Merged
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
estebank:issue-129792
Mar 17, 2026
Merged

Point at unit structs on foreign crates in type errors when they are the pattern of a binding#153894
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
estebank:issue-129792

Conversation

@estebank
Copy link
Contributor

@estebank estebank commented Mar 15, 2026

Consts and unit structs in patterns can be confusing if they are mistaken for new bindings. We already provide some context for unit structs and consts that come from the current crate, we now also point at those from foreign crates, and we properly skip cases where the pattern has type parameters which can't be confused with a new binding. So not suggest making a new binding when other suggestions are already emitted, as the likelihood of the other suggestions being what the user intended is higher. Make new binding suggestion verbose.

Fix #129792.

error[E0308]: mismatched types
 --> fi.rs:8:9
  |
1 | struct percentage;
  | ----------------- unit struct defined here
...
8 |     let percentage = 4i32;
  |         ^^^^^^^^^^   ---- this expression has type `i32`
  |         |
  |         expected `i32`, found `percentage`
  |         `percentage` is interpreted as a unit struct, not a new binding
help: introduce a new binding instead
  |
8 -     let percentage = 4i32;
8 +     let other_percentage = 4i32;
  |

…the pattern of a let binding

Consts and unit structs in patterns can be confusing if they are mistaken for new bindings. We already provide some context for unit structs and consts that come from the current crate, we now also point at those from foreign crates, and we properly skip cases where the pattern has type parameters which can't be confused with a new binding. Make new binding suggestion verbose.
@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 Mar 15, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 15, 2026

r? @nnethercote

rustbot has assigned @nnethercote.
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

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 15 candidates

@estebank estebank changed the title Point at unit structs on foreign crates in type errors when they are … Point at unit structs on foreign crates in type errors when they are the pattern of a let binding Mar 15, 2026
@estebank estebank changed the title Point at unit structs on foreign crates in type errors when they are the pattern of a let binding Point at unit structs on foreign crates in type errors when they are the pattern of a binding Mar 15, 2026
@nnethercote
Copy link
Contributor

The example from #129792 seems reasonable:

error[E0308]: mismatched types
 --> fi.rs:8:9
  |
1 | struct percentage;
  | ----------------- unit struct defined here
...
8 |     let percentage = 4i32;
  |         ^^^^^^^^^^   ---- this expression has type `i32`
  |         |
  |         expected `i32`, found `percentage`
  |         `percentage` is interpreted as a unit struct, not a new binding
  |         help: introduce a new binding instead: `other_percentage`

The use of a lower-case p on percentage leads to the type/binding name confusion. It's easy to imagine somebody thinking that percentage is a binding.

The example from this PR's description seems much less likely. Do we really think the problem in that code is that the user intended None to be a new binding? To me that's clearly just a type error caused by misunderstanding the Box, the extra information about the binding just confuses things, and suggesting other_none is not helpful.

@nnethercote nnethercote 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 Mar 15, 2026
@estebank
Copy link
Contributor Author

Agreed. The second commit uses the prior existence of suggestions as a signal that we shouldn't talk about introducing the new binding. The only case left in the test suite (other than the one in the ticket) is

error[E0308]: mismatched types
  --> $DIR/name-clash-nullary.rs:2:7
   |
LL |   let None: isize = 42;
   |       ^^^^  ----- expected due to this
   |       |
   |       expected `isize`, found `Option<_>`
   |       `None` is interpreted as a unit variant, not a new binding
   |
  --> $SRC_DIR/core/src/option.rs:LL:COL
   |
   = note: unit variant defined here
   |
   = note: expected type `isize`
              found enum `Option<_>`
help: introduce a new binding instead
   |
LL -   let None: isize = 42;
LL +   let other_none: isize = 42;
   |

and

error[E0308]: mismatched types
  --> $DIR/issue-33504.rs:7:13
   |
LL | struct Test;
   | ----------- unit struct defined here
...
LL |         let Test = 1;
   |             ^^^^   - this expression has type `{integer}`
   |             |
   |             expected integer, found `Test`
   |             `Test` is interpreted as a unit struct, not a new binding
   |
help: introduce a new binding instead
   |
LL -         let Test = 1;
LL +         let other_test = 1;
   |

Which I feel is the exact case we want to address, right? The only other thing I'd consider is making it so that in the cases where we're suggesting changing the case, we don't include the other_, but that's a very minor thing.

@estebank estebank 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 Mar 16, 2026
help: introduce a new binding instead
|
LL - BSTR_SIZED => {}
LL + other_bstr_sized => {}
Copy link
Contributor

Choose a reason for hiding this comment

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

This one feels marginal, and likewise the other ones in this test. I can imagine a user thinking this would match against b"012". But it's sufficiently broken thinking that it's hard to say for sure, so I can live with it.

Copy link
Contributor Author

@estebank estebank Mar 17, 2026

Choose a reason for hiding this comment

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

I'm currently looking at a completely different case, and maybe the suggestion I'm adding might also be relevant here?

error: constant of non-structural type `S` in a pattern
  --> $DIR/match_ice.rs:11:9
   |
LL | struct S;
   | -------- `S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: &S = &S;
   |     ----------- constant defined here
LL |     match C {
LL |         C => {}
   |         ^ constant of non-structural type
   |
   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: if `S` manually implemented `PartialEq`, you could check for equality
   |
LL -         C => {}
LL +         binding if binding == C => {}
   |

Note that the binding suggestion is pre-existing, it's just being made more obvious now.

@nnethercote
Copy link
Contributor

@bors r+ rollup

@rust-bors
Copy link
Contributor

rust-bors bot commented Mar 17, 2026

📌 Commit 408066f has been approved by nnethercote

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 Mar 17, 2026
Zalathar added a commit to Zalathar/rust that referenced this pull request Mar 17, 2026
Point at unit structs on foreign crates in type errors when they are the pattern of a binding

Consts and unit structs in patterns can be confusing if they are mistaken for new bindings. We already provide some context for unit structs and consts that come from the current crate, we now also point at those from foreign crates, and we properly skip cases where the pattern has type parameters which can't be confused with a new binding. So not suggest making a new binding when other suggestions are already emitted, as the likelihood of the other suggestions being what the user intended is higher. Make new binding suggestion verbose.

Fix rust-lang#129792.

```
error[E0308]: mismatched types
 --> fi.rs:8:9
  |
1 | struct percentage;
  | ----------------- unit struct defined here
...
8 |     let percentage = 4i32;
  |         ^^^^^^^^^^   ---- this expression has type `i32`
  |         |
  |         expected `i32`, found `percentage`
  |         `percentage` is interpreted as a unit struct, not a new binding
help: introduce a new binding instead
  |
8 -     let percentage = 4i32;
8 +     let other_percentage = 4i32;
  |
```
@rust-bors
Copy link
Contributor

rust-bors bot commented Mar 17, 2026

⌛ Testing commit 408066f with merge 501c798...

Workflow: https://github.com/rust-lang/rust/actions/runs/23190523244

rust-bors bot pushed a commit that referenced this pull request Mar 17, 2026
Point at unit structs on foreign crates in type errors when they are the pattern of a binding

Consts and unit structs in patterns can be confusing if they are mistaken for new bindings. We already provide some context for unit structs and consts that come from the current crate, we now also point at those from foreign crates, and we properly skip cases where the pattern has type parameters which can't be confused with a new binding. So not suggest making a new binding when other suggestions are already emitted, as the likelihood of the other suggestions being what the user intended is higher. Make new binding suggestion verbose.

Fix #129792.

```
error[E0308]: mismatched types
 --> fi.rs:8:9
  |
1 | struct percentage;
  | ----------------- unit struct defined here
...
8 |     let percentage = 4i32;
  |         ^^^^^^^^^^   ---- this expression has type `i32`
  |         |
  |         expected `i32`, found `percentage`
  |         `percentage` is interpreted as a unit struct, not a new binding
help: introduce a new binding instead
  |
8 -     let percentage = 4i32;
8 +     let other_percentage = 4i32;
  |
```
@JonathanBrouwer
Copy link
Contributor

Stuck
@bors yield

@rust-bors
Copy link
Contributor

rust-bors bot commented Mar 17, 2026

Auto build was cancelled. Cancelled workflows:

The next pull request likely to be tested is #154001.

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Mar 17, 2026
Point at unit structs on foreign crates in type errors when they are the pattern of a binding

Consts and unit structs in patterns can be confusing if they are mistaken for new bindings. We already provide some context for unit structs and consts that come from the current crate, we now also point at those from foreign crates, and we properly skip cases where the pattern has type parameters which can't be confused with a new binding. So not suggest making a new binding when other suggestions are already emitted, as the likelihood of the other suggestions being what the user intended is higher. Make new binding suggestion verbose.

Fix rust-lang#129792.

```
error[E0308]: mismatched types
 --> fi.rs:8:9
  |
1 | struct percentage;
  | ----------------- unit struct defined here
...
8 |     let percentage = 4i32;
  |         ^^^^^^^^^^   ---- this expression has type `i32`
  |         |
  |         expected `i32`, found `percentage`
  |         `percentage` is interpreted as a unit struct, not a new binding
help: introduce a new binding instead
  |
8 -     let percentage = 4i32;
8 +     let other_percentage = 4i32;
  |
```
rust-bors bot pushed a commit that referenced this pull request Mar 17, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - #153972 (stdarch subtree update)
 - #153801 (Add the option to run UI tests with the parallel frontend)
 - #153959 (Fix non-module `parent_module` in stripped cfg diagnostics)
 - #153967 (Tweak wording of failed predicate in inference error)
 - #152968 (Flip "region lattice" in RegionKind doc comment)
 - #153531 (Fix LegacyKeyValueFormat report from docker build: various)
 - #153622 (remove concept of soft-unstable features)
 - #153709 (Fix hypothetical ICE in `variances_of`)
 - #153884 (test `classify-runtime-const` for `f16`)
 - #153894 (Point at unit structs on foreign crates in type errors when they are the pattern of a binding)
 - #153920 (improve `#[track_caller]` invalid ABI error)
 - #153946 (dissolve `tests/ui/cross`)
 - #153965 (Fix minor kasan bugs)
 - #153991 (Small report_cycle refactor)
@rust-bors rust-bors bot merged commit a5e0306 into rust-lang:main Mar 17, 2026
11 of 12 checks passed
@rustbot rustbot added this to the 1.96.0 milestone Mar 17, 2026
github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Mar 18, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#153972 (stdarch subtree update)
 - rust-lang/rust#153801 (Add the option to run UI tests with the parallel frontend)
 - rust-lang/rust#153959 (Fix non-module `parent_module` in stripped cfg diagnostics)
 - rust-lang/rust#153967 (Tweak wording of failed predicate in inference error)
 - rust-lang/rust#152968 (Flip "region lattice" in RegionKind doc comment)
 - rust-lang/rust#153531 (Fix LegacyKeyValueFormat report from docker build: various)
 - rust-lang/rust#153622 (remove concept of soft-unstable features)
 - rust-lang/rust#153709 (Fix hypothetical ICE in `variances_of`)
 - rust-lang/rust#153884 (test `classify-runtime-const` for `f16`)
 - rust-lang/rust#153894 (Point at unit structs on foreign crates in type errors when they are the pattern of a binding)
 - rust-lang/rust#153920 (improve `#[track_caller]` invalid ABI error)
 - rust-lang/rust#153946 (dissolve `tests/ui/cross`)
 - rust-lang/rust#153965 (Fix minor kasan bugs)
 - rust-lang/rust#153991 (Small report_cycle refactor)
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Mar 18, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#153972 (stdarch subtree update)
 - rust-lang/rust#153801 (Add the option to run UI tests with the parallel frontend)
 - rust-lang/rust#153959 (Fix non-module `parent_module` in stripped cfg diagnostics)
 - rust-lang/rust#153967 (Tweak wording of failed predicate in inference error)
 - rust-lang/rust#152968 (Flip "region lattice" in RegionKind doc comment)
 - rust-lang/rust#153531 (Fix LegacyKeyValueFormat report from docker build: various)
 - rust-lang/rust#153622 (remove concept of soft-unstable features)
 - rust-lang/rust#153709 (Fix hypothetical ICE in `variances_of`)
 - rust-lang/rust#153884 (test `classify-runtime-const` for `f16`)
 - rust-lang/rust#153894 (Point at unit structs on foreign crates in type errors when they are the pattern of a binding)
 - rust-lang/rust#153920 (improve `#[track_caller]` invalid ABI error)
 - rust-lang/rust#153946 (dissolve `tests/ui/cross`)
 - rust-lang/rust#153965 (Fix minor kasan bugs)
 - rust-lang/rust#153991 (Small report_cycle refactor)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

Point at unit structs in type errors when they are the pattern of a let binding

4 participants