]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use crate::utils::{match_def_path, paths, span_lint}; |
2 | use rustc_hir::{Expr, ExprKind}; | |
3 | use rustc_lint::{LateContext, LateLintPass}; | |
4 | use rustc_session::{declare_lint_pass, declare_tool_lint}; | |
5 | ||
6 | declare_clippy_lint! { | |
7 | /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is | |
8 | /// `Drop`. | |
9 | /// | |
10 | /// **Why is this bad?** `std::mem::forget(t)` prevents `t` from running its | |
11 | /// destructor, possibly causing leaks. | |
12 | /// | |
13 | /// **Known problems:** None. | |
14 | /// | |
15 | /// **Example:** | |
16 | /// ```rust | |
17 | /// # use std::mem; | |
18 | /// # use std::rc::Rc; | |
19 | /// mem::forget(Rc::new(55)) | |
20 | /// ``` | |
21 | pub MEM_FORGET, | |
22 | restriction, | |
23 | "`mem::forget` usage on `Drop` types, likely to cause memory leaks" | |
24 | } | |
25 | ||
26 | declare_lint_pass!(MemForget => [MEM_FORGET]); | |
27 | ||
28 | impl<'tcx> LateLintPass<'tcx> for MemForget { | |
29 | fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { | |
30 | if let ExprKind::Call(ref path_expr, ref args) = e.kind { | |
31 | if let ExprKind::Path(ref qpath) = path_expr.kind { | |
32 | if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { | |
33 | if match_def_path(cx, def_id, &paths::MEM_FORGET) { | |
34 | let forgot_ty = cx.typeck_results().expr_ty(&args[0]); | |
35 | ||
36 | if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { | |
37 | span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type"); | |
38 | } | |
39 | } | |
40 | } | |
41 | } | |
42 | } | |
43 | } | |
44 | } |