• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //@run-rustfix
2 #![warn(clippy::manual_retain)]
3 #![allow(unused, clippy::redundant_clone)]
4 use std::collections::BTreeMap;
5 use std::collections::BTreeSet;
6 use std::collections::BinaryHeap;
7 use std::collections::HashMap;
8 use std::collections::HashSet;
9 use std::collections::VecDeque;
10 
main()11 fn main() {
12     binary_heap_retain();
13     btree_set_retain();
14     btree_map_retain();
15     hash_set_retain();
16     hash_map_retain();
17     string_retain();
18     vec_deque_retain();
19     vec_retain();
20     _msrv_153();
21     _msrv_126();
22     _msrv_118();
23 }
24 
binary_heap_retain()25 fn binary_heap_retain() {
26     // NOTE: Do not lint now, because binary_heap_retain is nightly API.
27     // And we need to add a test case for msrv if we update this implementation.
28     // https://github.com/rust-lang/rust/issues/71503
29     let mut heap = BinaryHeap::from([1, 2, 3]);
30     heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
31     heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect();
32     heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
33 
34     // Do not lint, because type conversion is performed
35     heap = heap.into_iter().filter(|x| x % 2 == 0).collect::<BinaryHeap<i8>>();
36     heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect::<BinaryHeap<i8>>();
37     heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect::<BinaryHeap<i8>>();
38 
39     // Do not lint, because this expression is not assign.
40     let mut bar: BinaryHeap<i8> = heap.iter().filter(|&x| x % 2 == 0).copied().collect();
41     let mut foobar: BinaryHeap<i8> = heap.into_iter().filter(|x| x % 2 == 0).collect();
42 
43     // Do not lint, because it is an assignment to a different variable.
44     bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
45     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
46 }
47 
btree_map_retain()48 fn btree_map_retain() {
49     let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
50     // Do lint.
51     btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
52     btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
53     btree_map = btree_map
54         .into_iter()
55         .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0))
56         .collect();
57 
58     // Do not lint.
59     btree_map = btree_map
60         .into_iter()
61         .filter(|(x, _)| x % 2 == 0)
62         .collect::<BTreeMap<i8, i8>>();
63 
64     // Do not lint, because this expression is not assign.
65     let mut foobar: BTreeMap<i8, i8> = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
66 
67     // Do not lint, because it is an assignment to a different variable.
68     btree_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect();
69 }
70 
btree_set_retain()71 fn btree_set_retain() {
72     let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
73 
74     // Do lint.
75     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
76     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
77     btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
78 
79     // Do not lint, because type conversion is performed
80     btree_set = btree_set
81         .iter()
82         .filter(|&x| x % 2 == 0)
83         .copied()
84         .collect::<BTreeSet<i8>>();
85 
86     btree_set = btree_set
87         .iter()
88         .filter(|&x| x % 2 == 0)
89         .cloned()
90         .collect::<BTreeSet<i8>>();
91 
92     btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect::<BTreeSet<i8>>();
93 
94     // Do not lint, because this expression is not assign.
95     let mut foobar: BTreeSet<i8> = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
96     let mut bar: BTreeSet<i8> = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
97 
98     // Do not lint, because it is an assignment to a different variable.
99     bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
100     bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect();
101     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
102 }
103 
hash_map_retain()104 fn hash_map_retain() {
105     let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
106     // Do lint.
107     hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
108     hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
109     hash_map = hash_map
110         .into_iter()
111         .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0))
112         .collect();
113 
114     // Do not lint.
115     hash_map = hash_map
116         .into_iter()
117         .filter(|(x, _)| x % 2 == 0)
118         .collect::<HashMap<i8, i8>>();
119 
120     // Do not lint, because this expression is not assign.
121     let mut foobar: HashMap<i8, i8> = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
122 
123     // Do not lint, because it is an assignment to a different variable.
124     hash_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect();
125 }
126 
hash_set_retain()127 fn hash_set_retain() {
128     let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]);
129     // Do lint.
130     hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
131     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
132     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
133 
134     // Do not lint, because type conversion is performed
135     hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>();
136     hash_set = hash_set
137         .iter()
138         .filter(|&x| x % 2 == 0)
139         .copied()
140         .collect::<HashSet<i8>>();
141 
142     hash_set = hash_set
143         .iter()
144         .filter(|&x| x % 2 == 0)
145         .cloned()
146         .collect::<HashSet<i8>>();
147 
148     // Do not lint, because this expression is not assign.
149     let mut bar: HashSet<i8> = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
150     let mut foobar: HashSet<i8> = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
151 
152     // Do not lint, because it is an assignment to a different variable.
153     bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
154     bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect();
155     bar = foobar.into_iter().filter(|&x| x % 2 == 0).collect();
156 }
157 
string_retain()158 fn string_retain() {
159     let mut s = String::from("foobar");
160     // Do lint.
161     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
162 
163     // Do not lint, because this expression is not assign.
164     let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect();
165 
166     // Do not lint, because it is an assignment to a different variable.
167     s = bar.chars().filter(|&c| c != 'o').to_owned().collect();
168 }
169 
vec_retain()170 fn vec_retain() {
171     let mut vec = vec![0, 1, 2];
172     // Do lint.
173     vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
174     vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
175     vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
176 
177     // Do not lint, because type conversion is performed
178     vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>();
179     vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>();
180     vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect::<Vec<i8>>();
181 
182     // Do not lint, because this expression is not assign.
183     let mut bar: Vec<i8> = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
184     let mut foobar: Vec<i8> = vec.into_iter().filter(|x| x % 2 == 0).collect();
185 
186     // Do not lint, because it is an assignment to a different variable.
187     bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
188     bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect();
189     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
190 }
191 
vec_deque_retain()192 fn vec_deque_retain() {
193     let mut vec_deque = VecDeque::new();
194     vec_deque.extend(1..5);
195 
196     // Do lint.
197     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
198     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect();
199     vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
200 
201     // Do not lint, because type conversion is performed
202     vec_deque = vec_deque
203         .iter()
204         .filter(|&x| x % 2 == 0)
205         .copied()
206         .collect::<VecDeque<i8>>();
207     vec_deque = vec_deque
208         .iter()
209         .filter(|&x| x % 2 == 0)
210         .cloned()
211         .collect::<VecDeque<i8>>();
212     vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect::<VecDeque<i8>>();
213 
214     // Do not lint, because this expression is not assign.
215     let mut bar: VecDeque<i8> = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
216     let mut foobar: VecDeque<i8> = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
217 
218     // Do not lint, because it is an assignment to a different variable.
219     bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
220     bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect();
221     bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
222 }
223 
224 #[clippy::msrv = "1.52"]
_msrv_153()225 fn _msrv_153() {
226     let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
227     btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
228 
229     let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
230     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
231 }
232 
233 #[clippy::msrv = "1.25"]
_msrv_126()234 fn _msrv_126() {
235     let mut s = String::from("foobar");
236     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
237 }
238 
239 #[clippy::msrv = "1.17"]
_msrv_118()240 fn _msrv_118() {
241     let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]);
242     hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
243     let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
244     hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
245 }
246