Skip to content

Suggest using equality comparison instead of pattern matching on non-structural constant in pattern#154010

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

Suggest using equality comparison instead of pattern matching on non-structural constant in pattern#154010
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
estebank:issue-42753

Conversation

@estebank
Copy link
Copy Markdown
Contributor

@estebank estebank commented Mar 17, 2026

When encountering a pattern containing a non-structural constant (not marked as #[derive(PartialEq)] to make it suitable for pattern matching, C in the examples below), we would previously not provide additional guidance. With this PR, the help in the following examples are added:

error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:16:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |             Some(C) => {}
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
   |
LL -             Some(C) => {}
LL +             Some(binding) if binding == C => {}
   |
error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:22:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |         let Some(C) = Some(S) else { return; };
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: check for equality instead of pattern matching
   |
LL -         let Some(C) = Some(S) else { return; };
LL +         if Some(C) == Some(S) { return; };
   |

The suggestion accounts for a few conditions:

  • if the type is not from the local crate and has no PartialEq impl, the user can't make it structural, so we don't provide the suggestion
  • regardless of whether the type is local or remote, if it has a manual PartialEq, explain that with a derived PartialEq you could use equality
  • if the type is local and has no impl, suggest adding a derived PartialEq and use equality check instead of pattern matching
  • when suggesting equality, account for if-let to suggest chaining (edition dependent), match arm with a present if check, match arm without an existing if check
  • when encountering let-else, we suggest turning it into an if expression instead (this doesn't check for additional bindings beyond the constant, which would suggest incorrect code in some more complex cases).

Fix #42753.

…strutural constant in pattern

```
error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:16:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |             Some(C) => {}
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
   |
LL -             Some(C) => {}
LL +             Some(binding) if binding == C => {}
   |
```
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 17, 2026

Some changes occurred in match checking

cc @Nadrieril

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

rustbot commented Mar 17, 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 14 candidates

@estebank estebank changed the title Suggest using equality comparison instead of pattern matching on non-… Suggest using equality comparison instead of pattern matching on non-structural constant in pattern Mar 17, 2026
…ural type const

```
error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:22:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |         let Some(C) = Some(S) else { return; };
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: check for equality instead of pattern matching
   |
LL -         let Some(C) = Some(S) else { return; };
LL +         if Some(C) == Some(S) { return; };
   |
```
@nnethercote
Copy link
Copy Markdown
Contributor

nnethercote commented Mar 19, 2026

Can you update the PR description to include more detail? I've read #42753, but links to issues aren't always helpful because they often include extraneous details. I also don't know how to interpret the two error outputs in the PR description. Are they new error messages? If so, how do they compare to the old error messages? I don't have enough context to proceed. Thanks.

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

rustbot commented Mar 19, 2026

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

@estebank
Copy link
Copy Markdown
Contributor Author

@nnethercote added some more context to the description, let me know if that sufficient, otherwise I can try to expand further.

@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 21, 2026
Copy link
Copy Markdown
Contributor

@nnethercote nnethercote left a comment

Choose a reason for hiding this comment

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

The expanded description was extremely helpful, thank you. There is a lot going on with this diagnostic!

Good enough as is, a couple of minor comments to consider, r=me either way.

View changes since this review

|
LL | pub struct CustomEq;
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
| ------------------- `CustomEq` is not usable in patterns
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.

This non-local case is tricky, because the other crate might be under the author's control and able to be changed. I guess it's impossible to know for sure.

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.

I was going back and forth on this one. I settled on "we're giving them a link to the docs". I was concerned with giving the impression to the user that they had to somehow fork their dep. We could instead say something like "CustomEq could be used in patterns if it was annotated with #[derive(PartialEq)]", but I fear that has the same problem.

help: add a condition to the match arm checking for equality
|
LL - BAR_BAZ => panic!(),
LL + binding if binding == BAR_BAZ => panic!(),
Copy link
Copy Markdown
Contributor

@nnethercote nnethercote Mar 24, 2026

Choose a reason for hiding this comment

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

It's a bit confusing that the error message suggests two separate ways of fixing this -- add derive(PartialEq) and use a match arm condition. Could the one-or-the-other nature be made clearer? Maybe by inserting "alternatively, " at the start of the help message?

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.

Ah, I was looking on how to address this. I'll follow up.

@nnethercote
Copy link
Copy Markdown
Contributor

@bors r+

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Mar 26, 2026

📌 Commit 801eafd 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 26, 2026
@rust-bors

This comment has been minimized.

@rust-bors rust-bors Bot added merged-by-bors This PR was explicitly merged by bors. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 26, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Mar 26, 2026

☀️ Test successful - CI
Approved by: nnethercote
Duration: 3h 11m 23s
Pushing 3ea2fbc to main...

@rust-bors rust-bors Bot merged commit 3ea2fbc into rust-lang:main Mar 26, 2026
12 checks passed
@rustbot rustbot added this to the 1.96.0 milestone Mar 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor

What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing 6d8bc65 (parent) -> 3ea2fbc (this PR)

Test differences

Show 5 test diffs

Stage 1

  • [ui] tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.rs: [missing] -> pass (J0)

Stage 2

  • [ui] tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.rs: [missing] -> pass (J1)

Additionally, 3 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard 3ea2fbcb2a872b7e1fa3cada256f8e97f9e6636f --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. dist-apple-various: 1h 49m -> 1h 24m (-22.8%)
  2. pr-check-1: 33m 49s -> 28m 20s (-16.2%)
  3. x86_64-gnu-miri: 1h 34m -> 1h 19m (-16.0%)
  4. aarch64-gnu-debug: 1h 19m -> 1h 7m (-15.5%)
  5. dist-aarch64-msvc: 1h 51m -> 1h 37m (-13.2%)
  6. i686-gnu-2: 1h 43m -> 1h 29m (-13.1%)
  7. dist-x86_64-apple: 2h -> 1h 44m (-12.8%)
  8. aarch64-gnu-llvm-21-2: 54m 25s -> 47m 47s (-12.2%)
  9. test-various: 2h 10m -> 1h 54m (-12.2%)
  10. i686-msvc-2: 2h 1m -> 2h 16m (+11.9%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (3ea2fbc): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

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

Max RSS (memory usage)

Results (primary 0.6%)

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

mean range count
Regressions ❌
(primary)
0.6% [0.6%, 0.6%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.6% [0.6%, 0.6%] 1

Cycles

Results (secondary 3.3%)

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)
3.3% [2.2%, 4.3%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

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

Bootstrap: 483.836s -> 485.545s (0.35%)
Artifact size: 395.09 MiB -> 395.12 MiB (0.01%)

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

Labels

merged-by-bors This PR was explicitly merged by bors. 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.

Error message when using non-derived constants from another crate in pattern matching is confusing

4 participants