]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/let_underscore.rs
Fix fallout
[rust.git] / clippy_lints / src / let_underscore.rs
1 use if_chain::if_chain;
2 use rustc::lint::in_external_macro;
3 use rustc_hir::{PatKind, Stmt, StmtKind};
4 use rustc_lint::{LateContext, LateLintPass};
5 use rustc_session::{declare_lint_pass, declare_tool_lint};
6
7 use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
8
9 declare_clippy_lint! {
10     /// **What it does:** Checks for `let _ = <expr>`
11     /// where expr is #[must_use]
12     ///
13     /// **Why is this bad?** It's better to explicitly
14     /// handle the value of a #[must_use] expr
15     ///
16     /// **Known problems:** None.
17     ///
18     /// **Example:**
19     /// ```rust
20     /// fn f() -> Result<u32, u32> {
21     ///     Ok(0)
22     /// }
23     ///
24     /// let _ = f();
25     /// // is_ok() is marked #[must_use]
26     /// let _ = f().is_ok();
27     /// ```
28     pub LET_UNDERSCORE_MUST_USE,
29     restriction,
30     "non-binding let on a `#[must_use]` expression"
31 }
32
33 declare_clippy_lint! {
34     /// **What it does:** Checks for `let _ = sync_lock`
35     ///
36     /// **Why is this bad?** This statement immediately drops the lock instead of
37     /// extending it's lifetime to the end of the scope, which is often not intended.
38     /// To extend lock lifetime to the end of the scope, use an underscore-prefixed
39     /// name instead (i.e. _lock). If you want to explicitly drop the lock,
40     /// `std::mem::drop` conveys your intention better and is less error-prone.
41     ///
42     /// **Known problems:** None.
43     ///
44     /// **Example:**
45     ///
46     /// Bad:
47     /// ```rust,ignore
48     /// let _ = mutex.lock();
49     /// ```
50     ///
51     /// Good:
52     /// ```rust,ignore
53     /// let _lock = mutex.lock();
54     /// ```
55     pub LET_UNDERSCORE_LOCK,
56     correctness,
57     "non-binding let on a synchronization lock"
58 }
59
60 declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
61
62 const SYNC_GUARD_PATHS: [&[&str]; 3] = [
63     &paths::MUTEX_GUARD,
64     &paths::RWLOCK_READ_GUARD,
65     &paths::RWLOCK_WRITE_GUARD,
66 ];
67
68 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
69     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) {
70         if in_external_macro(cx.tcx.sess, stmt.span) {
71             return;
72         }
73
74         if_chain! {
75             if let StmtKind::Local(ref local) = stmt.kind;
76             if let PatKind::Wild = local.pat.kind;
77             if let Some(ref init) = local.init;
78             then {
79                 let check_ty = |ty| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, ty, path));
80                 if cx.tables.expr_ty(init).walk().any(check_ty) {
81                     span_lint_and_help(
82                         cx,
83                         LET_UNDERSCORE_LOCK,
84                         stmt.span,
85                         "non-binding let on a synchronization lock",
86                         "consider using an underscore-prefixed named \
87                             binding or dropping explicitly with `std::mem::drop`"
88                     )
89                 } else if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
90                     span_lint_and_help(
91                         cx,
92                         LET_UNDERSCORE_MUST_USE,
93                         stmt.span,
94                         "non-binding let on an expression with `#[must_use]` type",
95                         "consider explicitly using expression value"
96                     )
97                 } else if is_must_use_func_call(cx, init) {
98                     span_lint_and_help(
99                         cx,
100                         LET_UNDERSCORE_MUST_USE,
101                         stmt.span,
102                         "non-binding let on a result of a `#[must_use]` function",
103                         "consider explicitly using function result"
104                     )
105                 }
106             }
107         }
108     }
109 }