mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
Add empty_drop lint
This commit is contained in:
parent
4c25880f0c
commit
8de3fb159d
8 changed files with 146 additions and 0 deletions
|
@ -3365,6 +3365,7 @@ Released 2018-09-13
|
|||
[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument
|
||||
[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
|
||||
[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
|
||||
[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
|
||||
[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
|
||||
[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
|
||||
[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
|
||||
|
|
65
clippy_lints/src/empty_drop.rs
Normal file
65
clippy_lints/src/empty_drop.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use clippy_utils::{diagnostics::span_lint_and_sugg, peel_blocks};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for empty `Drop` implementations.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Empty `Drop` implementations have no effect when dropping an instance of the type. They are
|
||||
/// most likely useless. However, an empty `Drop` implementation prevents a type from being
|
||||
/// destructured, which might be the intention behind adding the implementation as a marker.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// struct S;
|
||||
///
|
||||
/// impl Drop for S {
|
||||
/// fn drop(&mut self) {}
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// struct S;
|
||||
/// ```
|
||||
#[clippy::version = "1.61.0"]
|
||||
pub EMPTY_DROP,
|
||||
restriction,
|
||||
"empty `Drop` implementations"
|
||||
}
|
||||
declare_lint_pass!(EmptyDrop => [EMPTY_DROP]);
|
||||
|
||||
impl LateLintPass<'_> for EmptyDrop {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
if_chain! {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(ref trait_ref),
|
||||
items: [child],
|
||||
..
|
||||
}) = item.kind;
|
||||
if trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait();
|
||||
if let impl_item_hir = child.id.hir_id();
|
||||
if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
|
||||
if let ImplItemKind::Fn(_, b) = &impl_item.kind;
|
||||
if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
|
||||
let func_expr = peel_blocks(func_expr);
|
||||
if let ExprKind::Block(block, _) = func_expr.kind;
|
||||
if block.stmts.is_empty() && block.expr.is_none();
|
||||
then {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
EMPTY_DROP,
|
||||
item.span,
|
||||
"empty drop implementation",
|
||||
"try removing this impl",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -134,6 +134,7 @@ store.register_lints(&[
|
|||
drop_forget_ref::UNDROPPED_MANUALLY_DROPS,
|
||||
duration_subsec::DURATION_SUBSEC,
|
||||
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
|
||||
empty_drop::EMPTY_DROP,
|
||||
empty_enum::EMPTY_ENUM,
|
||||
empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS,
|
||||
entry::MAP_ENTRY,
|
||||
|
|
|
@ -16,6 +16,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
|
|||
LintId::of(default_union_representation::DEFAULT_UNION_REPRESENTATION),
|
||||
LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS),
|
||||
LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
|
||||
LintId::of(empty_drop::EMPTY_DROP),
|
||||
LintId::of(empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS),
|
||||
LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
|
||||
LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS),
|
||||
|
|
|
@ -210,6 +210,7 @@ mod double_parens;
|
|||
mod drop_forget_ref;
|
||||
mod duration_subsec;
|
||||
mod else_if_without_else;
|
||||
mod empty_drop;
|
||||
mod empty_enum;
|
||||
mod empty_structs_with_brackets;
|
||||
mod entry;
|
||||
|
@ -822,6 +823,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(move || Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
|
||||
store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
|
||||
store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
|
||||
store.register_late_pass(|| Box::new(empty_drop::EmptyDrop));
|
||||
store.register_late_pass(|| Box::new(strings::StrToString));
|
||||
store.register_late_pass(|| Box::new(strings::StringToString));
|
||||
store.register_late_pass(|| Box::new(zero_sized_map_values::ZeroSizedMapValues));
|
||||
|
|
24
tests/ui/empty_drop.fixed
Normal file
24
tests/ui/empty_drop.fixed
Normal file
|
@ -0,0 +1,24 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::empty_drop)]
|
||||
#![allow(unused)]
|
||||
|
||||
// should cause an error
|
||||
struct Foo;
|
||||
|
||||
|
||||
|
||||
// shouldn't cause an error
|
||||
struct Bar;
|
||||
|
||||
impl Drop for Bar {
|
||||
fn drop(&mut self) {
|
||||
println!("dropping bar!");
|
||||
}
|
||||
}
|
||||
|
||||
// should error
|
||||
struct Baz;
|
||||
|
||||
|
||||
|
||||
fn main() {}
|
30
tests/ui/empty_drop.rs
Normal file
30
tests/ui/empty_drop.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::empty_drop)]
|
||||
#![allow(unused)]
|
||||
|
||||
// should cause an error
|
||||
struct Foo;
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
// shouldn't cause an error
|
||||
struct Bar;
|
||||
|
||||
impl Drop for Bar {
|
||||
fn drop(&mut self) {
|
||||
println!("dropping bar!");
|
||||
}
|
||||
}
|
||||
|
||||
// should error
|
||||
struct Baz;
|
||||
|
||||
impl Drop for Baz {
|
||||
fn drop(&mut self) {
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
22
tests/ui/empty_drop.stderr
Normal file
22
tests/ui/empty_drop.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error: empty drop implementation
|
||||
--> $DIR/empty_drop.rs:8:1
|
||||
|
|
||||
LL | / impl Drop for Foo {
|
||||
LL | | fn drop(&mut self) {}
|
||||
LL | | }
|
||||
| |_^ help: try removing this impl
|
||||
|
|
||||
= note: `-D clippy::empty-drop` implied by `-D warnings`
|
||||
|
||||
error: empty drop implementation
|
||||
--> $DIR/empty_drop.rs:24:1
|
||||
|
|
||||
LL | / impl Drop for Baz {
|
||||
LL | | fn drop(&mut self) {
|
||||
LL | | {}
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^ help: try removing this impl
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in a new issue