Add let_underscore_drop
This commit is contained in:
parent
96d5f45ade
commit
f1f780c942
@ -1787,6 +1787,7 @@ Released 2018-09-13
|
||||
[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
|
||||
[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
|
||||
[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
|
||||
[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop
|
||||
[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
|
||||
[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
|
||||
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
|
||||
|
@ -5,7 +5,7 @@
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
|
||||
use crate::utils::{implements_trait, is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `let _ = <expr>`
|
||||
@ -58,7 +58,40 @@
|
||||
"non-binding let on a synchronization lock"
|
||||
}
|
||||
|
||||
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `let _ = <expr>`
|
||||
/// where expr has a type that implements `Drop`
|
||||
///
|
||||
/// **Why is this bad?** This statement immediately drops the initializer
|
||||
/// expression instead of extending its lifetime to the end of the scope, which
|
||||
/// is often not intended. To extend the expression's lifetime to the end of the
|
||||
/// scope, use an underscore-prefixed name instead (i.e. _var). If you want to
|
||||
/// explicitly drop the expression, `std::mem::drop` conveys your intention
|
||||
/// better and is less error-prone.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// Bad:
|
||||
/// ```rust,ignore
|
||||
/// struct Droppable;
|
||||
/// impl Drop for Droppable {
|
||||
/// fn drop(&mut self) {}
|
||||
/// }
|
||||
/// let _ = Droppable;
|
||||
/// ```
|
||||
///
|
||||
/// Good:
|
||||
/// ```rust,ignore
|
||||
/// let _droppable = Droppable;
|
||||
/// ```
|
||||
pub LET_UNDERSCORE_DROP,
|
||||
correctness,
|
||||
"non-binding let on a type that implements `Drop`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]);
|
||||
|
||||
const SYNC_GUARD_PATHS: [&[&str]; 3] = [
|
||||
&paths::MUTEX_GUARD,
|
||||
@ -84,6 +117,15 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
|
||||
|
||||
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
|
||||
});
|
||||
let implements_drop = cx.tcx.lang_items().drop_trait().map_or(false, |drop_trait|
|
||||
init_ty.walk().any(|inner| match inner.unpack() {
|
||||
GenericArgKind::Type(inner_ty) => {
|
||||
implements_trait(cx, inner_ty, drop_trait, &[])
|
||||
},
|
||||
|
||||
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
|
||||
})
|
||||
);
|
||||
if contains_sync_guard {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
@ -94,6 +136,16 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
|
||||
"consider using an underscore-prefixed named \
|
||||
binding or dropping explicitly with `std::mem::drop`"
|
||||
)
|
||||
} else if implements_drop {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
LET_UNDERSCORE_DROP,
|
||||
local.span,
|
||||
"non-binding let on a type that implements `Drop`",
|
||||
None,
|
||||
"consider using an underscore-prefixed named \
|
||||
binding or dropping explicitly with `std::mem::drop`"
|
||||
)
|
||||
} else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
@ -622,6 +622,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
&len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||
&len_zero::LEN_ZERO,
|
||||
&let_if_seq::USELESS_LET_IF_SEQ,
|
||||
&let_underscore::LET_UNDERSCORE_DROP,
|
||||
&let_underscore::LET_UNDERSCORE_LOCK,
|
||||
&let_underscore::LET_UNDERSCORE_MUST_USE,
|
||||
&lifetimes::EXTRA_UNUSED_LIFETIMES,
|
||||
@ -1383,6 +1384,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&len_zero::COMPARISON_TO_EMPTY),
|
||||
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
|
||||
LintId::of(&len_zero::LEN_ZERO),
|
||||
LintId::of(&let_underscore::LET_UNDERSCORE_DROP),
|
||||
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
|
||||
LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
|
||||
LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
|
||||
@ -1809,6 +1811,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&infinite_iter::INFINITE_ITER),
|
||||
LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
|
||||
LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
|
||||
LintId::of(&let_underscore::LET_UNDERSCORE_DROP),
|
||||
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
|
||||
LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
|
||||
LintId::of(&loops::FOR_LOOPS_OVER_FALLIBLES),
|
||||
|
@ -1117,6 +1117,13 @@
|
||||
deprecation: None,
|
||||
module: "returns",
|
||||
},
|
||||
Lint {
|
||||
name: "let_underscore_drop",
|
||||
group: "correctness",
|
||||
desc: "non-binding let on a type that implements `Drop`",
|
||||
deprecation: None,
|
||||
module: "let_underscore",
|
||||
},
|
||||
Lint {
|
||||
name: "let_underscore_lock",
|
||||
group: "correctness",
|
||||
|
19
tests/ui/let_underscore_drop.rs
Normal file
19
tests/ui/let_underscore_drop.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![warn(clippy::let_underscore_drop)]
|
||||
|
||||
struct Droppable;
|
||||
|
||||
impl Drop for Droppable {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let unit = ();
|
||||
let boxed = Box::new(());
|
||||
let droppable = Droppable;
|
||||
let optional = Some(Droppable);
|
||||
|
||||
let _ = ();
|
||||
let _ = Box::new(());
|
||||
let _ = Droppable;
|
||||
let _ = Some(Droppable);
|
||||
}
|
27
tests/ui/let_underscore_drop.stderr
Normal file
27
tests/ui/let_underscore_drop.stderr
Normal file
@ -0,0 +1,27 @@
|
||||
error: non-binding let on a type that implements `Drop`
|
||||
--> $DIR/let_underscore_drop.rs:16:5
|
||||
|
|
||||
LL | let _ = Box::new(());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::let-underscore-drop` implied by `-D warnings`
|
||||
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
|
||||
|
||||
error: non-binding let on a type that implements `Drop`
|
||||
--> $DIR/let_underscore_drop.rs:17:5
|
||||
|
|
||||
LL | let _ = Droppable;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
|
||||
|
||||
error: non-binding let on a type that implements `Drop`
|
||||
--> $DIR/let_underscore_drop.rs:18:5
|
||||
|
|
||||
LL | let _ = Some(Droppable);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user