Skip to content

Commit 6b01c39

Browse files
committed
Auto merge of #6181 - cgm616:undropped-manually-drops, r=flip1995
Add new lint for undropped ManuallyDrop values Adds a new lint for the following code: ```rust struct S; impl Drop for S { fn drop(&mut self) { println!("drip drop"); } } fn main() { // This will not drop the `S`!!! drop(std::mem::ManuallyDrop::new(S)); unsafe { // This will. std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S)); } } ``` The inner value of a `ManuallyDrop` will not be dropped unless the proper, unsafe drop function is called on it. This lint makes sure that a user does not accidently use the wrong function and forget to drop a `ManuallyDrop` value. Fixes #5581. --- *Please keep the line below* changelog: none
2 parents e0e617a + e70817e commit 6b01c39

File tree

6 files changed

+108
-0
lines changed

6 files changed

+108
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1982,6 +1982,7 @@ Released 2018-09-13
19821982
[`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
19831983
[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
19841984
[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
1985+
[`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops
19851986
[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc
19861987
[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented
19871988
[`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init

clippy_lints/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ mod transmute;
314314
mod transmuting_null;
315315
mod try_err;
316316
mod types;
317+
mod undropped_manually_drops;
317318
mod unicode;
318319
mod unit_return_expecting_ord;
319320
mod unnamed_address;
@@ -865,6 +866,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
865866
&types::UNIT_CMP,
866867
&types::UNNECESSARY_CAST,
867868
&types::VEC_BOX,
869+
&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS,
868870
&unicode::INVISIBLE_CHARACTERS,
869871
&unicode::NON_ASCII_LITERAL,
870872
&unicode::UNICODE_NOT_NFC,
@@ -1141,6 +1143,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11411143
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
11421144
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
11431145
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
1146+
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
11441147

11451148

11461149
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
@@ -1528,6 +1531,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15281531
LintId::of(&types::UNIT_CMP),
15291532
LintId::of(&types::UNNECESSARY_CAST),
15301533
LintId::of(&types::VEC_BOX),
1534+
LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
15311535
LintId::of(&unicode::INVISIBLE_CHARACTERS),
15321536
LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
15331537
LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
@@ -1800,6 +1804,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
18001804
LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
18011805
LintId::of(&types::CAST_REF_TO_MUT),
18021806
LintId::of(&types::UNIT_CMP),
1807+
LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
18031808
LintId::of(&unicode::INVISIBLE_CHARACTERS),
18041809
LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
18051810
LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::utils::{is_type_lang_item, match_function_call, paths, span_lint_and_help};
2+
use rustc_hir::{lang_items, Expr};
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:** Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`.
8+
///
9+
/// **Why is this bad?** The safe `drop` function does not drop the inner value of a `ManuallyDrop`.
10+
///
11+
/// **Known problems:** Does not catch cases if the user binds `std::mem::drop`
12+
/// to a different name and calls it that way.
13+
///
14+
/// **Example:**
15+
///
16+
/// ```rust
17+
/// struct S;
18+
/// drop(std::mem::ManuallyDrop::new(S));
19+
/// ```
20+
/// Use instead:
21+
/// ```rust
22+
/// struct S;
23+
/// unsafe {
24+
/// std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S));
25+
/// }
26+
/// ```
27+
pub UNDROPPED_MANUALLY_DROPS,
28+
correctness,
29+
"use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
30+
}
31+
32+
declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]);
33+
34+
impl LateLintPass<'tcx> for UndroppedManuallyDrops {
35+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
36+
if let Some(ref args) = match_function_call(cx, expr, &paths::DROP) {
37+
let ty = cx.typeck_results().expr_ty(&args[0]);
38+
if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop) {
39+
span_lint_and_help(
40+
cx,
41+
UNDROPPED_MANUALLY_DROPS,
42+
expr.span,
43+
"the inner value of this ManuallyDrop will not be dropped",
44+
None,
45+
"to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop",
46+
);
47+
}
48+
}
49+
}
50+
}

src/lintlist/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2433,6 +2433,13 @@ vec![
24332433
deprecation: None,
24342434
module: "trait_bounds",
24352435
},
2436+
Lint {
2437+
name: "undropped_manually_drops",
2438+
group: "correctness",
2439+
desc: "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value",
2440+
deprecation: None,
2441+
module: "undropped_manually_drops",
2442+
},
24362443
Lint {
24372444
name: "unicode_not_nfc",
24382445
group: "pedantic",

tests/ui/undropped_manually_drops.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#![warn(clippy::undropped_manually_drops)]
2+
3+
struct S;
4+
5+
fn main() {
6+
let f = std::mem::drop;
7+
let g = std::mem::ManuallyDrop::drop;
8+
let mut manual1 = std::mem::ManuallyDrop::new(S);
9+
let mut manual2 = std::mem::ManuallyDrop::new(S);
10+
let mut manual3 = std::mem::ManuallyDrop::new(S);
11+
let mut manual4 = std::mem::ManuallyDrop::new(S);
12+
13+
// These lines will not drop `S` and should be linted
14+
drop(std::mem::ManuallyDrop::new(S));
15+
drop(manual1);
16+
17+
// FIXME: this line is not linted, though it should be
18+
f(manual2);
19+
20+
// These lines will drop `S` and should be okay.
21+
unsafe {
22+
std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S));
23+
std::mem::ManuallyDrop::drop(&mut manual3);
24+
g(&mut manual4);
25+
}
26+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error: the inner value of this ManuallyDrop will not be dropped
2+
--> $DIR/undropped_manually_drops.rs:14:5
3+
|
4+
LL | drop(std::mem::ManuallyDrop::new(S));
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::undropped-manually-drops` implied by `-D warnings`
8+
= help: to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop
9+
10+
error: the inner value of this ManuallyDrop will not be dropped
11+
--> $DIR/undropped_manually_drops.rs:15:5
12+
|
13+
LL | drop(manual1);
14+
| ^^^^^^^^^^^^^
15+
|
16+
= help: to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop
17+
18+
error: aborting due to 2 previous errors
19+

0 commit comments

Comments
 (0)