]>
Commit | Line | Data |
---|---|---|
add651ee FG |
1 | use clippy_utils::diagnostics::span_lint_and_sugg; |
2 | use clippy_utils::peel_blocks; | |
04454e1e FG |
3 | use rustc_errors::Applicability; |
4 | use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node}; | |
5 | use rustc_lint::{LateContext, LateLintPass}; | |
4b012472 | 6 | use rustc_session::declare_lint_pass; |
04454e1e FG |
7 | |
8 | declare_clippy_lint! { | |
9 | /// ### What it does | |
10 | /// Checks for empty `Drop` implementations. | |
11 | /// | |
31ef2f64 | 12 | /// ### Why restrict this? |
04454e1e FG |
13 | /// Empty `Drop` implementations have no effect when dropping an instance of the type. They are |
14 | /// most likely useless. However, an empty `Drop` implementation prevents a type from being | |
15 | /// destructured, which might be the intention behind adding the implementation as a marker. | |
16 | /// | |
17 | /// ### Example | |
ed00b5ec | 18 | /// ```no_run |
04454e1e FG |
19 | /// struct S; |
20 | /// | |
21 | /// impl Drop for S { | |
22 | /// fn drop(&mut self) {} | |
23 | /// } | |
24 | /// ``` | |
25 | /// Use instead: | |
ed00b5ec | 26 | /// ```no_run |
04454e1e FG |
27 | /// struct S; |
28 | /// ``` | |
064997fb | 29 | #[clippy::version = "1.62.0"] |
04454e1e FG |
30 | pub EMPTY_DROP, |
31 | restriction, | |
32 | "empty `Drop` implementations" | |
33 | } | |
34 | declare_lint_pass!(EmptyDrop => [EMPTY_DROP]); | |
35 | ||
36 | impl LateLintPass<'_> for EmptyDrop { | |
37 | fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { | |
4b012472 FG |
38 | if let ItemKind::Impl(Impl { |
39 | of_trait: Some(ref trait_ref), | |
40 | items: [child], | |
41 | .. | |
42 | }) = item.kind | |
43 | && trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait() | |
44 | && let impl_item_hir = child.id.hir_id() | |
c620b35d | 45 | && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) |
4b012472 FG |
46 | && let ImplItemKind::Fn(_, b) = &impl_item.kind |
47 | && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) | |
48 | && let func_expr = peel_blocks(func_expr) | |
49 | && let ExprKind::Block(block, _) = func_expr.kind | |
50 | && block.stmts.is_empty() | |
51 | && block.expr.is_none() | |
52 | { | |
53 | span_lint_and_sugg( | |
54 | cx, | |
55 | EMPTY_DROP, | |
56 | item.span, | |
57 | "empty drop implementation", | |
58 | "try removing this impl", | |
59 | String::new(), | |
60 | Applicability::MaybeIncorrect, | |
61 | ); | |
04454e1e FG |
62 | } |
63 | } | |
64 | } |