diff --git a/CHANGELOG.md b/CHANGELOG.md index abe975fa42b2..5212bc247db4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5040,6 +5040,7 @@ Released 2018-09-13 [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy [`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop [`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref +[`drop_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_result [`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 88611eb70878..fbf09a18d13f 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -173,7 +173,9 @@ macro_rules! define_Conf { } })* // ignore contents of the third_party key - Ok(Field::third_party) => drop(map.next_value::()) + Ok(Field::third_party) => { + let _ = map.next_value::(); + } } } let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* }; diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 6b76a44debff..4ce2cc8dd230 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -999,7 +999,7 @@ fn try_rename_file(old_name: &Path, new_name: &Path) -> bool { match fs::rename(old_name, new_name) { Ok(()) => true, Err(e) => { - drop(fs::remove_file(new_name)); + let _ = fs::remove_file(new_name); if e.kind() == io::ErrorKind::NotFound { false } else { diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5a109fcc2ccd..8d4d13056704 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -145,6 +145,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::drop_forget_ref::DROP_NON_DROP_INFO, crate::drop_forget_ref::FORGET_NON_DROP_INFO, crate::drop_forget_ref::MEM_FORGET_INFO, + crate::drop_result::DROP_RESULT_INFO, crate::duplicate_mod::DUPLICATE_MOD_INFO, crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, crate::empty_drop::EMPTY_DROP_INFO, diff --git a/clippy_lints/src/drop_result.rs b/clippy_lints/src/drop_result.rs new file mode 100644 index 000000000000..061f9c7d70af --- /dev/null +++ b/clippy_lints/src/drop_result.rs @@ -0,0 +1,44 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `std::mem::drop(t)` where `t` is + /// a `Result`. + /// + /// ### Why is this bad? + /// Dropping a `Result` means that its value wasn't checked. + /// + /// ### Example + /// ```no_run + /// # use std::mem; + /// mem::drop(Err::<(), &str>("something went wrong")); + /// ``` + #[clippy::version = "1.76.0"] + pub DROP_RESULT, + pedantic, + "`mem::drop` usage on `Result` types" +} + +declare_lint_pass!(DropResult => [ + DROP_RESULT, +]); + +impl<'tcx> LateLintPass<'tcx> for DropResult { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Call(path, [arg]) = expr.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) + && fn_name == sym::mem_drop + && let arg_ty = cx.typeck_results().expr_ty(arg) + && is_type_diagnostic_item(cx, arg_ty, sym::Result) + { + span_lint(cx, DROP_RESULT, expr.span, "using `drop()` on a `Result` type"); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index abe768d50c7a..c70cae6e1afc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -108,6 +108,7 @@ mod disallowed_types; mod doc; mod double_parens; mod drop_forget_ref; +mod drop_result; mod duplicate_mod; mod else_if_without_else; mod empty_drop; @@ -1069,6 +1070,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter)); store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType)); store.register_late_pass(|_| Box::new(impl_hash_with_borrow_str_and_bytes::ImplHashWithBorrowStrBytes)); + store.register_late_pass(|_| Box::new(drop_result::DropResult)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/drop_non_drop.rs b/tests/ui/drop_non_drop.rs index 6dbcb7777d49..0969f8ec0605 100644 --- a/tests/ui/drop_non_drop.rs +++ b/tests/ui/drop_non_drop.rs @@ -1,4 +1,5 @@ #![warn(clippy::drop_non_drop)] +#![allow(clippy::drop_result)] use core::mem::drop; diff --git a/tests/ui/drop_non_drop.stderr b/tests/ui/drop_non_drop.stderr index a571076f68cd..b71a6a932219 100644 --- a/tests/ui/drop_non_drop.stderr +++ b/tests/ui/drop_non_drop.stderr @@ -1,11 +1,11 @@ error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes - --> $DIR/drop_non_drop.rs:22:5 + --> $DIR/drop_non_drop.rs:23:5 | LL | drop(Foo); | ^^^^^^^^^ | note: argument has type `main::Foo` - --> $DIR/drop_non_drop.rs:22:10 + --> $DIR/drop_non_drop.rs:23:10 | LL | drop(Foo); | ^^^ @@ -13,13 +13,13 @@ LL | drop(Foo); = help: to override `-D warnings` add `#[allow(clippy::drop_non_drop)]` error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes - --> $DIR/drop_non_drop.rs:38:5 + --> $DIR/drop_non_drop.rs:39:5 | LL | drop(Baz(Foo)); | ^^^^^^^^^^^^^^ | note: argument has type `main::Baz` - --> $DIR/drop_non_drop.rs:38:10 + --> $DIR/drop_non_drop.rs:39:10 | LL | drop(Baz(Foo)); | ^^^^^^^^ diff --git a/tests/ui/drop_result.rs b/tests/ui/drop_result.rs new file mode 100644 index 000000000000..c3c26b9ab5b7 --- /dev/null +++ b/tests/ui/drop_result.rs @@ -0,0 +1,12 @@ +#![warn(clippy::drop_result)] + +fn make_result(t: T) -> Result { + Ok(t) +} + +fn main() { + drop(Ok::("a".to_string())); //~ ERROR: using `drop()` on a `Result` type + let x = Err::<(), String>("b".to_string()); + drop(x); //~ ERROR: using `drop()` on a `Result` type + drop(make_result("a".to_string())); //~ ERROR: using `drop()` on a `Result` type +} diff --git a/tests/ui/drop_result.stderr b/tests/ui/drop_result.stderr new file mode 100644 index 000000000000..9dc6bacd1f3a --- /dev/null +++ b/tests/ui/drop_result.stderr @@ -0,0 +1,23 @@ +error: using `drop()` on a `Result` type + --> $DIR/drop_result.rs:8:5 + | +LL | drop(Ok::("a".to_string())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::drop-result` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::drop_result)]` + +error: using `drop()` on a `Result` type + --> $DIR/drop_result.rs:10:5 + | +LL | drop(x); + | ^^^^^^^ + +error: using `drop()` on a `Result` type + --> $DIR/drop_result.rs:11:5 + | +LL | drop(make_result("a".to_string())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors +