]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | // run-rustfix |
2 | ||
3 | #![allow( | |
4 | unused, | |
5 | clippy::no_effect, | |
6 | clippy::redundant_closure_call, | |
7 | clippy::many_single_char_names, | |
8 | clippy::needless_pass_by_value, | |
9 | clippy::option_map_unit_fn | |
10 | )] | |
11 | #![warn( | |
12 | clippy::redundant_closure, | |
13 | clippy::redundant_closure_for_method_calls, | |
14 | clippy::needless_borrow | |
15 | )] | |
16 | ||
17 | use std::path::PathBuf; | |
18 | ||
19 | macro_rules! mac { | |
20 | () => { | |
21 | foobar() | |
22 | }; | |
23 | } | |
24 | ||
25 | macro_rules! closure_mac { | |
26 | () => { | |
27 | |n| foo(n) | |
28 | }; | |
29 | } | |
30 | ||
31 | fn main() { | |
32 | let a = Some(1u8).map(|a| foo(a)); | |
33 | meta(|a| foo(a)); | |
34 | let c = Some(1u8).map(|a| {1+2; foo}(a)); | |
35 | true.then(|| mac!()); // don't lint function in macro expansion | |
36 | Some(1).map(closure_mac!()); // don't lint closure in macro expansion | |
37 | let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec! | |
38 | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | |
39 | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | |
40 | unsafe { | |
41 | Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn | |
42 | } | |
43 | ||
44 | // See #815 | |
45 | let e = Some(1u8).map(|a| divergent(a)); | |
46 | let e = Some(1u8).map(|a| generic(a)); | |
47 | let e = Some(1u8).map(generic); | |
48 | // See #515 | |
49 | let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> = | |
50 | Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) }); | |
17df50a5 XL |
51 | |
52 | // issue #7224 | |
53 | let _: Option<Vec<u32>> = Some(0).map(|_| vec![]); | |
f20569fa XL |
54 | } |
55 | ||
56 | trait TestTrait { | |
57 | fn trait_foo(self) -> bool; | |
58 | fn trait_foo_ref(&self) -> bool; | |
59 | } | |
60 | ||
61 | struct TestStruct<'a> { | |
62 | some_ref: &'a i32, | |
63 | } | |
64 | ||
65 | impl<'a> TestStruct<'a> { | |
66 | fn foo(self) -> bool { | |
67 | false | |
68 | } | |
69 | unsafe fn foo_unsafe(self) -> bool { | |
70 | true | |
71 | } | |
72 | } | |
73 | ||
74 | impl<'a> TestTrait for TestStruct<'a> { | |
75 | fn trait_foo(self) -> bool { | |
76 | false | |
77 | } | |
78 | fn trait_foo_ref(&self) -> bool { | |
79 | false | |
80 | } | |
81 | } | |
82 | ||
83 | impl<'a> std::ops::Deref for TestStruct<'a> { | |
84 | type Target = char; | |
85 | fn deref(&self) -> &char { | |
86 | &'a' | |
87 | } | |
88 | } | |
89 | ||
90 | fn test_redundant_closures_containing_method_calls() { | |
91 | let i = 10; | |
92 | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | |
93 | let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); | |
94 | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | |
95 | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); | |
96 | let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); | |
97 | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | |
98 | let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); | |
99 | unsafe { | |
100 | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); | |
101 | } | |
102 | let e = Some("str").map(|s| s.to_string()); | |
103 | let e = Some("str").map(str::to_string); | |
104 | let e = Some('a').map(|s| s.to_uppercase()); | |
105 | let e = Some('a').map(char::to_uppercase); | |
106 | let e: std::vec::Vec<usize> = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); | |
107 | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | |
108 | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); | |
109 | let p = Some(PathBuf::new()); | |
110 | let e = p.as_ref().and_then(|s| s.to_str()); | |
111 | let c = Some(TestStruct { some_ref: &i }) | |
112 | .as_ref() | |
113 | .map(|c| c.to_ascii_uppercase()); | |
114 | ||
115 | fn test_different_borrow_levels<T>(t: &[&T]) | |
116 | where | |
117 | T: TestTrait, | |
118 | { | |
119 | t.iter().filter(|x| x.trait_foo_ref()); | |
120 | t.iter().map(|x| x.trait_foo_ref()); | |
121 | } | |
122 | ||
123 | let mut some = Some(|x| x * x); | |
124 | let arr = [Ok(1), Err(2)]; | |
125 | let _: Vec<_> = arr.iter().map(|x| x.map_err(|e| some.take().unwrap()(e))).collect(); | |
126 | } | |
127 | ||
128 | struct Thunk<T>(Box<dyn FnMut() -> T>); | |
129 | ||
130 | impl<T> Thunk<T> { | |
131 | fn new<F: 'static + FnOnce() -> T>(f: F) -> Thunk<T> { | |
132 | let mut option = Some(f); | |
133 | // This should not trigger redundant_closure (#1439) | |
134 | Thunk(Box::new(move || option.take().unwrap()())) | |
135 | } | |
136 | ||
137 | fn unwrap(self) -> T { | |
138 | let Thunk(mut f) = self; | |
139 | f() | |
140 | } | |
141 | } | |
142 | ||
143 | fn foobar() { | |
144 | let thunk = Thunk::new(|| println!("Hello, world!")); | |
145 | thunk.unwrap() | |
146 | } | |
147 | ||
148 | fn meta<F>(f: F) | |
149 | where | |
150 | F: Fn(u8), | |
151 | { | |
152 | f(1u8) | |
153 | } | |
154 | ||
155 | fn foo(_: u8) {} | |
156 | ||
157 | fn foo2(_: u8) -> u8 { | |
158 | 1u8 | |
159 | } | |
160 | ||
161 | fn all<X, F>(x: &[X], y: &X, f: F) -> bool | |
162 | where | |
163 | F: Fn(&X, &X) -> bool, | |
164 | { | |
165 | x.iter().all(|e| f(e, y)) | |
166 | } | |
167 | ||
168 | fn below(x: &u8, y: &u8) -> bool { | |
169 | x < y | |
170 | } | |
171 | ||
172 | unsafe fn unsafe_fn(_: u8) {} | |
173 | ||
174 | fn divergent(_: u8) -> ! { | |
175 | unimplemented!() | |
176 | } | |
177 | ||
178 | fn generic<T>(_: T) -> u8 { | |
179 | 0 | |
180 | } | |
181 | ||
182 | fn passes_fn_mut(mut x: Box<dyn FnMut()>) { | |
183 | requires_fn_once(|| x()); | |
184 | } | |
185 | fn requires_fn_once<T: FnOnce()>(_: T) {} | |
186 | ||
187 | fn test_redundant_closure_with_function_pointer() { | |
188 | type FnPtrType = fn(u8); | |
189 | let foo_ptr: FnPtrType = foo; | |
190 | let a = Some(1u8).map(|a| foo_ptr(a)); | |
191 | } | |
192 | ||
193 | fn test_redundant_closure_with_another_closure() { | |
194 | let closure = |a| println!("{}", a); | |
195 | let a = Some(1u8).map(|a| closure(a)); | |
196 | } | |
197 | ||
198 | fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 { | |
199 | // Currently f is called when result of make_lazy is called. | |
200 | // If the closure is removed, f will be called when make_lazy itself is | |
201 | // called. This changes semantics, so the closure must stay. | |
202 | Box::new(move |x| f()(x)) | |
203 | } | |
204 | ||
205 | fn call<F: FnOnce(&mut String) -> String>(f: F) -> String { | |
206 | f(&mut "Hello".to_owned()) | |
207 | } | |
208 | fn test_difference_in_mutability() { | |
209 | call(|s| s.clone()); | |
210 | } | |
211 | ||
212 | struct Bar; | |
213 | impl std::ops::Deref for Bar { | |
214 | type Target = str; | |
215 | fn deref(&self) -> &str { | |
216 | "hi" | |
217 | } | |
218 | } | |
219 | ||
220 | fn test_deref_with_trait_method() { | |
221 | let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>(); | |
222 | } | |
136023e0 XL |
223 | |
224 | fn mutable_closure_used_again(x: Vec<i32>, y: Vec<i32>, z: Vec<i32>) { | |
225 | let mut res = Vec::new(); | |
226 | let mut add_to_res = |n| res.push(n); | |
227 | x.into_iter().for_each(|x| add_to_res(x)); | |
228 | y.into_iter().for_each(|x| add_to_res(x)); | |
229 | z.into_iter().for_each(|x| add_to_res(x)); | |
230 | } | |
231 | ||
232 | fn mutable_closure_in_loop() { | |
233 | let mut value = 0; | |
234 | let mut closure = |n| value += n; | |
235 | for _ in 0..5 { | |
236 | Some(1).map(|n| closure(n)); | |
237 | } | |
238 | } |