Implement the forget_ref lint.

This commit is contained in:
Theemathas Chirananthavat 2016-12-29 19:43:22 -08:00
parent f55d20ff46
commit e4a4d0c361
2 changed files with 41 additions and 8 deletions

View file

@ -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));
}

View file

@ -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,