diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs index 4f5b7762e3c..6ce3fdae407 100644 --- a/clippy_lints/src/methods/clear_with_drain.rs +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -1,16 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_range_full; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::{Expr, ExprKind, QPath}; +use rustc_hir::{Expr, ExprKind, LangItem, QPath}; use rustc_lint::LateContext; use rustc_span::symbol::sym; use rustc_span::Span; use super::CLEAR_WITH_DRAIN; -const ACCEPTABLE_TYPES_WITH_ARG: [rustc_span::Symbol; 3] = [sym::String, sym::Vec, sym::VecDeque]; +// Add `String` here when it is added to diagnostic items +const ACCEPTABLE_TYPES_WITH_ARG: [rustc_span::Symbol; 2] = [sym::Vec, sym::VecDeque]; const ACCEPTABLE_TYPES_WITHOUT_ARG: [rustc_span::Symbol; 3] = [sym::BinaryHeap, sym::HashMap, sym::HashSet]; @@ -30,11 +31,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, types: &[rustc_span::Symbol]) -> bool { let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); types.iter().any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty)) + // String type is a lang item but not a diagnostic item for now so we need a separate check + || is_type_lang_item(cx, expr_ty, LangItem::String) } fn suggest(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span) { if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def() - && let Some(ty_name) = cx.tcx.get_diagnostic_name(adt.did()) + // Use `opt_item_name` while `String` is not a diagnostic item + && let Some(ty_name) = cx.tcx.opt_item_name(adt.did()) { span_lint_and_sugg( cx, diff --git a/tests/ui/clear_with_drain.fixed b/tests/ui/clear_with_drain.fixed index dd02cc9148f..2d9545eeed1 100644 --- a/tests/ui/clear_with_drain.fixed +++ b/tests/ui/clear_with_drain.fixed @@ -2,108 +2,357 @@ #![allow(unused)] #![warn(clippy::clear_with_drain)] -use std::collections::BinaryHeap; -use std::collections::HashMap; -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; -fn range() { +fn vec_range() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(0..v.len()); // Yay + let iter = v.drain(0..v.len()); + // Do not lint because iterator is used let mut v = vec![1, 2, 3]; - let n = v.drain(0..v.len()).count(); // Yay + let n = v.drain(0..v.len()).count(); + // Do not lint because iterator is assigned and used let mut v = vec![1, 2, 3]; - let iter = v.drain(usize::MIN..v.len()); // Yay + let iter = v.drain(usize::MIN..v.len()); let n = iter.count(); + // Do lint let mut v = vec![1, 2, 3]; - v.clear(); // Nay + v.clear(); + // Do lint let mut v = vec![1, 2, 3]; - v.clear(); // Nay + v.clear(); } -fn range_from() { +fn vec_range_from() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(0..); // Yay + let iter = v.drain(0..); + // Do not lint because iterator is assigned and used let mut v = vec![1, 2, 3]; - let mut iter = v.drain(0..); // Yay + let mut iter = v.drain(0..); let next = iter.next(); + // Do not lint because iterator is used let mut v = vec![1, 2, 3]; - let next = v.drain(usize::MIN..).next(); // Yay + let next = v.drain(usize::MIN..).next(); + // Do lint let mut v = vec![1, 2, 3]; - v.clear(); // Nay + v.clear(); + // Do lint let mut v = vec![1, 2, 3]; - v.clear(); // Nay + v.clear(); } -fn range_full() { +fn vec_range_full() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(..); // Yay + let iter = v.drain(..); + // Do not lint because iterator is used let mut v = vec![1, 2, 3]; - // Yay for x in v.drain(..) { let y = format!("x = {x}"); } + // Do lint let mut v = vec![1, 2, 3]; - v.clear(); // Nay + v.clear(); } -fn range_to() { +fn vec_range_to() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(..v.len()); // Yay + let iter = v.drain(..v.len()); + // Do not lint because iterator is assigned and used let mut v = vec![1, 2, 3]; - let iter = v.drain(..v.len()); // Yay + let iter = v.drain(..v.len()); for x in iter { let y = format!("x = {x}"); } + // Do lint let mut v = vec![1, 2, 3]; - v.clear(); // Nay + v.clear(); } -fn partial_drains() { - let mut v = vec![1, 2, 3]; - v.drain(1..); // Yay - let mut v = vec![1, 2, 3]; - v.drain(1..).max(); // Yay +fn vec_partial_drains() { + // Do not lint any of these because the ranges are not full let mut v = vec![1, 2, 3]; - v.drain(..v.len() - 1); // Yay + v.drain(1..); let mut v = vec![1, 2, 3]; - v.drain(..v.len() - 1).min(); // Yay + v.drain(1..).max(); let mut v = vec![1, 2, 3]; - v.drain(1..v.len() - 1); // Yay + v.drain(..v.len() - 1); let mut v = vec![1, 2, 3]; - let w: Vec = v.drain(1..v.len() - 1).collect(); // Yay + v.drain(..v.len() - 1).min(); + + let mut v = vec![1, 2, 3]; + v.drain(1..v.len() - 1); + let mut v = vec![1, 2, 3]; + let w: Vec = v.drain(1..v.len() - 1).collect(); } -fn main() { - let mut deque: VecDeque<_> = [1, 2, 3].into(); +fn vec_deque_range() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..deque.len()); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let n = deque.drain(0..deque.len()).count(); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(usize::MIN..deque.len()); + let n = iter.count(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_range_from() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let mut iter = deque.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let next = deque.drain(usize::MIN..).next(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_range_full() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + for x in deque.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_range_to() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..).max(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1).min(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + let w: Vec = deque.drain(1..deque.len() - 1).collect(); +} + +fn string_range() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..s.len()); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let n = s.drain(0..s.len()).count(); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(usize::MIN..s.len()); + let n = iter.count(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_range_from() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let mut iter = s.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let next = s.drain(usize::MIN..).next(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_range_full() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + for x in s.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_range_to() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut s = String::from("Hello, world!"); + s.drain(1..); + let mut s = String::from("Hello, world!"); + s.drain(1..).max(); + + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1); + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1).min(); + + let mut s = String::from("Hello, world!"); + s.drain(1..s.len() - 1); + let mut s = String::from("Hello, world!"); + let w: String = s.drain(1..s.len() - 1).collect(); +} + +fn hash_set() { + // Do not lint because iterator is assigned + let mut set = HashSet::from([1, 2, 3]); + let iter = set.drain(); + + // Do not lint because iterator is assigned and used + let mut set = HashSet::from([1, 2, 3]); + let mut iter = set.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut set = HashSet::from([1, 2, 3]); + let next = set.drain().next(); + + // Do lint let mut set = HashSet::from([1, 2, 3]); set.clear(); - - let mut a = HashMap::new(); - a.insert(1, "a"); - a.insert(2, "b"); - a.clear(); - - let mut heap = BinaryHeap::from([1, 3]); - heap.clear(); - - // Not firing for now because `String` is not reckognized by `is_type_diagnostic_item` - let mut s = String::from("α is alpha, β is beta"); - s.drain(..); } + +fn hash_map() { + // Do not lint because iterator is assigned + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let iter = map.drain(); + + // Do not lint because iterator is assigned and used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let mut iter = map.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let next = map.drain().next(); + + // Do lint + let mut map = HashMap::from([(1, "a"), (2, "b")]); + map.clear(); +} + +fn binary_heap() { + // Do not lint because iterator is assigned + let mut heap = BinaryHeap::from([1, 2]); + let iter = heap.drain(); + + // Do not lint because iterator is assigned and used + let mut heap = BinaryHeap::from([1, 2]); + let mut iter = heap.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut heap = BinaryHeap::from([1, 2]); + let next = heap.drain().next(); + + // Do lint + let mut heap = BinaryHeap::from([1, 2]); + heap.clear(); +} + +fn main() {} diff --git a/tests/ui/clear_with_drain.rs b/tests/ui/clear_with_drain.rs index af2fe503d9a..4d60ee46e18 100644 --- a/tests/ui/clear_with_drain.rs +++ b/tests/ui/clear_with_drain.rs @@ -2,108 +2,357 @@ #![allow(unused)] #![warn(clippy::clear_with_drain)] -use std::collections::BinaryHeap; -use std::collections::HashMap; -use std::collections::HashSet; -use std::collections::VecDeque; +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; -fn range() { +fn vec_range() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(0..v.len()); // Yay + let iter = v.drain(0..v.len()); + // Do not lint because iterator is used let mut v = vec![1, 2, 3]; - let n = v.drain(0..v.len()).count(); // Yay + let n = v.drain(0..v.len()).count(); + // Do not lint because iterator is assigned and used let mut v = vec![1, 2, 3]; - let iter = v.drain(usize::MIN..v.len()); // Yay + let iter = v.drain(usize::MIN..v.len()); let n = iter.count(); + // Do lint let mut v = vec![1, 2, 3]; - v.drain(0..v.len()); // Nay + v.drain(0..v.len()); + // Do lint let mut v = vec![1, 2, 3]; - v.drain(usize::MIN..v.len()); // Nay + v.drain(usize::MIN..v.len()); } -fn range_from() { +fn vec_range_from() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(0..); // Yay + let iter = v.drain(0..); + // Do not lint because iterator is assigned and used let mut v = vec![1, 2, 3]; - let mut iter = v.drain(0..); // Yay + let mut iter = v.drain(0..); let next = iter.next(); + // Do not lint because iterator is used let mut v = vec![1, 2, 3]; - let next = v.drain(usize::MIN..).next(); // Yay + let next = v.drain(usize::MIN..).next(); + // Do lint let mut v = vec![1, 2, 3]; - v.drain(0..); // Nay + v.drain(0..); + // Do lint let mut v = vec![1, 2, 3]; - v.drain(usize::MIN..); // Nay + v.drain(usize::MIN..); } -fn range_full() { +fn vec_range_full() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(..); // Yay + let iter = v.drain(..); + // Do not lint because iterator is used let mut v = vec![1, 2, 3]; - // Yay for x in v.drain(..) { let y = format!("x = {x}"); } + // Do lint let mut v = vec![1, 2, 3]; - v.drain(..); // Nay + v.drain(..); } -fn range_to() { +fn vec_range_to() { + // Do not lint because iterator is assigned let mut v = vec![1, 2, 3]; - let iter = v.drain(..v.len()); // Yay + let iter = v.drain(..v.len()); + // Do not lint because iterator is assigned and used let mut v = vec![1, 2, 3]; - let iter = v.drain(..v.len()); // Yay + let iter = v.drain(..v.len()); for x in iter { let y = format!("x = {x}"); } + // Do lint let mut v = vec![1, 2, 3]; - v.drain(..v.len()); // Nay + v.drain(..v.len()); } -fn partial_drains() { - let mut v = vec![1, 2, 3]; - v.drain(1..); // Yay - let mut v = vec![1, 2, 3]; - v.drain(1..).max(); // Yay +fn vec_partial_drains() { + // Do not lint any of these because the ranges are not full let mut v = vec![1, 2, 3]; - v.drain(..v.len() - 1); // Yay + v.drain(1..); let mut v = vec![1, 2, 3]; - v.drain(..v.len() - 1).min(); // Yay + v.drain(1..).max(); let mut v = vec![1, 2, 3]; - v.drain(1..v.len() - 1); // Yay + v.drain(..v.len() - 1); let mut v = vec![1, 2, 3]; - let w: Vec = v.drain(1..v.len() - 1).collect(); // Yay + v.drain(..v.len() - 1).min(); + + let mut v = vec![1, 2, 3]; + v.drain(1..v.len() - 1); + let mut v = vec![1, 2, 3]; + let w: Vec = v.drain(1..v.len() - 1).collect(); } -fn main() { - let mut deque: VecDeque<_> = [1, 2, 3].into(); +fn vec_deque_range() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..deque.len()); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let n = deque.drain(0..deque.len()).count(); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(usize::MIN..deque.len()); + let n = iter.count(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(0..deque.len()); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(usize::MIN..deque.len()); +} + +fn vec_deque_range_from() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let mut iter = deque.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let next = deque.drain(usize::MIN..).next(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(0..); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(usize::MIN..); +} + +fn vec_deque_range_full() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + for x in deque.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); deque.drain(..); +} - let mut set = HashSet::from([1, 2, 3]); - set.drain(); +fn vec_deque_range_to() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); - let mut a = HashMap::new(); - a.insert(1, "a"); - a.insert(2, "b"); - a.drain(); + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + for x in iter { + let y = format!("x = {x}"); + } - let mut heap = BinaryHeap::from([1, 3]); - heap.drain(); + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len()); +} - // Not firing for now because `String` is not reckognized by `is_type_diagnostic_item` - let mut s = String::from("α is alpha, β is beta"); +fn vec_deque_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..).max(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1).min(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + let w: Vec = deque.drain(1..deque.len() - 1).collect(); +} + +fn string_range() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..s.len()); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let n = s.drain(0..s.len()).count(); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(usize::MIN..s.len()); + let n = iter.count(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(0..s.len()); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(usize::MIN..s.len()); +} + +fn string_range_from() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let mut iter = s.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let next = s.drain(usize::MIN..).next(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(0..); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(usize::MIN..); +} + +fn string_range_full() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + for x in s.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); s.drain(..); } + +fn string_range_to() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(..s.len()); +} + +fn string_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut s = String::from("Hello, world!"); + s.drain(1..); + let mut s = String::from("Hello, world!"); + s.drain(1..).max(); + + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1); + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1).min(); + + let mut s = String::from("Hello, world!"); + s.drain(1..s.len() - 1); + let mut s = String::from("Hello, world!"); + let w: String = s.drain(1..s.len() - 1).collect(); +} + +fn hash_set() { + // Do not lint because iterator is assigned + let mut set = HashSet::from([1, 2, 3]); + let iter = set.drain(); + + // Do not lint because iterator is assigned and used + let mut set = HashSet::from([1, 2, 3]); + let mut iter = set.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut set = HashSet::from([1, 2, 3]); + let next = set.drain().next(); + + // Do lint + let mut set = HashSet::from([1, 2, 3]); + set.drain(); +} + +fn hash_map() { + // Do not lint because iterator is assigned + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let iter = map.drain(); + + // Do not lint because iterator is assigned and used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let mut iter = map.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let next = map.drain().next(); + + // Do lint + let mut map = HashMap::from([(1, "a"), (2, "b")]); + map.drain(); +} + +fn binary_heap() { + // Do not lint because iterator is assigned + let mut heap = BinaryHeap::from([1, 2]); + let iter = heap.drain(); + + // Do not lint because iterator is assigned and used + let mut heap = BinaryHeap::from([1, 2]); + let mut iter = heap.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut heap = BinaryHeap::from([1, 2]); + let next = heap.drain().next(); + + // Do lint + let mut heap = BinaryHeap::from([1, 2]); + heap.drain(); +} + +fn main() {} diff --git a/tests/ui/clear_with_drain.stderr b/tests/ui/clear_with_drain.stderr index 2c0cc846de2..20158da1121 100644 --- a/tests/ui/clear_with_drain.stderr +++ b/tests/ui/clear_with_drain.stderr @@ -1,64 +1,130 @@ error: `drain` used to clear a `Vec` - --> $DIR/clear_with_drain.rs:22:7 + --> $DIR/clear_with_drain.rs:23:7 | -LL | v.drain(0..v.len()); // Nay +LL | v.drain(0..v.len()); | ^^^^^^^^^^^^^^^^^ help: try: `clear()` | = note: `-D clippy::clear-with-drain` implied by `-D warnings` error: `drain` used to clear a `Vec` - --> $DIR/clear_with_drain.rs:25:7 + --> $DIR/clear_with_drain.rs:27:7 | -LL | v.drain(usize::MIN..v.len()); // Nay +LL | v.drain(usize::MIN..v.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> $DIR/clear_with_drain.rs:40:7 + --> $DIR/clear_with_drain.rs:46:7 | -LL | v.drain(0..); // Nay +LL | v.drain(0..); | ^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> $DIR/clear_with_drain.rs:43:7 + --> $DIR/clear_with_drain.rs:50:7 | -LL | v.drain(usize::MIN..); // Nay +LL | v.drain(usize::MIN..); | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> $DIR/clear_with_drain.rs:57:7 + --> $DIR/clear_with_drain.rs:66:7 | -LL | v.drain(..); // Nay +LL | v.drain(..); | ^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> $DIR/clear_with_drain.rs:71:7 + --> $DIR/clear_with_drain.rs:83:7 | -LL | v.drain(..v.len()); // Nay +LL | v.drain(..v.len()); | ^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> $DIR/clear_with_drain.rs:93:11 + --> $DIR/clear_with_drain.rs:121:11 + | +LL | deque.drain(0..deque.len()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:125:11 + | +LL | deque.drain(usize::MIN..deque.len()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:144:11 + | +LL | deque.drain(0..); + | ^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:148:11 + | +LL | deque.drain(usize::MIN..); + | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:164:11 | LL | deque.drain(..); | ^^^^^^^^^ help: try: `clear()` +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:181:11 + | +LL | deque.drain(..deque.len()); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:219:7 + | +LL | s.drain(0..s.len()); + | ^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:223:7 + | +LL | s.drain(usize::MIN..s.len()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:242:7 + | +LL | s.drain(0..); + | ^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:246:7 + | +LL | s.drain(usize::MIN..); + | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:262:7 + | +LL | s.drain(..); + | ^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:279:7 + | +LL | s.drain(..s.len()); + | ^^^^^^^^^^^^^^^^ help: try: `clear()` + error: `drain` used to clear a `HashSet` - --> $DIR/clear_with_drain.rs:96:9 + --> $DIR/clear_with_drain.rs:317:9 | LL | set.drain(); | ^^^^^^^ help: try: `clear()` error: `drain` used to clear a `HashMap` - --> $DIR/clear_with_drain.rs:101:7 + --> $DIR/clear_with_drain.rs:336:9 | -LL | a.drain(); - | ^^^^^^^ help: try: `clear()` +LL | map.drain(); + | ^^^^^^^ help: try: `clear()` error: `drain` used to clear a `BinaryHeap` - --> $DIR/clear_with_drain.rs:104:10 + --> $DIR/clear_with_drain.rs:355:10 | LL | heap.drain(); | ^^^^^^^ help: try: `clear()` -error: aborting due to 10 previous errors +error: aborting due to 21 previous errors