fix equatable_if_let: FP in const context
This commit is contained in:
parent
c48592eb49
commit
757bad7206
7 changed files with 131 additions and 2 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::is_in_const_context;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -110,7 +111,16 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
|
|||
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
|
||||
if is_structural_partial_eq(cx, exp_ty, pat_ty) && !contains_type_mismatch(cx, let_expr.pat) {
|
||||
if is_structural_partial_eq(cx, exp_ty, pat_ty)
|
||||
&& !contains_type_mismatch(cx, let_expr.pat)
|
||||
// Calls to trait methods (`PartialEq::eq` in this case) aren't stable yet. We could _technically_
|
||||
// try looking at whether:
|
||||
// 1) features `const_trait_impl` and `const_cmp` are enabled
|
||||
// 2) implementation of `PartialEq<Rhs=PatTy> for ExpTy` has `fn eq` that is `const`
|
||||
//
|
||||
// but that didn't quite work out (see #15482), so we just reject outright in this case
|
||||
&& !is_in_const_context(cx)
|
||||
{
|
||||
let pat_str = match let_expr.pat.kind {
|
||||
PatKind::Struct(..) => format!(
|
||||
"({})",
|
||||
|
|
|
|||
|
|
@ -139,3 +139,24 @@ mod issue8710 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PartialEq is not stable in consts yet
|
||||
fn issue15376() {
|
||||
enum NonConstEq {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
impl PartialEq for NonConstEq {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const N: NonConstEq = NonConstEq::A;
|
||||
|
||||
// `impl PartialEq` is not const, suggest `matches!`
|
||||
const _: u32 = if matches!(N, NonConstEq::A) { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
const _: u32 = if matches!(Some(N), Some(NonConstEq::A)) { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,3 +139,24 @@ mod issue8710 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PartialEq is not stable in consts yet
|
||||
fn issue15376() {
|
||||
enum NonConstEq {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
impl PartialEq for NonConstEq {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const N: NonConstEq = NonConstEq::A;
|
||||
|
||||
// `impl PartialEq` is not const, suggest `matches!`
|
||||
const _: u32 = if let NonConstEq::A = N { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
const _: u32 = if let Some(NonConstEq::A) = Some(N) { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,5 +103,17 @@ error: this pattern matching can be expressed using `matches!`
|
|||
LL | if let Some(MyEnum::B) = get_enum() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))`
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let.rs:158:23
|
||||
|
|
||||
LL | const _: u32 = if let NonConstEq::A = N { 0 } else { 1 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(N, NonConstEq::A)`
|
||||
|
||||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let.rs:160:23
|
||||
|
|
||||
LL | const _: u32 = if let Some(NonConstEq::A) = Some(N) { 0 } else { 1 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(N), Some(NonConstEq::A))`
|
||||
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
|
|
|
|||
24
tests/ui/equatable_if_let_const_cmp.fixed
Normal file
24
tests/ui/equatable_if_let_const_cmp.fixed
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#![warn(clippy::equatable_if_let)]
|
||||
#![allow(clippy::eq_op)]
|
||||
#![feature(const_trait_impl, const_cmp)]
|
||||
|
||||
fn issue15376() {
|
||||
enum ConstEq {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
impl const PartialEq for ConstEq {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const C: ConstEq = ConstEq::A;
|
||||
|
||||
// `impl PartialEq` is const... but we still suggest `matches!` for now
|
||||
// TODO: detect this and suggest `=`
|
||||
const _: u32 = if matches!(C, ConstEq::A) { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
const _: u32 = if matches!(Some(C), Some(ConstEq::A)) { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
}
|
||||
24
tests/ui/equatable_if_let_const_cmp.rs
Normal file
24
tests/ui/equatable_if_let_const_cmp.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#![warn(clippy::equatable_if_let)]
|
||||
#![allow(clippy::eq_op)]
|
||||
#![feature(const_trait_impl, const_cmp)]
|
||||
|
||||
fn issue15376() {
|
||||
enum ConstEq {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
impl const PartialEq for ConstEq {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
const C: ConstEq = ConstEq::A;
|
||||
|
||||
// `impl PartialEq` is const... but we still suggest `matches!` for now
|
||||
// TODO: detect this and suggest `=`
|
||||
const _: u32 = if let ConstEq::A = C { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
const _: u32 = if let Some(ConstEq::A) = Some(C) { 0 } else { 1 };
|
||||
//~^ ERROR: this pattern matching can be expressed using `matches!`
|
||||
}
|
||||
17
tests/ui/equatable_if_let_const_cmp.stderr
Normal file
17
tests/ui/equatable_if_let_const_cmp.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let_const_cmp.rs:20:23
|
||||
|
|
||||
LL | const _: u32 = if let ConstEq::A = C { 0 } else { 1 };
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try: `matches!(C, ConstEq::A)`
|
||||
|
|
||||
= note: `-D clippy::equatable-if-let` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]`
|
||||
|
||||
error: this pattern matching can be expressed using `matches!`
|
||||
--> tests/ui/equatable_if_let_const_cmp.rs:22:23
|
||||
|
|
||||
LL | const _: u32 = if let Some(ConstEq::A) = Some(C) { 0 } else { 1 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(C), Some(ConstEq::A))`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue