Auto merge of #154010 - estebank:issue-42753, r=nnethercote

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

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 rust-lang/rust#42753.
This commit is contained in:
bors
2026-03-26 05:30:08 +00:00
22 changed files with 658 additions and 13 deletions
+100 -2
View File
@@ -1053,17 +1053,115 @@ pub(crate) struct TypeNotStructural<'tcx> {
#[primary_span]
#[label("constant of non-structural type")]
pub(crate) span: Span,
#[label("`{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns")]
#[label(
"{$is_local ->
*[true] `{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
[false] `{$ty}` is not usable in patterns
}"
)]
pub(crate) ty_def_span: Span,
pub(crate) ty: Ty<'tcx>,
#[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"
"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"
)]
pub(crate) manual_partialeq_impl_span: Option<Span>,
#[note(
"see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details"
)]
pub(crate) manual_partialeq_impl_note: bool,
#[subdiagnostic]
pub(crate) suggestion: Option<SuggestEq<'tcx>>,
pub(crate) is_local: bool,
}
#[derive(Subdiagnostic)]
pub(crate) enum SuggestEq<'tcx> {
#[multipart_suggestion(
"{$manual_partialeq_impl ->
[false] if `{$ty}` manually implemented `PartialEq`, you could add
*[true] add
} a condition to the match arm checking for equality",
applicability = "maybe-incorrect",
style = "verbose"
)]
AddIf {
#[suggestion_part(code = "binding")]
pat_span: Span,
#[suggestion_part(code = " if binding == {name}")]
if_span: Span,
name: String,
ty: Ty<'tcx>,
manual_partialeq_impl: bool,
},
#[multipart_suggestion(
"{$manual_partialeq_impl ->
[false] if `{$ty}` manually implemented `PartialEq`, you could add
*[true] add
} a check for equality to the condition of the match arm",
applicability = "maybe-incorrect",
style = "verbose"
)]
AddToIf {
#[suggestion_part(code = "binding")]
pat_span: Span,
#[suggestion_part(code = " && binding == {name}")]
span: Span,
name: String,
ty: Ty<'tcx>,
manual_partialeq_impl: bool,
},
#[multipart_suggestion(
"{$manual_partialeq_impl ->
[false] if `{$ty}` manually implemented `PartialEq`, you could check
*[true] check
} for equality instead of pattern matching",
applicability = "maybe-incorrect",
style = "verbose"
)]
AddToLetChain {
#[suggestion_part(code = "binding")]
pat_span: Span,
#[suggestion_part(code = " && binding == {name}")]
span: Span,
name: String,
ty: Ty<'tcx>,
manual_partialeq_impl: bool,
},
#[multipart_suggestion(
"{$manual_partialeq_impl ->
[false] if `{$ty}` manually implemented `PartialEq`, you could check
*[true] check
} for equality instead of pattern matching",
applicability = "maybe-incorrect",
style = "verbose"
)]
ReplaceWithEq {
#[suggestion_part(code = "")]
removal: Span,
#[suggestion_part(code = " == ")]
eq: Span,
ty: Ty<'tcx>,
manual_partialeq_impl: bool,
},
#[multipart_suggestion(
"{$manual_partialeq_impl ->
[false] if `{$ty}` manually implemented `PartialEq`, you could check
*[true] check
} for equality instead of pattern matching",
applicability = "maybe-incorrect",
style = "verbose"
)]
ReplaceLetElseWithIf {
#[suggestion_part(code = "if ")]
if_span: Span,
#[suggestion_part(code = " == ")]
eq: Span,
#[suggestion_part(code = " ")]
else_span: Span,
ty: Ty<'tcx>,
manual_partialeq_impl: bool,
},
}
#[derive(Diagnostic)]
@@ -22,7 +22,7 @@
use super::PatCtxt;
use crate::errors::{
ConstPatternDependsOnGenericParameter, CouldNotEvalConstPattern, InvalidPattern, NaNPattern,
PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern,
PointerPattern, SuggestEq, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern,
};
impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
@@ -224,13 +224,93 @@ fn valtree_to_pat(&self, value: ty::Value<'tcx>) -> Box<Pat<'tcx>> {
}
_ => (None, true),
};
let manual_partialeq_impl =
manual_partialeq_impl_note || manual_partialeq_impl_span.is_some();
let is_local = adt_def.did().is_local();
let ty_def_span = tcx.def_span(adt_def.did());
let suggestion = if let Ok(name) = tcx.sess.source_map().span_to_snippet(self.span)
&& (is_local || manual_partialeq_impl)
{
let mut hir_id = self.id;
while let hir::Node::Pat(pat) = tcx.parent_hir_node(hir_id) {
hir_id = pat.hir_id;
}
match tcx.parent_hir_node(hir_id) {
hir::Node::Arm(hir::Arm { pat, guard: None, .. }) => {
// Add an if condition to the match arm.
Some(SuggestEq::AddIf {
if_span: pat.span.shrink_to_hi(),
pat_span: self.span,
name,
ty,
manual_partialeq_impl,
})
}
hir::Node::Arm(hir::Arm { guard: Some(guard), .. }) => {
// Modify the the match arm if condition and add a check for equality.
Some(SuggestEq::AddToIf {
span: guard.span.shrink_to_hi(),
pat_span: self.span,
name,
ty,
manual_partialeq_impl,
})
}
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Let(let_expr),
span,
..
}) => {
if let_expr.pat.span == self.span {
// `if let CONST = expr` -> `if CONST == expr`.
Some(SuggestEq::ReplaceWithEq {
removal: span.until(self.span),
eq: self.span.between(let_expr.init.span),
ty,
manual_partialeq_impl,
})
} else if tcx.sess.edition().at_least_rust_2024() {
// `if let Some(CONST) = expr` ->
// `if let Some(binding) = expr && binding == CONST`.
Some(SuggestEq::AddToLetChain {
span: span.shrink_to_hi(),
pat_span: self.span,
name,
ty,
manual_partialeq_impl,
})
} else {
None
}
}
hir::Node::LetStmt(let_stmt)
if let Some(init) = let_stmt.init
&& let Some(els) = let_stmt.els
&& init.span.ctxt().is_root()
&& els.span.ctxt().is_root() =>
{
// `let PAT = expr else {` -> `if PAT == expr {`.
Some(SuggestEq::ReplaceLetElseWithIf {
if_span: let_stmt.span.until(let_stmt.pat.span),
eq: let_stmt.pat.span.between(init.span),
else_span: init.span.between(els.span),
ty,
manual_partialeq_impl,
})
}
_ => None,
}
} else {
None
};
let err = TypeNotStructural {
span,
ty,
ty_def_span,
manual_partialeq_impl_span,
manual_partialeq_impl_note,
is_local,
suggestion,
};
return self.mk_err(tcx.dcx().create_err(err), ty);
}
@@ -14,7 +14,7 @@ fn main() {
}
match None {
<Defaulted as consts::AssocConst>::SOME => panic!(),
<Defaulted as consts::AssocConst>::SOME => panic!(),
//~^ ERROR constant of non-structural type `CustomEq` in a pattern
_ => {}
}
@@ -7,28 +7,38 @@ LL | consts::SOME => panic!(),
::: $DIR/auxiliary/consts.rs:1:1
|
LL | pub struct CustomEq;
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
| ------------------- `CustomEq` is not usable in patterns
...
LL | pub const SOME: Option<CustomEq> = Some(CustomEq);
| -------------------------------- constant defined here
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - consts::SOME => panic!(),
LL + binding if binding == consts::SOME => panic!(),
|
error: constant of non-structural type `CustomEq` in a pattern
--> $DIR/cross-crate-fail.rs:17:9
|
LL | <Defaulted as consts::AssocConst>::SOME => panic!(),
LL | <Defaulted as consts::AssocConst>::SOME => panic!(),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
|
::: $DIR/auxiliary/consts.rs:1:1
|
LL | pub struct CustomEq;
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
| ------------------- `CustomEq` is not usable in patterns
...
LL | const SOME: Option<CustomEq> = Some(CustomEq);
| ---------------------------- constant defined here
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - <Defaulted as consts::AssocConst>::SOME => panic!(),
LL + binding if binding == <Defaulted as consts::AssocConst>::SOME => panic!(),
|
error: aborting due to 2 previous errors
@@ -11,6 +11,11 @@ LL | BAR_BAZ => panic!(),
| ^^^^^^^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - BAR_BAZ => panic!(),
LL + binding if binding == BAR_BAZ => panic!(),
|
error: aborting due to 1 previous error
@@ -14,6 +14,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
LL + match Derive::Some(NoDerive) { binding if binding == ENUM => dbg!(ENUM), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:65:28
@@ -31,6 +36,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
LL + match Some(NoDerive) { binding if binding == FIELD => dbg!(FIELD), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:71:27
@@ -48,6 +58,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
LL + match Some(NoDerive) {binding if binding == INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:76:36
@@ -65,6 +80,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
LL + match (None, Some(NoDerive)) { binding if binding == TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:81:28
@@ -82,6 +102,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
LL + match Some(NoDerive) { binding if binding == TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:86:36
@@ -99,6 +124,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
LL + match [None, Some(NoDerive)] { binding if binding == ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:91:33
@@ -116,6 +146,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
LL + match [Some(NoDerive); 2] { binding if binding == REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:97:28
@@ -134,6 +169,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
LL + match Some(NoDerive) { binding if binding == NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:102:28
@@ -151,6 +191,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
LL + match Some(NoDerive) { binding if binding == BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
|
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:107:29
@@ -168,6 +213,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
LL + match &Some(NoDerive) { binding if binding == ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
|
error: aborting due to 10 previous errors
@@ -0,0 +1,50 @@
//@ edition:2024
// #42753
mod partial_eq {
struct S;
impl PartialEq<S> for S {
fn eq(&self, _: &S) -> bool {
true
}
}
const C: S = S;
const V: Vec<()> = vec![];
fn foo() {
match Some(S) {
Some(C) => {} //~ ERROR: constant of non-structural type
Some(C) if true => {} //~ ERROR: constant of non-structural type
None => {}
}
if let Some(C) = Some(S) {} //~ ERROR: constant of non-structural type
if let Some(C) = Some(S) && let Some(1) = Some(2) {} //~ ERROR: constant of non-structural type
let Some(C) = Some(S) else { return; }; //~ ERROR: constant of non-structural type
match vec![] {
V => {} //~ ERROR: constant of non-structural type
_ => {}
}
if let V = vec![] {} //~ ERROR: constant of non-structural type
let V = vec![] else { return; }; //~ ERROR: constant of non-structural type
let V = Vec::new() else { return; }; //~ ERROR: constant of non-structural type
}
}
mod not_partial_eq {
struct S;
const C: S = S;
fn foo() {
match Some(S) {
Some(C) => {} //~ ERROR: constant of non-structural type
Some(C) if true => {} //~ ERROR: constant of non-structural type
None => {}
}
if let Some(C) = Some(S) {} //~ ERROR: constant of non-structural type
if let Some(C) = Some(S) && let Some(1) = Some(2) {} //~ ERROR: constant of non-structural type
let Some(C) = Some(S) else { return; }; //~ ERROR: constant of non-structural type
}
}
fn main() {}
@@ -0,0 +1,282 @@
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:17: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) if true => {}
| ^ 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 check for equality to the condition of the match arm
|
LL - Some(C) if true => {}
LL + Some(binding) if true && binding == C => {}
|
error: constant of non-structural type `partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:20:21
|
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 | if let Some(C) = Some(S) {}
| ^ 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 - if let Some(C) = Some(S) {}
LL + if let Some(binding) = Some(S) && binding == C {}
|
error: constant of non-structural type `partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:21:21
|
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 | if let Some(C) = Some(S) && let Some(1) = Some(2) {}
| ^ 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 - if let Some(C) = Some(S) && let Some(1) = Some(2) {}
LL + if let Some(binding) = Some(S) && binding == C && let Some(1) = Some(2) {}
|
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; };
|
error: constant of non-structural type `Vec<()>` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:24:13
|
LL | const V: Vec<()> = vec![];
| ---------------- constant defined here
...
LL | V => {}
| ^ constant of non-structural type
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - V => {}
LL + binding if binding == V => {}
|
error: constant of non-structural type `Vec<()>` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:27:16
|
LL | const V: Vec<()> = vec![];
| ---------------- constant defined here
...
LL | if let V = vec![] {}
| ^ constant of non-structural type
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: constant of non-structural type `Vec<()>` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:28:13
|
LL | const V: Vec<()> = vec![];
| ---------------- constant defined here
...
LL | let V = vec![] else { return; };
| ^ constant of non-structural type
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: constant of non-structural type `Vec<()>` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:29:13
|
LL | const V: Vec<()> = vec![];
| ---------------- constant defined here
...
LL | let V = Vec::new() else { return; };
| ^ constant of non-structural type
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: check for equality instead of pattern matching
|
LL - let V = Vec::new() else { return; };
LL + if V == Vec::new() { return; };
|
error: constant of non-structural type `not_partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:40:18
|
LL | struct S;
| -------- `not_partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
LL |
LL | const C: S = S;
| ---------- constant defined here
...
LL | Some(C) => {}
| ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
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 `not_partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:41:18
|
LL | struct S;
| -------- `not_partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
LL |
LL | const C: S = S;
| ---------- constant defined here
...
LL | Some(C) if true => {}
| ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a check for equality to the condition of the match arm
|
LL - Some(C) if true => {}
LL + Some(binding) if true && binding == C => {}
|
error: constant of non-structural type `not_partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:44:21
|
LL | struct S;
| -------- `not_partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
LL |
LL | const C: S = S;
| ---------- constant defined here
...
LL | if let Some(C) = Some(S) {}
| ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: check for equality instead of pattern matching
|
LL - if let Some(C) = Some(S) {}
LL + if let Some(binding) = Some(S) && binding == C {}
|
error: constant of non-structural type `not_partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:45:21
|
LL | struct S;
| -------- `not_partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
LL |
LL | const C: S = S;
| ---------- constant defined here
...
LL | if let Some(C) = Some(S) && let Some(1) = Some(2) {}
| ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: check for equality instead of pattern matching
|
LL - if let Some(C) = Some(S) && let Some(1) = Some(2) {}
LL + if let Some(binding) = Some(S) && binding == C && let Some(1) = Some(2) {}
|
error: constant of non-structural type `not_partial_eq::S` in a pattern
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:46:18
|
LL | struct S;
| -------- `not_partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
LL |
LL | const C: S = S;
| ---------- constant defined here
...
LL | let Some(C) = Some(S) else { return; };
| ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: check for equality instead of pattern matching
|
LL - let Some(C) = Some(S) else { return; };
LL + if Some(C) == Some(S) { return; };
|
error: aborting due to 14 previous errors
+6 -1
View File
@@ -9,9 +9,14 @@ LL | FOO => todo!(),
|
--> $SRC_DIR/alloc/src/borrow.rs:LL:COL
|
= note: `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
= note: `Cow<'_, str>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - FOO => todo!(),
LL + binding if binding == FOO => todo!(),
|
error: aborting due to 1 previous error
+5
View File
@@ -11,6 +11,11 @@ LL | C => {}
| ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - C => {}
LL + binding if binding == C => {}
|
error: aborting due to 1 previous error
@@ -9,9 +9,14 @@ LL | EMPTY => {}
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
= note: `Vec<()>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: add a condition to the match arm checking for equality
|
LL - EMPTY => {}
LL + binding if binding == EMPTY => {}
|
error: aborting due to 1 previous error
+6 -1
View File
@@ -9,9 +9,14 @@ LL | if let CONST_STRING = empty_str {}
|
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<u8>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
= note: `Vec<u8>` is not usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
help: check for equality instead of pattern matching
|
LL - if let CONST_STRING = empty_str {}
LL + if CONST_STRING == empty_str {}
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq<usize> for MyType {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: check for equality instead of pattern matching
|
LL - if let CONSTANT = &&MyType {
LL + if CONSTANT == &&MyType {
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
LL + binding if binding == WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
LL + binding if binding == WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
LL + binding if binding == WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
LL + binding if binding == WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
LL + binding if binding == WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
LL + binding if binding == WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
error: aborting due to 1 previous error
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for B {
| ^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
LL + binding if binding == RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
error: constant of non-structural type `B` in a pattern
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:42:9
@@ -33,6 +38,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for B {
| ^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
LL + binding if binding == RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
|
error: aborting due to 2 previous errors
@@ -16,8 +16,8 @@ fn eq(&self, _: &Foo) -> bool {
fn main() {
let y = Foo { x: 1 };
match y {
FOO => { }
FOO => {}
//~^ ERROR constant of non-structural type `Foo` in a pattern
_ => { }
_ => {}
}
}
@@ -7,7 +7,7 @@ LL | struct Foo {
LL | const FOO: Foo = Foo { x: 0 };
| -------------- constant defined here
...
LL | FOO => { }
LL | FOO => {}
| ^^^ 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
@@ -15,6 +15,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
|
LL | impl PartialEq for Foo {
| ^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
|
LL - FOO => {}
LL + binding if binding == FOO => {}
|
error: aborting due to 1 previous error