diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b503746cf..a4412292158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -312,6 +312,7 @@ All notable changes to this project will be documented in this file. [`doc_markdown`]: https://github.com/Manishearth/rust-clippy/wiki#doc_markdown [`double_neg`]: https://github.com/Manishearth/rust-clippy/wiki#double_neg [`double_parens`]: https://github.com/Manishearth/rust-clippy/wiki#double_parens +[`drop_copy`]: https://github.com/Manishearth/rust-clippy/wiki#drop_copy [`drop_ref`]: https://github.com/Manishearth/rust-clippy/wiki#drop_ref [`duplicate_underscore_argument`]: https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument [`empty_enum`]: https://github.com/Manishearth/rust-clippy/wiki#empty_enum @@ -333,6 +334,7 @@ All notable changes to this project will be documented in this file. [`for_kv_map`]: https://github.com/Manishearth/rust-clippy/wiki#for_kv_map [`for_loop_over_option`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option [`for_loop_over_result`]: https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result +[`forget_copy`]: https://github.com/Manishearth/rust-clippy/wiki#forget_copy [`forget_ref`]: https://github.com/Manishearth/rust-clippy/wiki#forget_ref [`get_unwrap`]: https://github.com/Manishearth/rust-clippy/wiki#get_unwrap [`identity_op`]: https://github.com/Manishearth/rust-clippy/wiki#identity_op diff --git a/README.md b/README.md index 36ea7e40177..9e3e3e0d482 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ transparently: ## Lints -There are 192 lints included in this crate: +There are 196 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -218,6 +218,7 @@ name [doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | presence of `_`, `::` or camel-case outside backticks in documentation [double_neg](https://github.com/Manishearth/rust-clippy/wiki#double_neg) | warn | `--x`, which is a double negation of `x` and not a pre-decrement as in C/C++ [double_parens](https://github.com/Manishearth/rust-clippy/wiki#double_parens) | warn | Warn on unnecessary double parentheses +[drop_copy](https://github.com/Manishearth/rust-clippy/wiki#drop_copy) | warn | calls to `std::mem::drop` with a value that implements Copy [drop_ref](https://github.com/Manishearth/rust-clippy/wiki#drop_ref) | warn | calls to `std::mem::drop` with a reference instead of an owned value [duplicate_underscore_argument](https://github.com/Manishearth/rust-clippy/wiki#duplicate_underscore_argument) | warn | function arguments having names which only differ by an underscore [empty_enum](https://github.com/Manishearth/rust-clippy/wiki#empty_enum) | allow | enum with no variants @@ -238,6 +239,7 @@ name [for_kv_map](https://github.com/Manishearth/rust-clippy/wiki#for_kv_map) | warn | looping on a map using `iter` when `keys` or `values` would do [for_loop_over_option](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_option) | warn | for-looping over an `Option`, which is more clearly expressed as an `if let` [for_loop_over_result](https://github.com/Manishearth/rust-clippy/wiki#for_loop_over_result) | warn | for-looping over a `Result`, which is more clearly expressed as an `if let` +[forget_copy](https://github.com/Manishearth/rust-clippy/wiki#forget_copy) | warn | calls to `std::mem::forget` with a value that implements Copy [forget_ref](https://github.com/Manishearth/rust-clippy/wiki#forget_ref) | warn | calls to `std::mem::forget` with a reference instead of an owned value [get_unwrap](https://github.com/Manishearth/rust-clippy/wiki#get_unwrap) | warn | using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead [identity_op](https://github.com/Manishearth/rust-clippy/wiki#identity_op) | warn | using identity operations, e.g. `x + 0` or `y / 1` diff --git a/clippy_lints/src/drop_forget_copy.rs b/clippy_lints/src/drop_forget_copy.rs new file mode 100644 index 00000000000..16259f33e7e --- /dev/null +++ b/clippy_lints/src/drop_forget_copy.rs @@ -0,0 +1,96 @@ +use rustc::lint::*; +use rustc::ty; +use rustc::hir::*; +use utils::{match_def_path, paths, span_note_and_lint}; + +/// **What it does:** Checks for calls to `std::mem::drop` with a value +/// that derives the Copy trait +/// +/// **Why is this bad?** Calling `std::mem::drop` [does nothing for types that +/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the +/// value will be copied and moved into the function on invocation. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x:i32 = 42; // i32 implements Copy +/// std::mem::drop(x) // A copy of x is passed to the function, leaving the original unaffected +/// ``` +declare_lint! { + pub DROP_COPY, + Warn, + "calls to `std::mem::drop` with a value that implements Copy" +} + +/// **What it does:** Checks for calls to `std::mem::forget` with a value that +/// derives the Copy trait +/// +/// **Why is this bad?** Calling `std::mem::forget` [does nothing for types that +/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the +/// value will be copied and moved into the function on invocation. +/// +/// An alternative, but also valid, explanation is that Copy types do not implement +/// the Drop trait, which means they have no destructors. Without a destructor, there +/// is nothing for `std::mem::forget` to ignore. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let x:i32 = 42; // i32 implements Copy +/// std::mem::forget(x) // A copy of x is passed to the function, leaving the original unaffected +/// ``` +declare_lint! { + pub FORGET_COPY, + Warn, + "calls to `std::mem::forget` with a value that implements Copy" +} + +#[allow(missing_copy_implementations)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(DROP_COPY, FORGET_COPY) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_let_chain!{[ + let ExprCall(ref path, ref args) = expr.node, + let ExprPath(ref qpath) = path.node, + args.len() == 1, + ], { + let def_id = cx.tables.qpath_def(qpath, path.id).def_id(); + let lint; + let msg; + + if match_def_path(cx.tcx, def_id, &paths::DROP) { + lint = DROP_COPY; + msg = "call to `std::mem::drop` with a value that implements Copy. \ + Dropping a copy leaves the original intact."; + } else if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { + lint = FORGET_COPY; + msg = "call to `std::mem::forget` with a value that implements Copy. \ + Forgetting a copy leaves the original intact."; + } else { + return; + } + + let arg = &args[0]; + let arg_ty = cx.tables.expr_ty(arg); + + let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, arg.id); + if !arg_ty.moves_by_default(cx.tcx.global_tcx(), ¶meter_environment, arg.span) { + span_note_and_lint(cx, + lint, + expr.span, + 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 31b2e23422f..edf568f1c7f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -72,6 +72,7 @@ pub mod cyclomatic_complexity; pub mod derive; pub mod doc; pub mod double_parens; +pub mod drop_forget_copy; pub mod drop_forget_ref; pub mod empty_enum; pub mod entry; @@ -269,6 +270,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { max_single_char_names: conf.max_single_char_names, }); reg.register_late_lint_pass(box drop_forget_ref::Pass); + reg.register_late_lint_pass(box drop_forget_copy::Pass); reg.register_late_lint_pass(box empty_enum::EmptyEnum); reg.register_late_lint_pass(box types::AbsurdExtremeComparisons); reg.register_late_lint_pass(box types::InvalidUpcastComparisons); @@ -375,6 +377,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { derive::EXPL_IMPL_CLONE_ON_COPY, doc::DOC_MARKDOWN, double_parens::DOUBLE_PARENS, + drop_forget_copy::DROP_COPY, + drop_forget_copy::FORGET_COPY, drop_forget_ref::DROP_REF, drop_forget_ref::FORGET_REF, entry::MAP_ENTRY, diff --git a/tests/ui/drop_forget_copy.rs b/tests/ui/drop_forget_copy.rs new file mode 100644 index 00000000000..d92c053476f --- /dev/null +++ b/tests/ui/drop_forget_copy.rs @@ -0,0 +1,62 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(drop_copy, forget_copy)] +#![allow(toplevel_ref_arg, drop_ref, forget_ref, unused_mut)] + +use std::mem::{drop, forget}; +use std::vec::Vec; + +#[derive(Copy, Clone)] +struct SomeStruct { +} + +struct AnotherStruct { + x: u8, + y: u8, + z: Vec +} + +impl Clone for AnotherStruct { + fn clone(& self) -> AnotherStruct { + AnotherStruct{x: self.x, y: self.y, z: self.z.clone()} + } +} + +fn main() { + let s1 = SomeStruct {}; + let s2 = s1; + let s3 = &s1; + let mut s4 = s1; + let ref s5 = s1; + + drop(s1); + drop(s2); + drop(s3); + drop(s4); + drop(s5); + + forget(s1); + forget(s2); + forget(s3); + forget(s4); + forget(s5); + + let a1 = AnotherStruct {x: 255, y: 0, z: vec![1, 2, 3]}; + let a2 = &a1; + let mut a3 = a1.clone(); + let ref a4 = a1; + let a5 = a1.clone(); + + drop(a2); + drop(a3); + drop(a4); + drop(a5); + + forget(a2); + let a3 = &a1; + forget(a3); + forget(a4); + let a5 = a1.clone(); + forget(a5); +} diff --git a/tests/ui/drop_forget_copy.stderr b/tests/ui/drop_forget_copy.stderr new file mode 100644 index 00000000000..79ad1dbabeb --- /dev/null +++ b/tests/ui/drop_forget_copy.stderr @@ -0,0 +1,192 @@ +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:33:5 + | +33 | drop(s1); + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/drop_forget_copy.rs:4:9 + | +4 | #![deny(drop_copy, forget_copy)] + | ^^^^^^^^^ +note: argument has type SomeStruct + --> $DIR/drop_forget_copy.rs:33:10 + | +33 | drop(s1); + | ^^ + +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:34:5 + | +34 | drop(s2); + | ^^^^^^^^ + | +note: argument has type SomeStruct + --> $DIR/drop_forget_copy.rs:34:10 + | +34 | drop(s2); + | ^^ + +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:35:5 + | +35 | drop(s3); + | ^^^^^^^^ + | +note: argument has type &SomeStruct + --> $DIR/drop_forget_copy.rs:35:10 + | +35 | drop(s3); + | ^^ + +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:36:5 + | +36 | drop(s4); + | ^^^^^^^^ + | +note: argument has type SomeStruct + --> $DIR/drop_forget_copy.rs:36:10 + | +36 | drop(s4); + | ^^ + +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:37:5 + | +37 | drop(s5); + | ^^^^^^^^ + | +note: argument has type &SomeStruct + --> $DIR/drop_forget_copy.rs:37:10 + | +37 | drop(s5); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:39:5 + | +39 | forget(s1); + | ^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/drop_forget_copy.rs:4:20 + | +4 | #![deny(drop_copy, forget_copy)] + | ^^^^^^^^^^^ +note: argument has type SomeStruct + --> $DIR/drop_forget_copy.rs:39:12 + | +39 | forget(s1); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:40:5 + | +40 | forget(s2); + | ^^^^^^^^^^ + | +note: argument has type SomeStruct + --> $DIR/drop_forget_copy.rs:40:12 + | +40 | forget(s2); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:41:5 + | +41 | forget(s3); + | ^^^^^^^^^^ + | +note: argument has type &SomeStruct + --> $DIR/drop_forget_copy.rs:41:12 + | +41 | forget(s3); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:42:5 + | +42 | forget(s4); + | ^^^^^^^^^^ + | +note: argument has type SomeStruct + --> $DIR/drop_forget_copy.rs:42:12 + | +42 | forget(s4); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:43:5 + | +43 | forget(s5); + | ^^^^^^^^^^ + | +note: argument has type &SomeStruct + --> $DIR/drop_forget_copy.rs:43:12 + | +43 | forget(s5); + | ^^ + +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:51:5 + | +51 | drop(a2); + | ^^^^^^^^ + | +note: argument has type &AnotherStruct + --> $DIR/drop_forget_copy.rs:51:10 + | +51 | drop(a2); + | ^^ + +error: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:53:5 + | +53 | drop(a4); + | ^^^^^^^^ + | +note: argument has type &AnotherStruct + --> $DIR/drop_forget_copy.rs:53:10 + | +53 | drop(a4); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:56:5 + | +56 | forget(a2); + | ^^^^^^^^^^ + | +note: argument has type &AnotherStruct + --> $DIR/drop_forget_copy.rs:56:12 + | +56 | forget(a2); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:58:5 + | +58 | forget(a3); + | ^^^^^^^^^^ + | +note: argument has type &AnotherStruct + --> $DIR/drop_forget_copy.rs:58:12 + | +58 | forget(a3); + | ^^ + +error: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_copy.rs:59:5 + | +59 | forget(a4); + | ^^^^^^^^^^ + | +note: argument has type &AnotherStruct + --> $DIR/drop_forget_copy.rs:59:12 + | +59 | forget(a4); + | ^^ + +error: aborting due to 15 previous errors + diff --git a/tests/ui/drop_forget_ref.stderr b/tests/ui/drop_forget_ref.stderr index 80c724c19c4..bbda347c9a9 100644 --- a/tests/ui/drop_forget_ref.stderr +++ b/tests/ui/drop_forget_ref.stderr @@ -15,6 +15,19 @@ note: argument has type &SomeStruct 12 | drop(&SomeStruct); | ^^^^^^^^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:12:5 + | +12 | drop(&SomeStruct); + | ^^^^^^^^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:12:10 + | +12 | drop(&SomeStruct); + | ^^^^^^^^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:13:5 | @@ -32,6 +45,19 @@ note: argument has type &SomeStruct 13 | forget(&SomeStruct); | ^^^^^^^^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:13:5 + | +13 | forget(&SomeStruct); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:13:12 + | +13 | forget(&SomeStruct); + | ^^^^^^^^^^^ + error: call to `std::mem::drop` with a reference argument. Dropping a reference does nothing --> $DIR/drop_forget_ref.rs:16:5 | @@ -44,6 +70,19 @@ note: argument has type &SomeStruct 16 | drop(&owned1); | ^^^^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:16:5 + | +16 | drop(&owned1); + | ^^^^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:16:10 + | +16 | drop(&owned1); + | ^^^^^^^ + error: call to `std::mem::drop` with a reference argument. Dropping a reference does nothing --> $DIR/drop_forget_ref.rs:17:5 | @@ -56,6 +95,19 @@ note: argument has type &&SomeStruct 17 | drop(&&owned1); | ^^^^^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:17:5 + | +17 | drop(&&owned1); + | ^^^^^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &&SomeStruct + --> $DIR/drop_forget_ref.rs:17:10 + | +17 | drop(&&owned1); + | ^^^^^^^^ + error: call to `std::mem::drop` with a reference argument. Dropping a reference does nothing --> $DIR/drop_forget_ref.rs:18:5 | @@ -80,6 +132,19 @@ note: argument has type &SomeStruct 21 | forget(&owned2); | ^^^^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:21:5 + | +21 | forget(&owned2); + | ^^^^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:21:12 + | +21 | forget(&owned2); + | ^^^^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:22:5 | @@ -92,6 +157,19 @@ note: argument has type &&SomeStruct 22 | forget(&&owned2); | ^^^^^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:22:5 + | +22 | forget(&&owned2); + | ^^^^^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &&SomeStruct + --> $DIR/drop_forget_ref.rs:22:12 + | +22 | forget(&&owned2); + | ^^^^^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:23:5 | @@ -116,6 +194,19 @@ note: argument has type &SomeStruct 27 | drop(reference1); | ^^^^^^^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:27:5 + | +27 | drop(reference1); + | ^^^^^^^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:27:10 + | +27 | drop(reference1); + | ^^^^^^^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:28:5 | @@ -128,6 +219,19 @@ note: argument has type &SomeStruct 28 | forget(&*reference1); | ^^^^^^^^^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:28:5 + | +28 | forget(&*reference1); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:28:12 + | +28 | forget(&*reference1); + | ^^^^^^^^^^^^ + error: call to `std::mem::drop` with a reference argument. Dropping a reference does nothing --> $DIR/drop_forget_ref.rs:31:5 | @@ -164,6 +268,19 @@ note: argument has type &SomeStruct 36 | drop(reference4); | ^^^^^^^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:36:5 + | +36 | drop(reference4); + | ^^^^^^^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:36:10 + | +36 | drop(reference4); + | ^^^^^^^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:37:5 | @@ -176,6 +293,19 @@ note: argument has type &SomeStruct 37 | forget(reference4); | ^^^^^^^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:37:5 + | +37 | forget(reference4); + | ^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:37:12 + | +37 | forget(reference4); + | ^^^^^^^^^^ + error: call to `std::mem::drop` with a reference argument. Dropping a reference does nothing --> $DIR/drop_forget_ref.rs:42:5 | @@ -188,6 +318,19 @@ note: argument has type &T 42 | drop(&val); | ^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:42:5 + | +42 | drop(&val); + | ^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &T + --> $DIR/drop_forget_ref.rs:42:10 + | +42 | drop(&val); + | ^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:48:5 | @@ -200,6 +343,19 @@ note: argument has type &T 48 | forget(&val); | ^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:48:5 + | +48 | forget(&val); + | ^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &T + --> $DIR/drop_forget_ref.rs:48:12 + | +48 | forget(&val); + | ^^^^ + error: call to `std::mem::drop` with a reference argument. Dropping a reference does nothing --> $DIR/drop_forget_ref.rs:56:5 | @@ -212,6 +368,19 @@ note: argument has type &SomeStruct 56 | std::mem::drop(&SomeStruct); | ^^^^^^^^^^^ +warning: call to `std::mem::drop` with a value that implements Copy. Dropping a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:56:5 + | +56 | std::mem::drop(&SomeStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(drop_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:56:20 + | +56 | std::mem::drop(&SomeStruct); + | ^^^^^^^^^^^ + error: call to `std::mem::forget` with a reference argument. Forgetting a reference does nothing --> $DIR/drop_forget_ref.rs:59:5 | @@ -224,5 +393,18 @@ note: argument has type &SomeStruct 59 | std::mem::forget(&SomeStruct); | ^^^^^^^^^^^ +warning: call to `std::mem::forget` with a value that implements Copy. Forgetting a copy leaves the original intact. + --> $DIR/drop_forget_ref.rs:59:5 + | +59 | std::mem::forget(&SomeStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(forget_copy)] on by default +note: argument has type &SomeStruct + --> $DIR/drop_forget_ref.rs:59:22 + | +59 | std::mem::forget(&SomeStruct); + | ^^^^^^^^^^^ + error: aborting due to 18 previous errors diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 9832bd992c1..e553afcf05f 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -1,6 +1,7 @@ #![feature(plugin)] #![plugin(clippy)] + use std::sync::Arc; use std::rc::Rc; @@ -8,6 +9,7 @@ use std::mem::forget as forgetSomething; use std::mem as memstuff; #[deny(mem_forget)] +#[allow(forget_copy)] fn main() { let five: i32 = 5; forgetSomething(five); diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 47c61adfbbf..21cb65f82eb 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -1,25 +1,25 @@ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:16:5 + --> $DIR/mem_forget.rs:18:5 | -16 | memstuff::forget(six); +18 | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/mem_forget.rs:10:8 + --> $DIR/mem_forget.rs:11:8 | -10 | #[deny(mem_forget)] +11 | #[deny(mem_forget)] | ^^^^^^^^^^ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:20:5 + --> $DIR/mem_forget.rs:22:5 | -20 | std::mem::forget(seven); +22 | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of mem::forget on Drop type - --> $DIR/mem_forget.rs:24:5 + --> $DIR/mem_forget.rs:26:5 | -24 | forgetSomething(eight); +26 | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors