about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkyoto7250 <50972773+kyoto7250@users.noreply.github.com>2022-06-10 11:31:25 +0900
committerkyoto7250 <50972773+kyoto7250@users.noreply.github.com>2022-06-27 08:11:58 +0900
commit4decfdec76a6b67dc87f29d6f1a8db148119211d (patch)
tree37f8c18623ba62f9888aaa03de5e5fd992336fa1
parent14212115c4f669d33007d45c2b26623b7879ccc0 (diff)
downloadrust-4decfdec76a6b67dc87f29d6f1a8db148119211d.tar.gz
rust-4decfdec76a6b67dc87f29d6f1a8db148119211d.zip
check msrv
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/use_retain.rs59
-rw-r--r--clippy_utils/src/msrvs.rs5
-rw-r--r--tests/ui/use_retain.fixed32
-rw-r--r--tests/ui/use_retain.rs32
-rw-r--r--tests/ui/use_retain.stderr38
6 files changed, 123 insertions, 45 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 124f0d12b08..716038aa522 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -915,7 +915,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(read_zero_byte_vec::ReadZeroByteVec));
     store.register_late_pass(|| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
     store.register_late_pass(move || Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv)));
-    store.register_late_pass(|| Box::new(use_retain::UseRetain));
+    store.register_late_pass(move || Box::new(use_retain::UseRetain::new(msrv)));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/clippy_lints/src/use_retain.rs b/clippy_lints/src/use_retain.rs
index 7c57020761c..185201514ad 100644
--- a/clippy_lints/src/use_retain.rs
+++ b/clippy_lints/src/use_retain.rs
@@ -2,12 +2,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq};
+use clippy_utils::{meets_msrv, msrvs};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ExprKind::Assign;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::sym;
 
 const ACCEPTABLE_METHODS: [&[&str]; 4] = [
@@ -16,13 +18,13 @@ const ACCEPTABLE_METHODS: [&[&str]; 4] = [
     &paths::SLICE_INTO,
     &paths::VEC_DEQUE_ITER,
 ];
-const ACCEPTABLE_TYPES: [rustc_span::Symbol; 6] = [
-    sym::BTreeSet,
-    sym::BTreeMap,
-    sym::HashSet,
-    sym::HashMap,
-    sym::Vec,
-    sym::VecDeque,
+const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 6] = [
+    (sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
+    (sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
+    (sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
+    (sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)),
+    (sym::Vec, None),
+    (sym::VecDeque, None),
 ];
 
 declare_clippy_lint! {
@@ -46,7 +48,19 @@ declare_clippy_lint! {
     perf,
     "`retain()` is simpler and the same functionalitys"
 }
-declare_lint_pass!(UseRetain => [USE_RETAIN]);
+
+pub struct UseRetain {
+    msrv: Option<RustcVersion>,
+}
+
+impl UseRetain {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(UseRetain => [USE_RETAIN]);
 
 impl<'tcx> LateLintPass<'tcx> for UseRetain {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
@@ -57,11 +71,13 @@ impl<'tcx> LateLintPass<'tcx> for UseRetain {
             && let hir::ExprKind::MethodCall(_, [target_expr], _) = &collect_expr.kind
             && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
             && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) {
-            check_into_iter(cx, parent_expr, left_expr, target_expr);
-            check_iter(cx, parent_expr, left_expr, target_expr);
-            check_to_owned(cx, parent_expr, left_expr, target_expr);
+            check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv);
+            check_iter(cx, parent_expr, left_expr, target_expr, self.msrv);
+            check_to_owned(cx, parent_expr, left_expr, target_expr, self.msrv);
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 fn check_into_iter(
@@ -69,6 +85,7 @@ fn check_into_iter(
     parent_expr: &hir::Expr<'_>,
     left_expr: &hir::Expr<'_>,
     target_expr: &hir::Expr<'_>,
+    msrv: Option<RustcVersion>,
 ) {
     if let hir::ExprKind::MethodCall(_, [into_iter_expr, _], _) = &target_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
@@ -76,7 +93,7 @@ fn check_into_iter(
         && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &into_iter_expr.kind
         && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
         && match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER)
-        && match_acceptable_type(cx, left_expr)
+        && match_acceptable_type(cx, left_expr, msrv)
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
         suggest(cx, parent_expr, left_expr, target_expr);
     }
@@ -87,6 +104,7 @@ fn check_iter(
     parent_expr: &hir::Expr<'_>,
     left_expr: &hir::Expr<'_>,
     target_expr: &hir::Expr<'_>,
+    msrv: Option<RustcVersion>,
 ) {
     if let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
         && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
@@ -98,7 +116,7 @@ fn check_iter(
         && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &iter_expr.kind
         && let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id)
         && match_acceptable_def_path(cx, iter_expr_def_id)
-        && match_acceptable_type(cx, left_expr)
+        && match_acceptable_type(cx, left_expr, msrv)
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
         suggest(cx, parent_expr, left_expr, filter_expr);
     }
@@ -109,8 +127,10 @@ fn check_to_owned(
     parent_expr: &hir::Expr<'_>,
     left_expr: &hir::Expr<'_>,
     target_expr: &hir::Expr<'_>,
+    msrv: Option<RustcVersion>,
 ) {
-    if let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
+    if meets_msrv(msrv,  msrvs::STRING_RETAIN)
+        && let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
         && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
         && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD)
         && let hir::ExprKind::MethodCall(_, [chars_expr, _], _) = &filter_expr.kind
@@ -199,9 +219,10 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo
         .any(|&method| match_def_path(cx, collect_def_id, method))
 }
 
-fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Option<RustcVersion>) -> bool {
     let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
-    ACCEPTABLE_TYPES
-        .iter()
-        .any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty))
+    ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| {
+        is_type_diagnostic_item(cx, expr_ty, *ty)
+            && acceptable_msrv.map_or(true, |acceptable_msrv| meets_msrv(msrv, acceptable_msrv))
+    })
 }
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index 43c0a03c42a..b09c929f76e 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -12,7 +12,7 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
-    1,53,0 { OR_PATTERNS, MANUAL_BITS }
+    1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN }
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS }
     1,50,0 { BOOL_THEN }
