diff --git a/clippy_lints/src/drop_ref.rs b/clippy_lints/src/drop_forget_ref.rs similarity index 54% rename from clippy_lints/src/drop_ref.rs rename to clippy_lints/src/drop_forget_ref.rs index bddf47d3f45a..3950cdb6acf9 100644 --- a/clippy_lints/src/drop_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -25,12 +25,32 @@ declare_lint! { "calls to `std::mem::drop` with a reference instead of an owned value" } +/// **What it does:** Checks for calls to `std::mem::forget` with a reference +/// instead of an owned value. +/// +/// **Why is this bad?** Calling `forget` on a reference will only forget the +/// reference itself, which is a no-op. It will not forget the underlying referenced +/// value, which is likely what was intended. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x = Box::new(1); +/// std::mem::forget(&x) // Should have been forget(x), x will still be dropped +/// ``` +declare_lint! { + pub FORGET_REF, + Warn, + "calls to `std::mem::forget` with a reference instead of an owned value" +} + #[allow(missing_copy_implementations)] pub struct Pass; impl LintPass for Pass { fn get_lints(&self) -> LintArray { - lint_array!(DROP_REF) + lint_array!(DROP_REF, FORGET_REF) } } @@ -39,17 +59,29 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_let_chain!{[ let ExprCall(ref path, ref args) = expr.node, let ExprPath(ref qpath) = path.node, - match_def_path(cx, cx.tcx.tables().qpath_def(qpath, path.id).def_id(), &paths::DROP), args.len() == 1, ], { + let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id(); + let lint; + let msg; + if match_def_path(cx, def_id, &paths::DROP) { + lint = DROP_REF; + msg = "call to `std::mem::drop` with a reference argument. \ + Dropping a reference does nothing"; + } else if match_def_path(cx, def_id, &paths::MEM_FORGET) { + lint = FORGET_REF; + msg = "call to `std::mem::forget` with a reference argument. \ + Forgetting a reference does nothing"; + } else { + return; + } let arg = &args[0]; let arg_ty = cx.tcx.tables().expr_ty(arg); if let ty::TyRef(..) = arg_ty.sty { span_note_and_lint(cx, - DROP_REF, + lint, expr.span, - "call to `std::mem::drop` with a reference argument. \ - Dropping a reference does nothing", + msg, arg.span, &format!("argument has type {}", arg_ty.sty)); } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3e0aa17f0fb8..f362ff12a85c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -72,7 +72,7 @@ pub mod cyclomatic_complexity; pub mod derive; pub mod doc; pub mod double_parens; -pub mod drop_ref; +pub mod drop_forget_ref; pub mod entry; pub mod enum_clike; pub mod enum_glob_use; @@ -259,7 +259,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames { max_single_char_names: conf.max_single_char_names, }); - reg.register_late_lint_pass(box drop_ref::Pass); + reg.register_late_lint_pass(box drop_forget_ref::Pass); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box types::InvalidUpcastComparisons); reg.register_late_lint_pass(box regex::Pass::default()); @@ -360,7 +360,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { derive::EXPL_IMPL_CLONE_ON_COPY, doc::DOC_MARKDOWN, double_parens::DOUBLE_PARENS, - drop_ref::DROP_REF, + drop_forget_ref::DROP_REF, + drop_forget_ref::FORGET_REF, entry::MAP_ENTRY, enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, enum_variants::ENUM_VARIANT_NAMES,