Skip to content

Commit 757bad7

Browse files
committed
fix equatable_if_let: FP in const context
1 parent c48592e commit 757bad7

File tree

7 files changed

+131
-2
lines changed

7 files changed

+131
-2
lines changed

clippy_lints/src/equatable_if_let.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::is_in_const_context;
23
use clippy_utils::source::snippet_with_context;
34
use clippy_utils::ty::implements_trait;
45
use rustc_errors::Applicability;
@@ -110,7 +111,16 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
110111
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
111112
let mut applicability = Applicability::MachineApplicable;
112113

113-
if is_structural_partial_eq(cx, exp_ty, pat_ty) && !contains_type_mismatch(cx, let_expr.pat) {
114+
if is_structural_partial_eq(cx, exp_ty, pat_ty)
115+
&& !contains_type_mismatch(cx, let_expr.pat)
116+
// Calls to trait methods (`PartialEq::eq` in this case) aren't stable yet. We could _technically_
117+
// try looking at whether:
118+
// 1) features `const_trait_impl` and `const_cmp` are enabled
119+
// 2) implementation of `PartialEq<Rhs=PatTy> for ExpTy` has `fn eq` that is `const`
120+
//
121+
// but that didn't quite work out (see #15482), so we just reject outright in this case
122+
&& !is_in_const_context(cx)
123+
{
114124
let pat_str = match let_expr.pat.kind {
115125
PatKind::Struct(..) => format!(
116126
"({})",

tests/ui/equatable_if_let.fixed

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,24 @@ mod issue8710 {
139139
}
140140
}
141141
}
142+
143+
// PartialEq is not stable in consts yet
144+
fn issue15376() {
145+
enum NonConstEq {
146+
A,
147+
B,
148+
}
149+
impl PartialEq for NonConstEq {
150+
fn eq(&self, _other: &Self) -> bool {
151+
true
152+
}
153+
}
154+
155+
const N: NonConstEq = NonConstEq::A;
156+
157+
// `impl PartialEq` is not const, suggest `matches!`
158+
const _: u32 = if matches!(N, NonConstEq::A) { 0 } else { 1 };
159+
//~^ ERROR: this pattern matching can be expressed using `matches!`
160+
const _: u32 = if matches!(Some(N), Some(NonConstEq::A)) { 0 } else { 1 };
161+
//~^ ERROR: this pattern matching can be expressed using `matches!`
162+
}

tests/ui/equatable_if_let.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,24 @@ mod issue8710 {
139139
}
140140
}
141141
}
142+
143+
// PartialEq is not stable in consts yet
144+
fn issue15376() {
145+
enum NonConstEq {
146+
A,
147+
B,
148+
}
149+
impl PartialEq for NonConstEq {
150+
fn eq(&self, _other: &Self) -> bool {
151+
true
152+
}
153+
}
154+
155+
const N: NonConstEq = NonConstEq::A;
156+
157+
// `impl PartialEq` is not const, suggest `matches!`
158+
const _: u32 = if let NonConstEq::A = N { 0 } else { 1 };
159+
//~^ ERROR: this pattern matching can be expressed using `matches!`
160+
const _: u32 = if let Some(NonConstEq::A) = Some(N) { 0 } else { 1 };
161+
//~^ ERROR: this pattern matching can be expressed using `matches!`
162+
}

tests/ui/equatable_if_let.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,17 @@ error: this pattern matching can be expressed using `matches!`
103103
LL | if let Some(MyEnum::B) = get_enum() {
104104
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))`
105105

106-
error: aborting due to 17 previous errors
106+
error: this pattern matching can be expressed using `matches!`
107+
--> tests/ui/equatable_if_let.rs:158:23
108+
|
109+
LL | const _: u32 = if let NonConstEq::A = N { 0 } else { 1 };
110+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(N, NonConstEq::A)`
111+
112+
error: this pattern matching can be expressed using `matches!`
113+
--> tests/ui/equatable_if_let.rs:160:23
114+
|
115+
LL | const _: u32 = if let Some(NonConstEq::A) = Some(N) { 0 } else { 1 };
116+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(N), Some(NonConstEq::A))`
117+
118+
error: aborting due to 19 previous errors
107119

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![warn(clippy::equatable_if_let)]
2+
#![allow(clippy::eq_op)]
3+
#![feature(const_trait_impl, const_cmp)]
4+
5+
fn issue15376() {
6+
enum ConstEq {
7+
A,
8+
B,
9+
}
10+
impl const PartialEq for ConstEq {
11+
fn eq(&self, _other: &Self) -> bool {
12+
true
13+
}
14+
}
15+
16+
const C: ConstEq = ConstEq::A;
17+
18+
// `impl PartialEq` is const... but we still suggest `matches!` for now
19+
// TODO: detect this and suggest `=`
20+
const _: u32 = if matches!(C, ConstEq::A) { 0 } else { 1 };
21+
//~^ ERROR: this pattern matching can be expressed using `matches!`
22+
const _: u32 = if matches!(Some(C), Some(ConstEq::A)) { 0 } else { 1 };
23+
//~^ ERROR: this pattern matching can be expressed using `matches!`
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![warn(clippy::equatable_if_let)]
2+
#![allow(clippy::eq_op)]
3+
#![feature(const_trait_impl, const_cmp)]
4+
5+
fn issue15376() {
6+
enum ConstEq {
7+
A,
8+
B,
9+
}
10+
impl const PartialEq for ConstEq {
11+
fn eq(&self, _other: &Self) -> bool {
12+
true
13+
}
14+
}
15+
16+
const C: ConstEq = ConstEq::A;
17+
18+
// `impl PartialEq` is const... but we still suggest `matches!` for now
19+
// TODO: detect this and suggest `=`
20+
const _: u32 = if let ConstEq::A = C { 0 } else { 1 };
21+
//~^ ERROR: this pattern matching can be expressed using `matches!`
22+
const _: u32 = if let Some(ConstEq::A) = Some(C) { 0 } else { 1 };
23+
//~^ ERROR: this pattern matching can be expressed using `matches!`
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: this pattern matching can be expressed using `matches!`
2+
--> tests/ui/equatable_if_let_const_cmp.rs:20:23
3+
|
4+
LL | const _: u32 = if let ConstEq::A = C { 0 } else { 1 };
5+
| ^^^^^^^^^^^^^^^^^^ help: try: `matches!(C, ConstEq::A)`
6+
|
7+
= note: `-D clippy::equatable-if-let` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]`
9+
10+
error: this pattern matching can be expressed using `matches!`
11+
--> tests/ui/equatable_if_let_const_cmp.rs:22:23
12+
|
13+
LL | const _: u32 = if let Some(ConstEq::A) = Some(C) { 0 } else { 1 };
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(C), Some(ConstEq::A))`
15+
16+
error: aborting due to 2 previous errors
17+

0 commit comments

Comments
 (0)