Skip to content

Commit

Permalink
Auto merge of rust-lang#9368 - nahuakang:improve-equatable-if-let, r=…
Browse files Browse the repository at this point in the history
…flip1995

Improvement for  `equatable_if_let`

fixes rust-lang#9221

This PR makes sure that enums or structs not implementing `PartialEq` trait but still using the `if let` patterns can be linted to be rewritten with `matches!`.

If you added a new lint, here's a checklist for things that will be
checked during review or continuous integration.

- \[ ] Followed [lint naming conventions][lint_naming]
- \[x] Added passing UI tests (including committed `.stderr` file)
- \[x] `cargo test` passes locally
- \[ ] Executed `cargo dev update_lints`
- \[ ] Added lint documentation
- \[x] Run `cargo dev fmt`

---

changelog: Improve [`equatable_if_let`] with additional `matches!` suggestions.
  • Loading branch information
bors committed Oct 23, 2022
2 parents fe57ab7 + 4eaadd6 commit 628a79d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 22 deletions.
27 changes: 19 additions & 8 deletions clippy_lints/src/equatable_if_let.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::implements_trait;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Pat, PatKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
Expand Down Expand Up @@ -67,16 +66,14 @@ fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: T

impl<'tcx> LateLintPass<'tcx> for PatternEquality {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if_chain! {
if !in_external_macro(cx.sess(), expr.span);
if let ExprKind::Let(let_expr) = expr.kind;
if unary_pattern(let_expr.pat);
if !in_external_macro(cx.sess(), expr.span)
&& let ExprKind::Let(let_expr) = expr.kind
&& unary_pattern(let_expr.pat) {
let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
if is_structural_partial_eq(cx, exp_ty, pat_ty);
then {
let mut applicability = Applicability::MachineApplicable;

let mut applicability = Applicability::MachineApplicable;
if is_structural_partial_eq(cx, exp_ty, pat_ty) {
let pat_str = match let_expr.pat.kind {
PatKind::Struct(..) => format!(
"({})",
Expand All @@ -96,6 +93,20 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
),
applicability,
);
} else {
span_lint_and_sugg(
cx,
EQUATABLE_IF_LET,
expr.span,
"this pattern matching can be expressed using `matches!`",
"try",
format!(
"matches!({}, {})",
snippet_with_context(cx, let_expr.init.span, expr.span.ctxt(), "..", &mut applicability).0,
snippet_with_context(cx, let_expr.pat.span, expr.span.ctxt(), "..", &mut applicability).0,
),
applicability,
);
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions tests/ui/equatable_if_let.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ struct Struct {
b: bool,
}

struct NoPartialEqStruct {
a: i32,
b: bool,
}

enum NotPartialEq {
A,
B,
Expand All @@ -47,6 +52,7 @@ fn main() {
let e = Enum::UnitVariant;
let f = NotPartialEq::A;
let g = NotStructuralEq::A;
let h = NoPartialEqStruct { a: 2, b: false };

// true

Expand All @@ -66,10 +72,11 @@ fn main() {
if let Some(3 | 4) = c {}
if let Struct { a, b: false } = d {}
if let Struct { a: 2, b: x } = d {}
if let NotPartialEq::A = f {}
if matches!(f, NotPartialEq::A) {}
if g == NotStructuralEq::A {}
if let Some(NotPartialEq::A) = Some(f) {}
if matches!(Some(f), Some(NotPartialEq::A)) {}
if Some(g) == Some(NotStructuralEq::A) {}
if matches!(h, NoPartialEqStruct { a: 2, b: false }) {}

macro_rules! m1 {
(x) => {
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/equatable_if_let.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ struct Struct {
b: bool,
}

struct NoPartialEqStruct {
a: i32,
b: bool,
}

enum NotPartialEq {
A,
B,
Expand All @@ -47,6 +52,7 @@ fn main() {
let e = Enum::UnitVariant;
let f = NotPartialEq::A;
let g = NotStructuralEq::A;
let h = NoPartialEqStruct { a: 2, b: false };

// true

Expand All @@ -70,6 +76,7 @@ fn main() {
if let NotStructuralEq::A = g {}
if let Some(NotPartialEq::A) = Some(f) {}
if let Some(NotStructuralEq::A) = Some(g) {}
if let NoPartialEqStruct { a: 2, b: false } = h {}

macro_rules! m1 {
(x) => {
Expand Down
42 changes: 30 additions & 12 deletions tests/ui/equatable_if_let.stderr
Original file line number Diff line number Diff line change
@@ -1,70 +1,88 @@
error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:53:8
--> $DIR/equatable_if_let.rs:59:8
|
LL | if let 2 = a {}
| ^^^^^^^^^ help: try: `a == 2`
|
= note: `-D clippy::equatable-if-let` implied by `-D warnings`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:54:8
--> $DIR/equatable_if_let.rs:60:8
|
LL | if let Ordering::Greater = a.cmp(&b) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:55:8
--> $DIR/equatable_if_let.rs:61:8
|
LL | if let Some(2) = c {}
| ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:56:8
--> $DIR/equatable_if_let.rs:62:8
|
LL | if let Struct { a: 2, b: false } = d {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:57:8
--> $DIR/equatable_if_let.rs:63:8
|
LL | if let Enum::TupleVariant(32, 64) = e {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:58:8
--> $DIR/equatable_if_let.rs:64:8
|
LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:59:8
--> $DIR/equatable_if_let.rs:65:8
|
LL | if let Enum::UnitVariant = e {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:60:8
--> $DIR/equatable_if_let.rs:66:8
|
LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`

error: this pattern matching can be expressed using `matches!`
--> $DIR/equatable_if_let.rs:75:8
|
LL | if let NotPartialEq::A = f {}
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:70:8
--> $DIR/equatable_if_let.rs:76:8
|
LL | if let NotStructuralEq::A = g {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`

error: this pattern matching can be expressed using `matches!`
--> $DIR/equatable_if_let.rs:77:8
|
LL | if let Some(NotPartialEq::A) = Some(f) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:72:8
--> $DIR/equatable_if_let.rs:78:8
|
LL | if let Some(NotStructuralEq::A) = Some(g) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`

error: this pattern matching can be expressed using equality
error: this pattern matching can be expressed using `matches!`
--> $DIR/equatable_if_let.rs:79:8
|
LL | if let NoPartialEqStruct { a: 2, b: false } = h {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`

error: this pattern matching can be expressed using equality
--> $DIR/equatable_if_let.rs:86:8
|
LL | if let m1!(x) = "abc" {
| ^^^^^^^^^^^^^^^^^^ help: try: `"abc" == m1!(x)`

error: aborting due to 11 previous errors
error: aborting due to 14 previous errors

0 comments on commit 628a79d

Please sign in to comment.