Skip to content

Commit 283f89d

Browse files
committed
WIP: fix const PartialEq check
before this, the lint would suggest `==` even for types that aren't `const PartialEq` still doesn't work on nested types for some reason
1 parent 3a02646 commit 283f89d

File tree

4 files changed

+101
-29
lines changed

4 files changed

+101
-29
lines changed

clippy_lints/src/equatable_if_let.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_errors::Applicability;
99
use rustc_hir::def_id::DefId;
1010
use rustc_hir::{Expr, ExprKind, Pat, PatKind};
1111
use rustc_lint::{LateContext, LateLintPass, LintContext};
12-
use rustc_middle::ty::{Ty, TyCtxt};
12+
use rustc_middle::ty::{Instance, Ty, TyCtxt};
1313
use rustc_session::impl_lint_pass;
1414

1515
declare_clippy_lint! {
@@ -68,10 +68,16 @@ impl PatternEquality {
6868
.is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()]))
6969
};
7070

71-
// TODO: add a MSRV test once `eq` becomes stably-const
7271
let eq_method_is_const = || {
73-
self.eq_method
74-
.is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv))
72+
if let Some(eq_method) = self.eq_method
73+
&& let args = cx.tcx.mk_args(&[ty.into(), other.into()])
74+
&& let Ok(Some(instance)) = Instance::try_resolve(cx.tcx, cx.typing_env(), eq_method, args)
75+
&& is_stable_const_fn(cx, instance.def_id(), self.msrv)
76+
{
77+
true
78+
} else {
79+
false
80+
}
7581
};
7682

7783
is_partial_eq() && (!is_in_const_context(cx) || eq_method_is_const())

tests/ui/equatable_if_let.fixed

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
clippy::needless_if
88
)]
99
#![warn(clippy::equatable_if_let)]
10+
#![feature(const_trait_impl, const_cmp)]
1011

1112
extern crate proc_macros;
1213
use proc_macros::{external, inline_macros};
@@ -140,8 +141,31 @@ mod issue8710 {
140141
}
141142
}
142143

144+
#[allow(irrefutable_let_patterns, clippy::partialeq_to_none, clippy::eq_op)]
143145
fn issue15376() {
144-
// PartialEq is not stable in consts yet
145-
const _: u32 = if matches!(None, Some(true)) { 0 } else { 1 };
146+
struct NonConstEq;
147+
148+
impl PartialEq for NonConstEq {
149+
fn eq(&self, _other: &Self) -> bool {
150+
true
151+
}
152+
}
153+
154+
const _: u32 = if matches!(NonConstEq, NonConstEq) { 0 } else { 1 };
155+
//~^ ERROR: this pattern matching can be expressed using `matches!`
156+
const _: u32 = if matches!(None, Some(NonConstEq)) { 0 } else { 1 };
146157
//~^ ERROR: this pattern matching can be expressed using `matches!`
158+
159+
struct ConstEq;
160+
161+
impl const PartialEq for ConstEq {
162+
fn eq(&self, _other: &Self) -> bool {
163+
true
164+
}
165+
}
166+
167+
const _: u32 = if ConstEq == ConstEq { 0 } else { 1 };
168+
//~^ ERROR: this pattern matching can be expressed using equality
169+
const _: u32 = if None == Some(ConstEq) { 0 } else { 1 };
170+
//~^ ERROR: this pattern matching can be expressed using equality
147171
}

tests/ui/equatable_if_let.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
clippy::needless_if
88
)]
99
#![warn(clippy::equatable_if_let)]
10+
#![feature(const_trait_impl, const_cmp)]
1011

1112
extern crate proc_macros;
1213
use proc_macros::{external, inline_macros};
@@ -140,8 +141,31 @@ mod issue8710 {
140141
}
141142
}
142143

144+
#[allow(irrefutable_let_patterns, clippy::partialeq_to_none, clippy::eq_op)]
143145
fn issue15376() {
144-
// PartialEq is not stable in consts yet
145-
const _: u32 = if let Some(true) = None { 0 } else { 1 };
146+
struct NonConstEq;
147+
148+
impl PartialEq for NonConstEq {
149+
fn eq(&self, _other: &Self) -> bool {
150+
true
151+
}
152+
}
153+
154+
const _: u32 = if let NonConstEq = NonConstEq { 0 } else { 1 };
155+
//~^ ERROR: this pattern matching can be expressed using `matches!`
156+
const _: u32 = if let Some(NonConstEq) = None { 0 } else { 1 };
146157
//~^ ERROR: this pattern matching can be expressed using `matches!`
158+
159+
struct ConstEq;
160+
161+
impl const PartialEq for ConstEq {
162+
fn eq(&self, _other: &Self) -> bool {
163+
true
164+
}
165+
}
166+
167+
const _: u32 = if let ConstEq = ConstEq { 0 } else { 1 };
168+
//~^ ERROR: this pattern matching can be expressed using equality
169+
const _: u32 = if let Some(ConstEq) = None { 0 } else { 1 };
170+
//~^ ERROR: this pattern matching can be expressed using equality
147171
}

