Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rust-lang/rust-clippy
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: bc3a80ec4705115c4908eaffb8c41250a743ac13
Choose a base ref
..
head repository: rust-lang/rust-clippy
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3745d2307549e934d6be9b7a0a101b06da302ded
Choose a head ref
Showing with 69 additions and 43 deletions.
  1. +25 −43 clippy_lints/src/matches/redundant_guard.rs
  2. +22 −0 tests/ui/redundant_guard.fixed
  3. +22 −0 tests/ui/redundant_guard.rs
68 changes: 25 additions & 43 deletions clippy_lints/src/matches/redundant_guard.rs
Original file line number Diff line number Diff line change
@@ -197,48 +197,30 @@ fn emit_redundant_guard(

/// Checks if the given `Expr` can also be represented as a `Pat`.
fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
fn helper(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
for_each_expr(expr, |expr| {
let expr = expr.peel_blocks();
if match expr.kind {
ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat,
ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
// Allow ctors
matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..))
},
ExprKind::AddrOf(.., expr) => helper(cx, expr),
ExprKind::Array(exprs) | ExprKind::Tup(exprs) => {
for expr in exprs {
if !helper(cx, expr) {
return ControlFlow::Break(());
}
}

true
},
ExprKind::Struct(_, fields, None) => {
for field in fields {
if !helper(cx, field.expr) {
return ControlFlow::Break(());
}
}

true
},
ExprKind::Path(qpath) => {
// Can't compare a local with another local in a pat
!matches!(cx.qpath_res(&qpath, expr.hir_id), Res::Local(..))
},
ExprKind::Lit(..) => true,
_ => false,
} {
return ControlFlow::Continue(());
}

ControlFlow::Break(())
})
.is_none()
}
for_each_expr(expr, |expr| {
if match expr.kind {
ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat,
ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
// Allow ctors
matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..))
},
ExprKind::Path(qpath) => {
matches!(
cx.qpath_res(&qpath, expr.hir_id),
Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Ctor(..), ..),
)
},
ExprKind::AddrOf(..)
| ExprKind::Array(..)
| ExprKind::Tup(..)
| ExprKind::Struct(..)
| ExprKind::Lit(..) => true,
_ => false,
} {
return ControlFlow::Continue(());
}

helper(cx, expr)
ControlFlow::Break(())
})
.is_none()
}
22 changes: 22 additions & 0 deletions tests/ui/redundant_guard.fixed
Original file line number Diff line number Diff line change
@@ -81,9 +81,31 @@ fn main() {
}

// Do not lint

fn f(s: Option<std::ffi::OsString>) {
match s {
Some(x) if x == "a" => {},
_ => {},
}
}

struct S {
a: usize,
}

impl PartialEq for S {
fn eq(&self, _: &Self) -> bool {
true
}
}

impl Eq for S {}

static CONST_S: S = S { a: 1 };

fn g(opt_s: Option<S>) {
match opt_s {
Some(x) if x == CONST_S => {},
_ => {},
}
}
22 changes: 22 additions & 0 deletions tests/ui/redundant_guard.rs
Original file line number Diff line number Diff line change
@@ -81,9 +81,31 @@ fn main() {
}

// Do not lint

fn f(s: Option<std::ffi::OsString>) {
match s {
Some(x) if x == "a" => {},
_ => {},
}
}

struct S {
a: usize,
}

impl PartialEq for S {
fn eq(&self, _: &Self) -> bool {
true
}
}

impl Eq for S {}

static CONST_S: S = S { a: 1 };

fn g(opt_s: Option<S>) {
match opt_s {
Some(x) if x == CONST_S => {},
_ => {},
}
}