Skip to content

Add T: PartialEq bounds to derived StructuralPartialEq impls.#156807

Open
kpreid wants to merge 1 commit into
rust-lang:mainfrom
kpreid:speq
Open

Add T: PartialEq bounds to derived StructuralPartialEq impls.#156807
kpreid wants to merge 1 commit into
rust-lang:mainfrom
kpreid:speq

Conversation

@kpreid

@kpreid kpreid commented May 21, 2026

Copy link
Copy Markdown
Contributor

View all comments

Fixes #147714.

This is a breaking change to fix a bug, so it will need a crater run if it is to be done at all.

The changes in const_to_pat.rs are entirely to avoid regressing diagnostic quality, and should not make any difference to what code is accepted. The changes in compute_applicable_impls_for_diagnostics and its callers are entirely to be able to reuse that algorithm for this purpose.

@rustbot label +T-lang

@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
@kpreid

kpreid commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

This PR is probably less correct than the just-posted #156809, because the documentation of StructuralPartialEq says that it ensures that “interpreting the value of the constant as a pattern is equivalent to calling PartialEq”, and so the trait bounds should require transitive StructuralPartialEq, not just that the applicable PartialEq impl is the derived one. Still, I'll leave this open until things settle down more.

Currently waiting on an answer to my question about a route to to fixing the diagnostics.

@rust-log-analyzer

This comment has been minimized.

@theemathas

Copy link
Copy Markdown
Contributor

Adding T: StructuralPartialEq bounds like in #156809 is incorrect. Consider the following code, which compiles in current stable rust, despite Box not implementing StructuralPartialEq:

const X: Option<Box<()>> = None;

fn main() {
    if let X = X {}
}

@theemathas

Copy link
Copy Markdown
Contributor

Relevant documentation: https://doc.rust-lang.org/nightly/reference/patterns.html#r-patterns.const

The StructuralPartialEq trait does not correspond to the concept of "structural equality" in the documentation. In fact, this concept of "structural equality" cannot be represented as a trait at all, due to the "active variant" clause for enums, which makes structural equality depend on the const's value, not just the type.

Instead, the StructuralPartialEq trait corresponds to some notion of "shallow" structural equality, which is not written down in the reference.

@kpreid

kpreid commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

I am working on improving this PR to prevent a diagnostic regression. I believe it is possible to do so cheaply by being a little more clever about which possible error to emit (among all the errors possible to produce from different elements of the valtree being converted to a pattern).

Fixes <rust-lang#147714>.

The changes in `const_to_pat.rs` are entirely to avoid regressing
diagnostic quality, and should not make any difference to what code is
accepted. The change in `compute_applicable_impls_for_diagnostics`
and its callers is entirely to be able to reuse that algorithm for this
purpose.
@kpreid

kpreid commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

Actually, I misunderstood the UI tests that showed the regression. The worse diagnostic is emitted in UI tests where there is a generic argument that doesn't derive(PartialEq) but which is not involved in the specific value of the constant, e.g. if a locally-defined enum shaped like Option<T> is instantiated as Option::<NonStructural>::None.

In this case, we used to hit the error branch in ConstToPat::unevaluated_to_pat() that checks the type, but we now hit the error branch in ConstToPat::valtree_to_pat() that checks the value and runs first, because valtree_to_pat() cares about exactly the StructuralPartialEq impl that we're constraining away in this PR.

I fixed that by adding a copy of the check that unevaluated_to_pat() does, early enough that we produce that error in the right cases.

This should now be ready for review, but I’ll see if PR CI has anything to say first.

@kpreid kpreid marked this pull request as ready for review May 26, 2026 00:39
@rustbot

rustbot commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Changes to the code generated for builtin derived traits.

cc @nnethercote

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. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 26, 2026
@rustbot

rustbot commented May 26, 2026

Copy link
Copy Markdown
Collaborator

r? @petrochenkov

rustbot has assigned @petrochenkov.
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 73 candidates
  • Random selection from 18 candidates

@theemathas

This comment has been minimized.

@craterbot

This comment has been minimized.

@theemathas

Copy link
Copy Markdown
Contributor

