Implement the forget_ref lint.
This commit is contained in:
@@ -25,12 +25,32 @@ declare_lint! {
|
|||||||
"calls to `std::mem::drop` with a reference instead of an owned value"
|
"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)]
|
#[allow(missing_copy_implementations)]
|
||||||
pub struct Pass;
|
pub struct Pass;
|
||||||
|
|
||||||
impl LintPass for Pass {
|
impl LintPass for Pass {
|
||||||
fn get_lints(&self) -> LintArray {
|
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!{[
|
if_let_chain!{[
|
||||||
let ExprCall(ref path, ref args) = expr.node,
|
let ExprCall(ref path, ref args) = expr.node,
|
||||||
let ExprPath(ref qpath) = path.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,
|
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 = &args[0];
|
||||||
let arg_ty = cx.tcx.tables().expr_ty(arg);
|
let arg_ty = cx.tcx.tables().expr_ty(arg);
|
||||||
if let ty::TyRef(..) = arg_ty.sty {
|
if let ty::TyRef(..) = arg_ty.sty {
|
||||||
span_note_and_lint(cx,
|
span_note_and_lint(cx,
|
||||||
DROP_REF,
|
lint,
|
||||||
expr.span,
|
expr.span,
|
||||||
"call to `std::mem::drop` with a reference argument. \
|
msg,
|
||||||
Dropping a reference does nothing",
|
|
||||||
arg.span,
|
arg.span,
|
||||||
&format!("argument has type {}", arg_ty.sty));
|
&format!("argument has type {}", arg_ty.sty));
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ pub mod cyclomatic_complexity;
|
|||||||
pub mod derive;
|
pub mod derive;
|
||||||
pub mod doc;
|
pub mod doc;
|
||||||
pub mod double_parens;
|
pub mod double_parens;
|
||||||
pub mod drop_ref;
|
pub mod drop_forget_ref;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
pub mod enum_clike;
|
pub mod enum_clike;
|
||||||
pub mod enum_glob_use;
|
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 {
|
reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames {
|
||||||
max_single_char_names: conf.max_single_char_names,
|
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::AbsurdExtremeComparisons);
|
||||||
reg.register_late_lint_pass(box types::InvalidUpcastComparisons);
|
reg.register_late_lint_pass(box types::InvalidUpcastComparisons);
|
||||||
reg.register_late_lint_pass(box regex::Pass::default());
|
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,
|
derive::EXPL_IMPL_CLONE_ON_COPY,
|
||||||
doc::DOC_MARKDOWN,
|
doc::DOC_MARKDOWN,
|
||||||
double_parens::DOUBLE_PARENS,
|
double_parens::DOUBLE_PARENS,
|
||||||
drop_ref::DROP_REF,
|
drop_forget_ref::DROP_REF,
|
||||||
|
drop_forget_ref::FORGET_REF,
|
||||||
entry::MAP_ENTRY,
|
entry::MAP_ENTRY,
|
||||||
enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
|
enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
|
||||||
enum_variants::ENUM_VARIANT_NAMES,
|
enum_variants::ENUM_VARIANT_NAMES,
|
||||||
|
|||||||
Reference in New Issue
Block a user