Skip to content

Commit 4a4f998

Browse files
committed
Add new lint for undropped ManuallyDrop values
1 parent 85959be commit 4a4f998

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,6 +1979,7 @@ Released 2018-09-13
19791979
[`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
19801980
[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
19811981
[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
1982+
[`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops
19821983
[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc
19831984
[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented
19841985
[`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init

clippy_lints/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ mod transmuting_null;
314314
mod trivially_copy_pass_by_ref;
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;
@@ -862,6 +863,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
862863
&types::UNIT_CMP,
863864
&types::UNNECESSARY_CAST,
864865
&types::VEC_BOX,
866+
&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS,
865867
&unicode::INVISIBLE_CHARACTERS,
866868
&unicode::NON_ASCII_LITERAL,
867869
&unicode::UNICODE_NOT_NFC,
@@ -1137,6 +1139,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11371139
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
11381140
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
11391141
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
1142+
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
11401143

11411144

11421145
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
@@ -1790,6 +1793,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
17901793
LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
17911794
LintId::of(&types::CAST_REF_TO_MUT),
17921795
LintId::of(&types::UNIT_CMP),
1796+
LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
17931797
LintId::of(&unicode::INVISIBLE_CHARACTERS),
17941798
LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
17951799
LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use rustc_lint::{LateLintPass, LateContext};
2+
use rustc_session::{declare_lint_pass, declare_tool_lint};
3+
use rustc_hir::*;
4+
use crate::utils::{match_function_call, is_type_lang_item, paths, span_lint_and_help};
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:** None.
12+
///
13+
/// **Example:**
14+
///
15+
/// ```rust
16+
/// struct S;
17+
/// drop(std::mem::ManuallyDrop::new(S));
18+
/// ```
19+
/// Use instead:
20+
/// ```rust
21+
/// struct S;
22+
/// unsafe {
23+
/// std::mem::ManuallyDrop::drop(std::mem::ManuallyDrop::new(S));
24+
/// }
25+
/// ```
26+
pub UNDROPPED_MANUALLY_DROPS,
27+
correctness,
28+
"use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
29+
}
30+
31+
declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]);
32+
33+
impl LateLintPass<'tcx> for UndroppedManuallyDrops {
34+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
35+
if let Some(ref args) = match_function_call(cx, expr, &paths::DROP) {
36+
let ty = cx.typeck_results().expr_ty(&args[0]);
37+
if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop) {
38+
span_lint_and_help(
39+
cx,
40+
UNDROPPED_MANUALLY_DROPS,
41+
expr.span,
42+
"the inner value of this ManuallyDrop will not be dropped",
43+
None,
44+
"to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop"
45+
);
46+
}
47+
}
48+
}
49+
}

src/lintlist/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,6 +2412,13 @@ vec![
24122412
deprecation: None,
24132413
module: "trait_bounds",
24142414
},
2415+
Lint {
2416+
name: "undropped_manually_drops",
2417+
group: "correctness",
2418+
desc: "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value",
2419+
deprecation: None,
2420+
module: "undropped_manually_drops",
2421+
},
24152422
Lint {
24162423
name: "unicode_not_nfc",
24172424
group: "pedantic",

tests/ui/undropped_manually_drops.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![warn(clippy::undropped_manually_drops)]
2+
3+
struct S;
4+
5+
fn main() {
6+
let f = drop;
7+
let manual = std::mem::ManuallyDrop::new(S);
8+
9+
// These lines will not drop `S`
10+
drop(std::mem::ManuallyDrop::new(S));
11+
f(manual);
12+
13+
// These lines will
14+
unsafe {
15+
std::mem::ManuallyDrop::drop(std::mem::ManuallyDrop::new(S));
16+
std::mem::ManuallyDrop::drop(manual);
17+
}
18+
}

0 commit comments

Comments
 (0)