]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/drop_ref.rs
Fix deploy.sh III
[rust.git] / clippy_lints / src / drop_ref.rs
1 use rustc::lint::*;
2 use rustc::ty;
3 use rustc::hir::*;
4 use syntax::codemap::Span;
5 use utils::{match_def_path, paths, span_note_and_lint};
6
7 /// **What it does:** This lint checks for calls to `std::mem::drop` with a reference instead of an owned value.
8 ///
9 /// **Why is this bad?** Calling `drop` on a reference will only drop the reference itself, which is a no-op. It will not call the `drop` method (from the `Drop` trait implementation) on the underlying referenced value, which is likely what was intended.
10 ///
11 /// **Known problems:** None
12 ///
13 /// **Example:**
14 /// ```rust
15 /// let mut lock_guard = mutex.lock();
16 /// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked
17 /// operation_that_requires_mutex_to_be_unlocked();
18 /// ```
19 declare_lint! {
20     pub DROP_REF, Warn,
21     "call to `std::mem::drop` with a reference instead of an owned value, \
22     which will not call the `Drop::drop` method on the underlying value"
23 }
24
25 #[allow(missing_copy_implementations)]
26 pub struct Pass;
27
28 impl LintPass for Pass {
29     fn get_lints(&self) -> LintArray {
30         lint_array!(DROP_REF)
31     }
32 }
33
34 impl LateLintPass for Pass {
35     fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
36         if let ExprCall(ref path, ref args) = expr.node {
37             if let ExprPath(None, _) = path.node {
38                 let def_id = cx.tcx.expect_def(path.id).def_id();
39                 if match_def_path(cx, def_id, &paths::DROP) {
40                     if args.len() != 1 {
41                         return;
42                     }
43                     check_drop_arg(cx, expr.span, &*args[0]);
44                 }
45             }
46         }
47     }
48 }
49
50 fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) {
51     let arg_ty = cx.tcx.expr_ty(arg);
52     if let ty::TyRef(..) = arg_ty.sty {
53         span_note_and_lint(cx,
54                            DROP_REF,
55                            call_span,
56                            "call to `std::mem::drop` with a reference argument. \
57                            Dropping a reference does nothing",
58                            arg.span,
59                            &format!("argument has type {}", arg_ty.sty));
60     }
61 }