]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/let_underscore.rs
disable let_underscore_must_use in external macros
[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::*;
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, span_help_and_lint};
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_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE]);
34
35 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
36     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) {
37         if in_external_macro(cx.tcx.sess, stmt.span) {
38             return;
39         }
40
41         if_chain! {
42             if let StmtKind::Local(ref local) = stmt.kind;
43             if let PatKind::Wild = local.pat.kind;
44             if let Some(ref init) = local.init;
45             then {
46                 if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
47                    span_help_and_lint(
48                         cx,
49                         LET_UNDERSCORE_MUST_USE,
50                         stmt.span,
51                         "non-binding let on an expression with `#[must_use]` type",
52                         "consider explicitly using expression value"
53                     )
54                 } else if is_must_use_func_call(cx, init) {
55                     span_help_and_lint(
56                         cx,
57                         LET_UNDERSCORE_MUST_USE,
58                         stmt.span,
59                         "non-binding let on a result of a `#[must_use]` function",
60                         "consider explicitly using function result"
61                     )
62                 }
63             }
64         }
65     }
66 }