]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/undropped_manually_drops.rs
Auto merge of #8500 - rust-lang:testless-dbg-macro, r=Manishearth
[rust.git] / clippy_lints / src / undropped_manually_drops.rs
1 use clippy_utils::diagnostics::span_lint_and_help;
2 use clippy_utils::path_res;
3 use clippy_utils::ty::is_type_lang_item;
4 use rustc_hir::{lang_items, Expr, ExprKind};
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7 use rustc_span::sym;
8
9 declare_clippy_lint! {
10     /// ### What it does
11     /// Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`.
12     ///
13     /// ### Why is this bad?
14     /// The safe `drop` function does not drop the inner value of a `ManuallyDrop`.
15     ///
16     /// ### Known problems
17     /// Does not catch cases if the user binds `std::mem::drop`
18     /// to a different name and calls it that way.
19     ///
20     /// ### Example
21     /// ```rust
22     /// struct S;
23     /// drop(std::mem::ManuallyDrop::new(S));
24     /// ```
25     /// Use instead:
26     /// ```rust
27     /// struct S;
28     /// unsafe {
29     ///     std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S));
30     /// }
31     /// ```
32     #[clippy::version = "1.49.0"]
33     pub UNDROPPED_MANUALLY_DROPS,
34     correctness,
35     "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
36 }
37
38 declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]);
39
40 impl<'tcx> LateLintPass<'tcx> for UndroppedManuallyDrops {
41     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
42         if_chain! {
43             if let ExprKind::Call(fun, [arg_0, ..]) = expr.kind;
44             if path_res(cx, fun).opt_def_id() == cx.tcx.get_diagnostic_item(sym::mem_drop);
45             let ty = cx.typeck_results().expr_ty(arg_0);
46             if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop);
47             then {
48                 span_lint_and_help(
49                     cx,
50                     UNDROPPED_MANUALLY_DROPS,
51                     expr.span,
52                     "the inner value of this ManuallyDrop will not be dropped",
53                     None,
54                     "to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop",
55                 );
56             }
57         }
58     }
59 }