]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/tests/ui/eta.fixed
New upstream version 1.63.0+dfsg1
[rustc.git] / src / tools / clippy / tests / ui / eta.fixed
1 // run-rustfix
2
3 #![allow(
4 unused,
5 clippy::no_effect,
6 clippy::redundant_closure_call,
7 clippy::needless_pass_by_value,
8 clippy::option_map_unit_fn,
9 clippy::needless_borrow
10 )]
11 #![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
12
13 use std::path::{Path, PathBuf};
14
15 macro_rules! mac {
16 () => {
17 foobar()
18 };
19 }
20
21 macro_rules! closure_mac {
22 () => {
23 |n| foo(n)
24 };
25 }
26
27 fn main() {
28 let a = Some(1u8).map(foo);
29 let c = Some(1u8).map(|a| {1+2; foo}(a));
30 true.then(|| mac!()); // don't lint function in macro expansion
31 Some(1).map(closure_mac!()); // don't lint closure in macro expansion
32 let _: Option<Vec<u8>> = true.then(std::vec::Vec::new); // special case vec!
33 let d = Some(1u8).map(|a| foo(foo2(a))); //is adjusted?
34 all(&[1, 2, 3], &&2, below); //is adjusted
35 unsafe {
36 Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn
37 }
38
39 // See #815
40 let e = Some(1u8).map(|a| divergent(a));
41 let e = Some(1u8).map(generic);
42 let e = Some(1u8).map(generic);
43 // See #515
44 let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> =
45 Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) });
46
47 // issue #7224
48 let _: Option<Vec<u32>> = Some(0).map(|_| vec![]);
49 }
50
51 trait TestTrait {
52 fn trait_foo(self) -> bool;
53 fn trait_foo_ref(&self) -> bool;
54 }
55
56 struct TestStruct<'a> {
57 some_ref: &'a i32,
58 }
59
60 impl<'a> TestStruct<'a> {
61 fn foo(self) -> bool {
62 false
63 }
64 unsafe fn foo_unsafe(self) -> bool {
65 true
66 }
67 }
68
69 impl<'a> TestTrait for TestStruct<'a> {
70 fn trait_foo(self) -> bool {
71 false
72 }
73 fn trait_foo_ref(&self) -> bool {
74 false
75 }
76 }
77
78 impl<'a> std::ops::Deref for TestStruct<'a> {
79 type Target = char;
80 fn deref(&self) -> &char {
81 &'a'
82 }
83 }
84
85 fn test_redundant_closures_containing_method_calls() {
86 let i = 10;
87 let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo);
88 let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo);
89 let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref());
90 let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear);
91 unsafe {
92 let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe());
93 }
94 let e = Some("str").map(std::string::ToString::to_string);
95 let e = Some('a').map(char::to_uppercase);
96 let e: std::vec::Vec<usize> = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect();
97 let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect();
98 let e = Some(PathBuf::new()).as_ref().and_then(|s| s.to_str());
99 let c = Some(TestStruct { some_ref: &i })
100 .as_ref()
101 .map(|c| c.to_ascii_uppercase());
102
103 fn test_different_borrow_levels<T>(t: &[&T])
104 where
105 T: TestTrait,
106 {
107 t.iter().filter(|x| x.trait_foo_ref());
108 t.iter().map(|x| x.trait_foo_ref());
109 }
110 }
111
112 struct Thunk<T>(Box<dyn FnMut() -> T>);
113
114 impl<T> Thunk<T> {
115 fn new<F: 'static + FnOnce() -> T>(f: F) -> Thunk<T> {
116 let mut option = Some(f);
117 // This should not trigger redundant_closure (#1439)
118 Thunk(Box::new(move || option.take().unwrap()()))
119 }
120
121 fn unwrap(self) -> T {
122 let Thunk(mut f) = self;
123 f()
124 }
125 }
126
127 fn foobar() {
128 let thunk = Thunk::new(|| println!("Hello, world!"));
129 thunk.unwrap()
130 }
131
132 fn foo(_: u8) {}
133
134 fn foo2(_: u8) -> u8 {
135 1u8
136 }
137
138 fn all<X, F>(x: &[X], y: &X, f: F) -> bool
139 where
140 F: Fn(&X, &X) -> bool,
141 {
142 x.iter().all(|e| f(e, y))
143 }
144
145 fn below(x: &u8, y: &u8) -> bool {
146 x < y
147 }
148
149 unsafe fn unsafe_fn(_: u8) {}
150
151 fn divergent(_: u8) -> ! {
152 unimplemented!()
153 }
154
155 fn generic<T>(_: T) -> u8 {
156 0
157 }
158
159 fn passes_fn_mut(mut x: Box<dyn FnMut()>) {
160 requires_fn_once(x);
161 }
162 fn requires_fn_once<T: FnOnce()>(_: T) {}
163
164 fn test_redundant_closure_with_function_pointer() {
165 type FnPtrType = fn(u8);
166 let foo_ptr: FnPtrType = foo;
167 let a = Some(1u8).map(foo_ptr);
168 }
169
170 fn test_redundant_closure_with_another_closure() {
171 let closure = |a| println!("{}", a);
172 let a = Some(1u8).map(closure);
173 }
174
175 fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 {
176 // Currently f is called when result of make_lazy is called.
177 // If the closure is removed, f will be called when make_lazy itself is
178 // called. This changes semantics, so the closure must stay.
179 Box::new(move |x| f()(x))
180 }
181
182 fn call<F: FnOnce(&mut String) -> String>(f: F) -> String {
183 f(&mut "Hello".to_owned())
184 }
185 fn test_difference_in_mutability() {
186 call(|s| s.clone());
187 }
188
189 struct Bar;
190 impl std::ops::Deref for Bar {
191 type Target = str;
192 fn deref(&self) -> &str {
193 "hi"
194 }
195 }
196
197 fn test_deref_with_trait_method() {
198 let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
199 }
200
201 fn mutable_closure_used_again(x: Vec<i32>, y: Vec<i32>, z: Vec<i32>) {
202 let mut res = Vec::new();
203 let mut add_to_res = |n| res.push(n);
204 x.into_iter().for_each(&mut add_to_res);
205 y.into_iter().for_each(&mut add_to_res);
206 z.into_iter().for_each(add_to_res);
207 }
208
209 fn mutable_closure_in_loop() {
210 let mut value = 0;
211 let mut closure = |n| value += n;
212 for _ in 0..5 {
213 Some(1).map(&mut closure);
214
215 let mut value = 0;
216 let mut in_loop = |n| value += n;
217 Some(1).map(in_loop);
218 }
219 }
220
221 fn late_bound_lifetimes() {
222 fn take_asref_path<P: AsRef<Path>>(path: P) {}
223
224 fn map_str<F>(thunk: F)
225 where
226 F: FnOnce(&str),
227 {
228 }
229
230 fn map_str_to_path<F>(thunk: F)
231 where
232 F: FnOnce(&str) -> &Path,
233 {
234 }
235 map_str(|s| take_asref_path(s));
236 map_str_to_path(|s| s.as_ref());
237 }
238
239 mod type_param_bound {
240 trait Trait {
241 fn fun();
242 }
243
244 fn take<T: 'static>(_: T) {}
245
246 fn test<X: Trait>() {
247 // don't lint, but it's questionable that rust requires a cast
248 take(|| X::fun());
249 take(X::fun as fn());
250 }
251 }
252
253 // #8073 Don't replace closure with `Arc<F>` or `Rc<F>`
254 fn arc_fp() {
255 let rc = std::rc::Rc::new(|| 7);
256 let arc = std::sync::Arc::new(|n| n + 1);
257 let ref_arc = &std::sync::Arc::new(|_| 5);
258
259 true.then(|| rc());
260 (0..5).map(|n| arc(n));
261 Some(4).map(|n| ref_arc(n));
262 }
263
264 // #8460 Don't replace closures with params bounded as `ref`
265 mod bind_by_ref {
266 struct A;
267 struct B;
268
269 impl From<&A> for B {
270 fn from(A: &A) -> Self {
271 B
272 }
273 }
274
275 fn test() {
276 // should not lint
277 Some(A).map(|a| B::from(&a));
278 // should not lint
279 Some(A).map(|ref a| B::from(a));
280 }
281 }
282
283 // #7812 False positive on coerced closure
284 fn coerced_closure() {
285 fn function_returning_unit<F: FnMut(i32)>(f: F) {}
286 function_returning_unit(|x| std::process::exit(x));
287
288 fn arr() -> &'static [u8; 0] {
289 &[]
290 }
291 fn slice_fn(_: impl FnOnce() -> &'static [u8]) {}
292 slice_fn(|| arr());
293 }
294
295 // https://github.com/rust-lang/rust-clippy/issues/7861
296 fn box_dyn() {
297 fn f(_: impl Fn(usize) -> Box<dyn std::any::Any>) {}
298 f(|x| Box::new(x));
299 }
300
301 // https://github.com/rust-lang/rust-clippy/issues/5939
302 fn not_general_enough() {
303 fn f(_: impl FnMut(&Path) -> std::io::Result<()>) {}
304 f(|path| std::fs::remove_file(path));
305 }