about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/methods/clear_with_drain.rs12
-rw-r--r--tests/ui/clear_with_drain.fixed333
-rw-r--r--tests/ui/clear_with_drain.rs333
-rw-r--r--tests/ui/clear_with_drain.stderr104
4 files changed, 675 insertions, 107 deletions
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() {
+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(1..); // Yay
+    v.drain(1..);
     let mut v = vec![1, 2, 3];
-    v.drain(1..).max(); // Yay
+    v.drain(1..).max();
 
     let mut v = vec![1, 2, 3];
-    v.drain(..v.len() - 1); // Yay
+    v.drain(..v.len() - 1);
     let mut v = vec![1, 2, 3];
-    v.drain(..v.len() - 1).min(); // Yay
+    v.drain(..v.len() - 1).min();
 
     let mut v = vec![1, 2, 3];
-    v.drain(1..v.len() - 1); // Yay
+    v.drain(1..v.len() - 1);
     let mut v = vec![1, 2, 3];
-    let w: Vec<i8> = v.drain(1..v.len() - 1).collect(); // Yay
+    let w: Vec<i8> = v.drain(1..v.len() - 1).collect();
+}
+
+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 main() {
-    let mut deque: VecDeque<_> = [1, 2, 3].into();
+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<i8> = 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();
+fn hash_map() {
+    // Do not lint because iterator is assigned
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let iter = map.drain();
 
-    let mut heap = BinaryHeap::from([1, 3]);
-    heap.clear();
+    // 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();
 
-    // 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(..);
+    // 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() {
+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(1..); // Yay
+    v.drain(1..);
     let mut v = vec![1, 2, 3];
-    v.drain(1..).max(); // Yay
+    v.drain(1..).max();
 
     let mut v = vec![1, 2, 3];
-    v.drain(..v.len() - 1); // Yay
+    v.drain(..v.len() - 1);
     let mut v = vec![1, 2, 3];
-    v.drain(..v.len() - 1).min(); // Yay
+    v.drain(..v.len() - 1).min();
 
     let mut v = vec![1, 2, 3];
-    v.drain(1..v.len() - 1); // Yay
+    v.drain(1..v.len() - 1);
     let mut v = vec![1, 2, 3];
-    let w: Vec<i8> = v.drain(1..v.len() - 1).collect(); // Yay
+    let w: Vec<i8> = v.drain(1..v.len() - 1).collect();
+}
+
+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 main() {
-    let mut deque: VecDeque<_> = [1, 2, 3].into();
+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(..);
+}
+
+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.drain(..deque.len());
+}
+
+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<i8> = 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();
+}
 
-    let mut a = HashMap::new();
-    a.insert(1, "a");
-    a.insert(2, "b");
-    a.drain();
+fn hash_map() {
+    // Do not lint because iterator is assigned
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let iter = map.drain();
 
-    let mut heap = BinaryHeap::from([1, 3]);
-    heap.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();
 
-    // 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(..);
+    // 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