diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index e578fbf6d68..8fddcb84922 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -10,6 +10,7 @@ use syntax::ast::LitKind; use syntax::codemap::Span; use utils::paths; use utils::{match_type, snippet, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block}; +use utils::sugg::Sugg; /// **What it does:** This lint checks for matches with a single arm where an `if let` will usually suffice. /// @@ -262,8 +263,9 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, ".."))) } (true, false) => { - Some(format!("try\nif !{} {}", - snippet(cx, ex.span, "b"), + let test = &Sugg::hir(cx, ex, ".."); + Some(format!("if {} {}", + !test, expr_block(cx, false_expr, None, ".."))) } (true, true) => None, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 6667598b009..f4b359b35de 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -123,6 +123,13 @@ impl<'a, 'b> std::ops::Sub<&'b Sugg<'b>> for &'a Sugg<'a> { } } +impl<'a> std::ops::Not for &'a Sugg<'a> { + type Output = Sugg<'static>; + fn not(self) -> Sugg<'static> { + make_unop("!", self) + } +} + struct ParenHelper { paren: bool, wrapped: T, @@ -147,6 +154,15 @@ impl std::fmt::Display for ParenHelper { } } +/// Build the string for ` ` adding parenthesis when necessary. +/// +/// For convenience, the operator is taken as a string because all unary operators have the same +/// precedence. +pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> { + let needs_paren = !matches!(*expr, Sugg::NonParen(..)); + Sugg::MaybeParen(format!("{}{}", op, ParenHelper::new(needs_paren, expr)).into()) +} + /// Build the string for ` ` adding parenthesis when necessary. /// /// Precedence of shift operator relative to other arithmetic operation is often confusing so diff --git a/tests/compile-fail/matches.rs b/tests/compile-fail/matches.rs index 989106a5a16..e49aeaa6ec8 100644 --- a/tests/compile-fail/matches.rs +++ b/tests/compile-fail/matches.rs @@ -130,7 +130,7 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression //~| HELP try - //~^^ SUGGESTION if !test { println!("Noooo!"); }; + //~| SUGGESTION if !test { println!("Noooo!"); }; true => (), false => { println!("Noooo!"); } }; @@ -138,7 +138,16 @@ fn match_bool() { match test { //~^ ERROR you seem to be trying to match on a boolean expression //~| HELP try - //~^^ SUGGESTION if !test { println!("Noooo!"); }; + //~| SUGGESTION if !test { println!("Noooo!"); }; + false => { println!("Noooo!"); } + _ => (), + }; + + match test && test { + //~^ ERROR you seem to be trying to match on a boolean expression + //~| HELP try + //~| SUGGESTION if !(test && test) { println!("Noooo!"); }; + //~| ERROR equal expressions as operands false => { println!("Noooo!"); } _ => (), };