]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/matches/match_bool.rs
Auto merge of #8630 - Jarcho:forget_non_drop, r=Manishearth
[rust.git] / clippy_lints / src / matches / match_bool.rs
1 use clippy_utils::diagnostics::span_lint_and_then;
2 use clippy_utils::is_unit_expr;
3 use clippy_utils::source::{expr_block, snippet};
4 use clippy_utils::sugg::Sugg;
5 use rustc_ast::LitKind;
6 use rustc_errors::Applicability;
7 use rustc_hir::{Arm, Expr, ExprKind, PatKind};
8 use rustc_lint::LateContext;
9 use rustc_middle::ty;
10
11 use super::MATCH_BOOL;
12
13 pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
14     // Type of expression is `bool`.
15     if *cx.typeck_results().expr_ty(ex).kind() == ty::Bool {
16         span_lint_and_then(
17             cx,
18             MATCH_BOOL,
19             expr.span,
20             "you seem to be trying to match on a boolean expression",
21             move |diag| {
22                 if arms.len() == 2 {
23                     // no guards
24                     let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
25                         if let ExprKind::Lit(ref lit) = arm_bool.kind {
26                             match lit.node {
27                                 LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)),
28                                 LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)),
29                                 _ => None,
30                             }
31                         } else {
32                             None
33                         }
34                     } else {
35                         None
36                     };
37
38                     if let Some((true_expr, false_expr)) = exprs {
39                         let sugg = match (is_unit_expr(true_expr), is_unit_expr(false_expr)) {
40                             (false, false) => Some(format!(
41                                 "if {} {} else {}",
42                                 snippet(cx, ex.span, "b"),
43                                 expr_block(cx, true_expr, None, "..", Some(expr.span)),
44                                 expr_block(cx, false_expr, None, "..", Some(expr.span))
45                             )),
46                             (false, true) => Some(format!(
47                                 "if {} {}",
48                                 snippet(cx, ex.span, "b"),
49                                 expr_block(cx, true_expr, None, "..", Some(expr.span))
50                             )),
51                             (true, false) => {
52                                 let test = Sugg::hir(cx, ex, "..");
53                                 Some(format!(
54                                     "if {} {}",
55                                     !test,
56                                     expr_block(cx, false_expr, None, "..", Some(expr.span))
57                                 ))
58                             },
59                             (true, true) => None,
60                         };
61
62                         if let Some(sugg) = sugg {
63                             diag.span_suggestion(
64                                 expr.span,
65                                 "consider using an `if`/`else` expression",
66                                 sugg,
67                                 Applicability::HasPlaceholders,
68                             );
69                         }
70                     }
71                 }
72             },
73         );
74     }
75 }