Skip to content

Commit a9d31e7

Browse files
committed
Auto merge of #8571 - PyroTechniac:empty-drop, r=flip1995
add `empty_drop` Closes #8352 changelog: New lint [`empty_drop`]
2 parents 4c25880 + 8de3fb1 commit a9d31e7

8 files changed

+146
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,6 +3365,7 @@ Released 2018-09-13
33653365
[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument
33663366
[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
33673367
[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
3368+
[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
33683369
[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
33693370
[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
33703371
[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop

clippy_lints/src/empty_drop.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use clippy_utils::{diagnostics::span_lint_and_sugg, peel_blocks};
2+
use if_chain::if_chain;
3+
use rustc_errors::Applicability;
4+
use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node};
5+
use rustc_lint::{LateContext, LateLintPass};
6+
use rustc_session::{declare_lint_pass, declare_tool_lint};
7+
8+
declare_clippy_lint! {
9+
/// ### What it does
10+
/// Checks for empty `Drop` implementations.
11+
///
12+
/// ### Why is this bad?
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
18+
/// ```rust
19+
/// struct S;
20+
///
21+
/// impl Drop for S {
22+
/// fn drop(&mut self) {}
23+
/// }
24+
/// ```
25+
/// Use instead:
26+
/// ```rust
27+
/// struct S;
28+
/// ```
29+
#[clippy::version = "1.61.0"]
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<'_>) {
38+
if_chain! {
39+
if let ItemKind::Impl(Impl {
40+
of_trait: Some(ref trait_ref),
41+
items: [child],
42+
..
43+
}) = item.kind;
44+
if trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait();
45+
if let impl_item_hir = child.id.hir_id();
46+
if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
47+
if let ImplItemKind::Fn(_, b) = &impl_item.kind;
48+
if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
49+
let func_expr = peel_blocks(func_expr);
50+
if let ExprKind::Block(block, _) = func_expr.kind;
51+
if block.stmts.is_empty() && block.expr.is_none();
52+
then {
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+
);
62+
}
63+
}
64+
}
65+
}

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ store.register_lints(&[
134134
drop_forget_ref::UNDROPPED_MANUALLY_DROPS,
135135
duration_subsec::DURATION_SUBSEC,
136136
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
137+
empty_drop::EMPTY_DROP,
137138
empty_enum::EMPTY_ENUM,
138139
empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS,
139140
entry::MAP_ENTRY,

clippy_lints/src/lib.register_restriction.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
1616
LintId::of(default_union_representation::DEFAULT_UNION_REPRESENTATION),
1717
LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS),
1818
LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
19+
LintId::of(empty_drop::EMPTY_DROP),
1920
LintId::of(empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS),
2021
LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
2122
LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS),

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ mod double_parens;
210210
mod drop_forget_ref;
211211
mod duration_subsec;
212212
mod else_if_without_else;
213+
mod empty_drop;
213214
mod empty_enum;
214215
mod empty_structs_with_brackets;
215216
mod entry;
@@ -822,6 +823,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
822823
store.register_late_pass(move || Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
823824
store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
824825
store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
826+
store.register_late_pass(|| Box::new(empty_drop::EmptyDrop));
825827
store.register_late_pass(|| Box::new(strings::StrToString));
826828
store.register_late_pass(|| Box::new(strings::StringToString));
827829
store.register_late_pass(|| Box::new(zero_sized_map_values::ZeroSizedMapValues));

tests/ui/empty_drop.fixed

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// run-rustfix
2+
#![warn(clippy::empty_drop)]
3+
#![allow(unused)]
4+
5+
// should cause an error
6+
struct Foo;
7+
8+
9+
10+
// shouldn't cause an error
11+
struct Bar;
12+
13+
impl Drop for Bar {
14+
fn drop(&mut self) {
15+
println!("dropping bar!");
16+
}
17+
}
18+
19+
// should error
20+
struct Baz;
21+
22+
23+
24+
fn main() {}

tests/ui/empty_drop.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// run-rustfix
2+
#![warn(clippy::empty_drop)]
3+
#![allow(unused)]
4+
5+
// should cause an error
6+
struct Foo;
7+
8+
impl Drop for Foo {
9+
fn drop(&mut self) {}
10+
}
11+
12+
// shouldn't cause an error
13+
struct Bar;
14+
15+
impl Drop for Bar {
16+
fn drop(&mut self) {
17+
println!("dropping bar!");
18+
}
19+
}
20+
21+
// should error
22+
struct Baz;
23+
24+
impl Drop for Baz {
25+
fn drop(&mut self) {
26+
{}
27+
}
28+
}
29+
30+
fn main() {}

tests/ui/empty_drop.stderr

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: empty drop implementation
2+
--> $DIR/empty_drop.rs:8:1
3+
|
4+
LL | / impl Drop for Foo {
5+
LL | | fn drop(&mut self) {}
6+
LL | | }
7+
| |_^ help: try removing this impl
8+
|
9+
= note: `-D clippy::empty-drop` implied by `-D warnings`
10+
11+
error: empty drop implementation
12+
--> $DIR/empty_drop.rs:24:1
13+
|
14+
LL | / impl Drop for Baz {
15+
LL | | fn drop(&mut self) {
16+
LL | | {}
17+
LL | | }
18+
LL | | }
19+
| |_^ help: try removing this impl
20+
21+
error: aborting due to 2 previous errors
22+

0 commit comments

Comments
 (0)