tests/ui/equatable_if_let.stderr

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this pattern matching can be expressed using equality
2-
--> tests/ui/equatable_if_let.rs:64:8
2+
--> tests/ui/equatable_if_let.rs:65:8
33
|
44
LL | if let 2 = a {}
55
| ^^^^^^^^^ help: try: `a == 2`
@@ -8,106 +8,124 @@ LL | if let 2 = a {}
88
= help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]`
99

1010
error: this pattern matching can be expressed using equality
11-
--> tests/ui/equatable_if_let.rs:66:8
11+
--> tests/ui/equatable_if_let.rs:67:8
1212
|
1313
LL | if let Ordering::Greater = a.cmp(&b) {}
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
1515

1616
error: this pattern matching can be expressed using equality
17-
--> tests/ui/equatable_if_let.rs:68:8
17+
--> tests/ui/equatable_if_let.rs:69:8
1818
|
1919
LL | if let Some(2) = c {}
2020
| ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
2121

2222
error: this pattern matching can be expressed using equality
23-
--> tests/ui/equatable_if_let.rs:70:8
23+
--> tests/ui/equatable_if_let.rs:71:8
2424
|
2525
LL | if let Struct { a: 2, b: false } = d {}
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
2727

2828
error: this pattern matching can be expressed using equality
29-
--> tests/ui/equatable_if_let.rs:72:8
29+
--> tests/ui/equatable_if_let.rs:73:8
3030
|
3131
LL | if let Enum::TupleVariant(32, 64) = e {}
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
3333

3434
error: this pattern matching can be expressed using equality
35-
--> tests/ui/equatable_if_let.rs:74:8
35+
--> tests/ui/equatable_if_let.rs:75:8
3636
|
3737
LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {}
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
3939

4040
error: this pattern matching can be expressed using equality
41-
--> tests/ui/equatable_if_let.rs:76:8
41+
--> tests/ui/equatable_if_let.rs:77:8
4242
|
4343
LL | if let Enum::UnitVariant = e {}
4444
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
4545

4646
error: this pattern matching can be expressed using equality
47-
--> tests/ui/equatable_if_let.rs:78:8
47+
--> tests/ui/equatable_if_let.rs:79:8
4848
|
4949
LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
5050
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
5151

5252
error: this pattern matching can be expressed using `matches!`
53-
--> tests/ui/equatable_if_let.rs:88:8
53+
--> tests/ui/equatable_if_let.rs:89:8
5454
|
5555
LL | if let NotPartialEq::A = f {}
5656
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
5757

5858
error: this pattern matching can be expressed using equality
59-
--> tests/ui/equatable_if_let.rs:90:8
59+
--> tests/ui/equatable_if_let.rs:91:8
6060
|
6161
LL | if let NotStructuralEq::A = g {}
6262
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
6363

6464
error: this pattern matching can be expressed using `matches!`
65-
--> tests/ui/equatable_if_let.rs:92:8
65+
--> tests/ui/equatable_if_let.rs:93:8
6666
|
6767
LL | if let Some(NotPartialEq::A) = Some(f) {}
6868
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
6969

7070
error: this pattern matching can be expressed using equality
71-
--> tests/ui/equatable_if_let.rs:94:8
71+
--> tests/ui/equatable_if_let.rs:95:8
7272
|
7373
LL | if let Some(NotStructuralEq::A) = Some(g) {}
7474
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
7575

7676
error: this pattern matching can be expressed using `matches!`
77-
--> tests/ui/equatable_if_let.rs:96:8
77+
--> tests/ui/equatable_if_let.rs:97:8
7878
|
7979
LL | if let NoPartialEqStruct { a: 2, b: false } = h {}
8080
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
8181

8282
error: this pattern matching can be expressed using equality
83-
--> tests/ui/equatable_if_let.rs:99:8
83+
--> tests/ui/equatable_if_let.rs:100:8
8484
|
8585
LL | if let inline!("abc") = "abc" {
8686
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
8787

8888
error: this pattern matching can be expressed using `matches!`
89-
--> tests/ui/equatable_if_let.rs:109:12
89+
--> tests/ui/equatable_if_let.rs:110:12
9090
|
9191
LL | if let Some('i') = cs.iter().next() {
9292
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some('i'))`
9393

9494
error: this pattern matching can be expressed using `matches!`
95-
--> tests/ui/equatable_if_let.rs:117:12
95+
--> tests/ui/equatable_if_let.rs:118:12
9696
|
9797
LL | if let Some(1) = cs.iter().next() {
9898
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some(1))`
9999

100100
error: this pattern matching can be expressed using `matches!`
101-
--> tests/ui/equatable_if_let.rs:135:12
101+
--> tests/ui/equatable_if_let.rs:136:12
102102
|
103103
LL | if let Some(MyEnum::B) = get_enum() {
104104
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))`
105105

106106
error: this pattern matching can be expressed using `matches!`
107-
--> tests/ui/equatable_if_let.rs:145:23
107+
--> tests/ui/equatable_if_let.rs:154:23
108108
|
109-
LL | const _: u32 = if let Some(true) = None { 0 } else { 1 };
110-
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(None, Some(true))`
109+
LL | const _: u32 = if let NonConstEq = NonConstEq { 0 } else { 1 };
110+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(NonConstEq, NonConstEq)`
111111

112-
error: aborting due to 18 previous errors
112+
error: this pattern matching can be expressed using equality
113+
--> tests/ui/equatable_if_let.rs:156:23
114+
|
115+
LL | const _: u32 = if let Some(NonConstEq) = None { 0 } else { 1 };
116+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `None == Some(NonConstEq)`
117+
118+
error: this pattern matching can be expressed using equality
119+
--> tests/ui/equatable_if_let.rs:167:23
120+
|
121+
LL | const _: u32 = if let ConstEq = ConstEq { 0 } else { 1 };
122+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `ConstEq == ConstEq`
123+
124+
error: this pattern matching can be expressed using equality
125+
--> tests/ui/equatable_if_let.rs:169:23
126+
|
127+
LL | const _: u32 = if let Some(ConstEq) = None { 0 } else { 1 };
128+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `None == Some(ConstEq)`
129+
130+
error: aborting due to 21 previous errors
113131

0 commit comments

Comments
 (0)