@@ -30,7 +30,8 @@ msrv_aliases! {
     1,34,0 { TRY_FROM }
     1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
     1,28,0 { FROM_BOOL }
-    1,26,0 { RANGE_INCLUSIVE }
+    1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN }
+    1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
     1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
     1,16,0 { STR_REPEAT }
     1,24,0 { IS_ASCII_DIGIT }
diff --git a/tests/ui/use_retain.fixed b/tests/ui/use_retain.fixed
index 0c80d0e204a..549b8a62c0c 100644
--- a/tests/ui/use_retain.fixed
+++ b/tests/ui/use_retain.fixed
@@ -1,4 +1,5 @@
 // run-rustfix
+#![feature(custom_inner_attributes)]
 #![warn(clippy::use_retain)]
 #![allow(unused)]
 use std::collections::BTreeMap;
@@ -15,12 +16,16 @@ fn main() {
     hash_set_retain();
     hash_map_retain();
     string_retain();
-    vec_queue_retain();
+    vec_deque_retain();
     vec_retain();
+    _msrv_153();
+    _msrv_126();
+    _msrv_118();
 }
 
 fn binary_heap_retain() {
     // NOTE: Do not lint now, because binary_heap_retain is nighyly API.
+    // And we need to add a test case for msrv if we update this implmention.
     // https://github.com/rust-lang/rust/issues/71503
     let mut heap = BinaryHeap::from([1, 2, 3]);
     heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
@@ -179,7 +184,7 @@ fn vec_retain() {
     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
 }
 
-fn vec_queue_retain() {
+fn vec_deque_retain() {
     let mut vec_deque = VecDeque::new();
     vec_deque.extend(1..5);
 
@@ -210,3 +215,26 @@ fn vec_queue_retain() {
     bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect();
     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
 }
+
+fn _msrv_153() {
+    #![clippy::msrv = "1.52"]
+    let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
+    btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
+
+    let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
+    btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
+}
+
+fn _msrv_126() {
+    #![clippy::msrv = "1.25"]
+    let mut s = String::from("foobar");
+    s = s.chars().filter(|&c| c != 'o').to_owned().collect();
+}
+
+fn _msrv_118() {
+    #![clippy::msrv = "1.17"]
+    let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]);
+    hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
+    let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
+    hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
+}
diff --git a/tests/ui/use_retain.rs b/tests/ui/use_retain.rs
index 08c184486f9..36c4176b8d5 100644
--- a/tests/ui/use_retain.rs
+++ b/tests/ui/use_retain.rs
@@ -1,4 +1,5 @@
 // run-rustfix
+#![feature(custom_inner_attributes)]
 #![warn(clippy::use_retain)]
 #![allow(unused)]
 use std::collections::BTreeMap;
@@ -15,12 +16,16 @@ fn main() {
     hash_set_retain();
     hash_map_retain();
     string_retain();
-    vec_queue_retain();
+    vec_deque_retain();
     vec_retain();
+    _msrv_153();
+    _msrv_126();
+    _msrv_118();
 }
 
 fn binary_heap_retain() {
     // NOTE: Do not lint now, because binary_heap_retain is nighyly API.
+    // And we need to add a test case for msrv if we update this implmention.
     // https://github.com/rust-lang/rust/issues/71503
     let mut heap = BinaryHeap::from([1, 2, 3]);
     heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
@@ -185,7 +190,7 @@ fn vec_retain() {
     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
 }
 
-fn vec_queue_retain() {
+fn vec_deque_retain() {
     let mut vec_deque = VecDeque::new();
     vec_deque.extend(1..5);
 
@@ -216,3 +221,26 @@ fn vec_queue_retain() {
     bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect();
     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
 }
+
+fn _msrv_153() {
+    #![clippy::msrv = "1.52"]
+    let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
+    btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
+
+    let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
+    btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
+}
+
+fn _msrv_126() {
+    #![clippy::msrv = "1.25"]
+    let mut s = String::from("foobar");
+    s = s.chars().filter(|&c| c != 'o').to_owned().collect();
+}
+
+fn _msrv_118() {
+    #![clippy::msrv = "1.17"]
+    let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]);
+    hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
+    let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
+    hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
+}
diff --git a/tests/ui/use_retain.stderr b/tests/ui/use_retain.stderr
index e29d40a2e39..decd406f22a 100644
--- a/tests/ui/use_retain.stderr
+++ b/tests/ui/use_retain.stderr
@@ -1,5 +1,5 @@
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:47:5
+  --> $DIR/use_retain.rs:52:5
    |
 LL |     btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)`
@@ -7,13 +7,13 @@ LL |     btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect()
    = note: `-D clippy::use-retain` implied by `-D warnings`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:48:5
+  --> $DIR/use_retain.rs:53:5
    |
 LL |     btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:49:5
+  --> $DIR/use_retain.rs:54:5
    |
 LL | /     btree_map = btree_map
 LL | |         .into_iter()
@@ -22,37 +22,37 @@ LL | |         .collect();
    | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:71:5
+  --> $DIR/use_retain.rs:76:5
    |
 LL |     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:72:5
+  --> $DIR/use_retain.rs:77:5
    |
 LL |     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:73:5
+  --> $DIR/use_retain.rs:78:5
    |
 LL |     btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:103:5
+  --> $DIR/use_retain.rs:108:5
    |
 LL |     hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:104:5
+  --> $DIR/use_retain.rs:109:5
    |
 LL |     hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:105:5
+  --> $DIR/use_retain.rs:110:5
    |
 LL | /     hash_map = hash_map
 LL | |         .into_iter()
@@ -61,61 +61,61 @@ LL | |         .collect();
    | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:126:5
+  --> $DIR/use_retain.rs:131:5
    |
 LL |     hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:127:5
+  --> $DIR/use_retain.rs:132:5
    |
 LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:128:5
+  --> $DIR/use_retain.rs:133:5
    |
 LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:157:5
+  --> $DIR/use_retain.rs:162:5
    |
 LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:169:5
+  --> $DIR/use_retain.rs:174:5
    |
 LL |     vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:170:5
+  --> $DIR/use_retain.rs:175:5
    |
 LL |     vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:171:5
+  --> $DIR/use_retain.rs:176:5
    |
 LL |     vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:193:5
+  --> $DIR/use_retain.rs:198:5
    |
 LL |     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:194:5
+  --> $DIR/use_retain.rs:199:5
    |
 LL |     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> $DIR/use_retain.rs:195:5
+  --> $DIR/use_retain.rs:200:5
    |
 LL |     vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`