diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs index 9e55852ef7a6..ac6c0e57257c 100644 --- a/clippy_lints/src/methods/clear_with_drain.rs +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -1,8 +1,29 @@ -use rustc_lint::{LateContext, LintContext}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::higher::Range; +use clippy_utils::is_range_full; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; +use rustc_span::Span; use super::CLEAR_WITH_DRAIN; // TODO: Adjust the parameters as necessary -pub(super) fn check(cx: &LateContext) { - todo!(); +// see clippy_lints/src/methods/mod.rs to add call to this check in `check_methods` +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, arg: &Expr<'_>) { + let ty = cx.typeck_results().expr_ty(recv); + if is_type_diagnostic_item(cx, ty, sym::Vec) && let Some(range) = Range::hir(arg) && is_range_full(cx, recv, range) + { + span_lint_and_sugg( + cx, + CLEAR_WITH_DRAIN, + span.with_hi(expr.span.hi()), + "`drain` used to clear a `Vec`", + "try", + "clear()".to_string(), + Applicability::MachineApplicable, + ); + } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4e74ac6af2bb..257bc4eccc30 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -111,7 +111,7 @@ use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_ use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, return_ty}; use if_chain::if_chain; use rustc_hir as hir; -use rustc_hir::{Expr, ExprKind, TraitItem, TraitItemKind}; +use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -3590,7 +3590,13 @@ impl Methods { _ => {}, }, ("drain", [arg]) => { - iter_with_drain::check(cx, expr, recv, span, arg); + if let Node::Stmt(Stmt { hir_id: _, kind, .. }) = cx.tcx.hir().get_parent(expr.hir_id) + && matches!(kind, StmtKind::Semi(_)) + { + clear_with_drain::check(cx, expr, recv, span, arg); + } else { + iter_with_drain::check(cx, expr, recv, span, arg); + } }, ("ends_with", [arg]) => { if let ExprKind::MethodCall(.., span) = expr.kind {