Handle methods with an immediate negation in the non-minimal boolean lint, fixes #1930.

This commit is contained in:
laurent 2017-11-07 21:43:24 +00:00
parent 088555c4ea
commit 82793768b7
3 changed files with 68 additions and 0 deletions

View File

@ -44,6 +44,13 @@
"boolean expressions that contain terminals which can be eliminated"
}
const METHODS_WITH_NEGATION: [(&str, &str); 4] = [
("is_some", "is_none"),
("is_none", "is_some"),
("is_err", "is_ok"),
("is_ok", "is_err"),
];
#[derive(Copy, Clone)]
pub struct NonminimalBool;
@ -396,6 +403,28 @@ fn bool_expr(&self, e: &Expr) {
}
}
}
fn handle_method_call_in_not(&mut self, e: &'tcx Expr, inner: &'tcx Expr) {
if let ExprMethodCall(ref path, _, _) = inner.node {
METHODS_WITH_NEGATION.iter().for_each(|&(method, negation_method)| {
if method == path.name.as_str() {
span_lint_and_then(
self.cx,
NONMINIMAL_BOOL,
e.span,
"this boolean expression can be simplified",
|db| {
db.span_suggestion(
e.span,
"try",
negation_method.to_owned()
);
}
)
}
})
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
@ -406,6 +435,7 @@ fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() {
self.handle_method_call_in_not(e, inner);
self.bool_expr(e);
} else {
walk_expr(self, e);

View File

@ -38,3 +38,17 @@ fn equality_stuff() {
let _ = a > b && a == b;
let _ = a != b || !(a != b || c == d);
}
#[allow(unused, many_single_char_names)]
fn methods_with_negation() {
let a: Option<i32> = unimplemented!();
let b: Result<i32, i32> = unimplemented!();
let _ = a.is_some();
let _ = !a.is_some();
let _ = a.is_none();
let _ = !a.is_none();
let _ = b.is_err();
let _ = !b.is_err();
let _ = b.is_ok();
let _ = !b.is_ok();
}

View File

@ -130,3 +130,27 @@ help: try
39 | let _ = !(a == b && c == d);
| ^^^^^^^^^^^^^^^^^^^
error: this boolean expression can be simplified
--> $DIR/booleans.rs:47:13
|
47 | let _ = !a.is_some();
| ^^^^^^^^^^^^ help: try: `is_none`
error: this boolean expression can be simplified
--> $DIR/booleans.rs:49:13
|
49 | let _ = !a.is_none();
| ^^^^^^^^^^^^ help: try: `is_some`
error: this boolean expression can be simplified
--> $DIR/booleans.rs:51:13
|
51 | let _ = !b.is_err();
| ^^^^^^^^^^^ help: try: `is_ok`
error: this boolean expression can be simplified
--> $DIR/booleans.rs:53:13
|
53 | let _ = !b.is_ok();
| ^^^^^^^^^^ help: try: `is_err`