@bors try

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request May 26, 2026
Add `T: PartialEq` bounds to derived `StructuralPartialEq` impls.
@rust-bors

rust-bors Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 3857be5 (3857be5045fe74bd0f296f6f4c23db10f8857f73, parent: 31a9463c6e2794a59ce57a8f37abc6966afc2a58)

@theemathas

Copy link
Copy Markdown
Contributor

@craterbot check

@craterbot

Copy link
Copy Markdown
Collaborator

👌 Experiment pr-156807 created and queued.
🤖 Automatically detected try build 3857be5
🔍 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 May 26, 2026
@craterbot

Copy link
Copy Markdown
Collaborator

🚧 Experiment pr-156807 is now running

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

@rustbot rustbot added the T-lang Relevant to the language team label May 26, 2026
@craterbot

Copy link
Copy Markdown
Collaborator

🎉 Experiment pr-156807 is completed!
📊 2 regressed and 1 fixed (950352 total)
📊 5376 spurious results on the retry-regressed-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-156807/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 May 31, 2026
@theemathas

Copy link
Copy Markdown
Contributor

The regressions are spurious and unrelated to this PR.

@rustbot label +I-lang-nominated

I am nominating because this PR is a breaking change. This PR changes the behavior of derive(PartialEq). That is, given:

#[derive(PartialEq)]
struct Thing<T>(Option<T>);

Previously, the above code will cause Thing(None) to be usable as a const pattern as long as Thing<T> implements PartialEq in some way, regardless of whether this impl came from the derive or not. This PR causes Thing(None) to be usable as a const pattern only when the relevant PartialEq came from the derive.

See the reference for documentation on what's allowed as constant patterns. See the issue being fixed for compilable demonstration code that will be broken by this PR.

@rustbot rustbot added the I-lang-nominated Nominated for discussion during a lang team meeting. label May 31, 2026
@traviscross traviscross added the P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang label May 31, 2026
@petrochenkov petrochenkov added S-waiting-on-t-lang Status: Awaiting decision from T-lang and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 1, 2026
@traviscross

Copy link
Copy Markdown
Contributor

This makes sense to me. Good (and subtle) call, in particular, on the bound being T: PartialEq rather than T: StructuralPartialEq. Thanks to @kpreid and @theemathas on this.

@rfcbot fcp merge lang

@rust-rfcbot

rust-rfcbot commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

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

No concerns currently listed.

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!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
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 Jun 3, 2026
@scottmcm

scottmcm commented Jun 3, 2026

Copy link
Copy Markdown
Member

Note: neither of the two regressions from the crater run is real.

@theemathas

Copy link
Copy Markdown
Contributor

To clarify why this bound is correct: We want StructuralPartialEq to apply exactly at the same time that the derived PartialEq applies. That way, the promise made by StructuralPartialEq is always fulfilled by the derive.

@rust-rfcbot rust-rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Jun 3, 2026
@rust-rfcbot

Copy link
Copy Markdown
Collaborator

🔔 This is now entering its final comment period, as per the review above. 🔔

@nikomatsakis

Copy link
Copy Markdown
Contributor

@rfcbot reviewed

@traviscross traviscross added I-lang-radar Items that are on lang's radar and will need eventual work or consideration. and removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Jun 3, 2026
@tmandry

tmandry commented Jun 3, 2026

Copy link
Copy Markdown
Member

We want StructuralPartialEq to apply exactly at the same time that the derived PartialEq applies. That way, the promise made by StructuralPartialEq is always fulfilled by the derive.

In other words, iiuc, we want StructuralPartialEq to have the same bounds as PartialEq, so that the impls apply for the same types. That makes sense to me.

@rfcbot reviewed

@rust-rfcbot rust-rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Jun 13, 2026
@rust-rfcbot

Copy link
Copy Markdown
Collaborator

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

@kpreid

kpreid commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

@rustbot label -S-waiting-on-t-lang +S-waiting-on-review

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-t-lang Status: Awaiting decision from T-lang labels Jun 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. 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. T-lang Relevant to the language team to-announce Announce this issue on triage meeting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Const patterns can have different behavior from PartialEq, due to incorrect bounds in derive(PartialEq)