//@run-rustfix #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; fn main() { binary_heap_retain(); btree_set_retain(); btree_map_retain(); hash_set_retain(); hash_map_retain(); string_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 nightly API. // And we need to add a test case for msrv if we update this implementation. // 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(); heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect(); heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); // Do not lint, because type conversion is performed heap = heap.into_iter().filter(|x| x % 2 == 0).collect::>(); heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect::>(); heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect::>(); // Do not lint, because this expression is not assign. let mut bar: BinaryHeap = heap.iter().filter(|&x| x % 2 == 0).copied().collect(); let mut foobar: BinaryHeap = heap.into_iter().filter(|x| x % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); } fn btree_map_retain() { let mut btree_map: BTreeMap = (0..8).map(|x| (x, x * 10)).collect(); // Do lint. btree_map.retain(|k, _| k % 2 == 0); btree_map.retain(|_, &mut v| v % 2 == 0); btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); // Do not lint. btree_map = btree_map .into_iter() .filter(|(x, _)| x % 2 == 0) .collect::>(); // Do not lint, because this expression is not assign. let mut foobar: BTreeMap = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. btree_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect(); } fn btree_set_retain() { let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]); // Do lint. btree_set.retain(|x| x % 2 == 0); btree_set.retain(|x| x % 2 == 0); btree_set.retain(|x| x % 2 == 0); // Do not lint, because type conversion is performed btree_set = btree_set .iter() .filter(|&x| x % 2 == 0) .copied() .collect::>(); btree_set = btree_set .iter() .filter(|&x| x % 2 == 0) .cloned() .collect::>(); btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect::>(); // Do not lint, because this expression is not assign. let mut foobar: BTreeSet = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); let mut bar: BTreeSet = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); } fn hash_map_retain() { let mut hash_map: HashMap = (0..8).map(|x| (x, x * 10)).collect(); // Do lint. hash_map.retain(|k, _| k % 2 == 0); hash_map.retain(|_, &mut v| v % 2 == 0); hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); // Do not lint. hash_map = hash_map .into_iter() .filter(|(x, _)| x % 2 == 0) .collect::>(); // Do not lint, because this expression is not assign. let mut foobar: HashMap = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. hash_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect(); } fn hash_set_retain() { let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); // Do lint. hash_set.retain(|x| x % 2 == 0); hash_set.retain(|x| x % 2 == 0); hash_set.retain(|x| x % 2 == 0); // Do not lint, because type conversion is performed hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::>(); hash_set = hash_set .iter() .filter(|&x| x % 2 == 0) .copied() .collect::>(); hash_set = hash_set .iter() .filter(|&x| x % 2 == 0) .cloned() .collect::>(); // Do not lint, because this expression is not assign. let mut bar: HashSet = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); let mut foobar: HashSet = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); bar = foobar.into_iter().filter(|&x| x % 2 == 0).collect(); } fn string_retain() { let mut s = String::from("foobar"); // Do lint. s.retain(|c| c != 'o'); // Do not lint, because this expression is not assign. let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect(); // Do not lint, because it is an assignment to a different variable. s = bar.chars().filter(|&c| c != 'o').to_owned().collect(); } fn vec_retain() { let mut vec = vec![0, 1, 2]; // Do lint. vec.retain(|x| x % 2 == 0); vec.retain(|x| x % 2 == 0); vec.retain(|x| x % 2 == 0); // Do not lint, because type conversion is performed vec = vec.into_iter().filter(|x| x % 2 == 0).collect::>(); vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::>(); vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect::>(); // Do not lint, because this expression is not assign. let mut bar: Vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); let mut foobar: Vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); } fn vec_deque_retain() { let mut vec_deque = VecDeque::new(); vec_deque.extend(1..5); // Do lint. vec_deque.retain(|x| x % 2 == 0); vec_deque.retain(|x| x % 2 == 0); vec_deque.retain(|x| x % 2 == 0); // Do not lint, because type conversion is performed vec_deque = vec_deque .iter() .filter(|&x| x % 2 == 0) .copied() .collect::>(); vec_deque = vec_deque .iter() .filter(|&x| x % 2 == 0) .cloned() .collect::>(); vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect::>(); // Do not lint, because this expression is not assign. let mut bar: VecDeque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); let mut foobar: VecDeque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); // Do not lint, because it is an assignment to a different variable. bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); } #[clippy::msrv = "1.52"] fn _msrv_153() { let mut btree_map: BTreeMap = (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(); } #[clippy::msrv = "1.25"] fn _msrv_126() { let mut s = String::from("foobar"); s = s.chars().filter(|&c| c != 'o').to_owned().collect(); } #[clippy::msrv = "1.17"] fn _msrv_118() { 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 = (0..8).map(|x| (x, x * 10)).collect(); hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); }