mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-26 22:50:56 +00:00
Implement the forget_ref lint.
This commit is contained in:
parent
f55d20ff46
commit
e4a4d0c361
2 changed files with 41 additions and 8 deletions
|
@ -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));
|
||||
}
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue