]> git.proxmox.com Git - rustc.git/blame_incremental - src/tools/clippy/tests/ui/eta.fixed
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / clippy / tests / ui / eta.fixed
... / ...
CommitLineData
1#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
2#![allow(unused)]
3#![allow(
4 clippy::needless_borrow,
5 clippy::needless_pass_by_value,
6 clippy::no_effect,
7 clippy::option_map_unit_fn,
8 clippy::redundant_closure_call,
9 clippy::uninlined_format_args,
10 clippy::useless_vec,
11 clippy::unnecessary_map_on_constructor
12)]
13
14use std::path::{Path, PathBuf};
15
16macro_rules! mac {
17 () => {
18 foobar()
19 };
20}
21
22macro_rules! closure_mac {
23 () => {
24 |n| foo(n)
25 };
26}
27
28fn main() {
29 let a = Some(1u8).map(foo);
30 let c = Some(1u8).map(|a| {1+2; foo}(a));
31 true.then(|| mac!()); // don't lint function in macro expansion
32 Some(1).map(closure_mac!()); // don't lint closure in macro expansion
33 let _: Option<Vec<u8>> = true.then(std::vec::Vec::new); // special case vec!
34 let d = Some(1u8).map(|a| foo(foo2(a))); //is adjusted?
35 all(&[1, 2, 3], &&2, below); //is adjusted
36 unsafe {
37 Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn
38 }
39
40 // See #815
41 let e = Some(1u8).map(|a| divergent(a));
42 let e = Some(1u8).map(generic);
43 let e = Some(1u8).map(generic);
44 // See #515
45 let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> =
46 Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) });
47
48 // issue #7224
49 let _: Option<Vec<u32>> = Some(0).map(|_| vec![]);
50
51 // issue #10684
52 fn test<T>(x: impl Fn(usize, usize) -> T) -> T {
53 x(1, 2)
54 }
55 test(|start, end| start..=end);
56}
57
58trait TestTrait {
59 fn trait_foo(self) -> bool;
60 fn trait_foo_ref(&self) -> bool;
61}
62
63struct TestStruct<'a> {
64 some_ref: &'a i32,
65}
66
67impl<'a> TestStruct<'a> {
68 fn foo(self) -> bool {
69 false
70 }
71 unsafe fn foo_unsafe(self) -> bool {
72 true
73 }
74}
75
76impl<'a> TestTrait for TestStruct<'a> {
77 fn trait_foo(self) -> bool {
78 false
79 }
80 fn trait_foo_ref(&self) -> bool {
81 false
82 }
83}
84
85impl<'a> std::ops::Deref for TestStruct<'a> {
86 type Target = char;
87 fn deref(&self) -> &char {
88 &'a'
89 }
90}
91
92fn test_redundant_closures_containing_method_calls() {
93 let i = 10;
94 let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo);
95 let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo);
96 let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref());
97 let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear);
98 unsafe {
99 let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe());
100 }
101 let e = Some("str").map(std::string::ToString::to_string);
102 let e = Some('a').map(char::to_uppercase);
103 let e: std::vec::Vec<usize> = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect();
104 let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect();
105 let e = Some(PathBuf::new()).as_ref().and_then(|s| s.to_str());
106 let c = Some(TestStruct { some_ref: &i })
107 .as_ref()
108 .map(|c| c.to_ascii_uppercase());
109
110 fn test_different_borrow_levels<T>(t: &[&T])
111 where
112 T: TestTrait,
113 {
114 t.iter().filter(|x| x.trait_foo_ref());
115 t.iter().map(|x| x.trait_foo_ref());
116 }
117}
118
119struct Thunk<T>(Box<dyn FnMut() -> T>);
120
121impl<T> Thunk<T> {
122 fn new<F: 'static + FnOnce() -> T>(f: F) -> Thunk<T> {
123 let mut option = Some(f);
124 // This should not trigger redundant_closure (#1439)
125 Thunk(Box::new(move || option.take().unwrap()()))
126 }
127
128 fn unwrap(self) -> T {
129 let Thunk(mut f) = self;
130 f()
131 }
132}
133
134fn foobar() {
135 let thunk = Thunk::new(|| println!("Hello, world!"));
136 thunk.unwrap()
137}
138
139fn foo(_: u8) {}
140
141fn foo2(_: u8) -> u8 {
142 1u8
143}
144
145fn all<X, F>(x: &[X], y: &X, f: F) -> bool
146where
147 F: Fn(&X, &X) -> bool,
148{
149 x.iter().all(|e| f(e, y))
150}
151
152fn below(x: &u8, y: &u8) -> bool {
153 x < y
154}
155
156unsafe fn unsafe_fn(_: u8) {}
157
158fn divergent(_: u8) -> ! {
159 unimplemented!()
160}
161
162fn generic<T>(_: T) -> u8 {
163 0
164}
165
166fn passes_fn_mut(mut x: Box<dyn FnMut()>) {
167 requires_fn_once(x);
168}
169fn requires_fn_once<T: FnOnce()>(_: T) {}
170
171fn test_redundant_closure_with_function_pointer() {
172 type FnPtrType = fn(u8);
173 let foo_ptr: FnPtrType = foo;
174 let a = Some(1u8).map(foo_ptr);
175}
176
177fn test_redundant_closure_with_another_closure() {
178 let closure = |a| println!("{}", a);
179 let a = Some(1u8).map(closure);
180}
181
182fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 {
183 // Currently f is called when result of make_lazy is called.
184 // If the closure is removed, f will be called when make_lazy itself is
185 // called. This changes semantics, so the closure must stay.
186 Box::new(move |x| f()(x))
187}
188
189fn call<F: FnOnce(&mut String) -> String>(f: F) -> String {
190 f(&mut "Hello".to_owned())
191}
192fn test_difference_in_mutability() {
193 call(|s| s.clone());
194}
195
196struct Bar;
197impl std::ops::Deref for Bar {
198 type Target = str;
199 fn deref(&self) -> &str {
200 "hi"
201 }
202}
203
204fn test_deref_with_trait_method() {
205 let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
206}
207
208fn mutable_closure_used_again(x: Vec<i32>, y: Vec<i32>, z: Vec<i32>) {
209 let mut res = Vec::new();
210 let mut add_to_res = |n| res.push(n);
211 x.into_iter().for_each(&mut add_to_res);
212 y.into_iter().for_each(&mut add_to_res);
213 z.into_iter().for_each(add_to_res);
214}
215
216fn mutable_closure_in_loop() {
217 let mut value = 0;
218 let mut closure = |n| value += n;
219 for _ in 0..5 {
220 Some(1).map(&mut closure);
221
222 let mut value = 0;
223 let mut in_loop = |n| value += n;
224 Some(1).map(in_loop);
225 }
226}
227
228fn late_bound_lifetimes() {
229 fn take_asref_path<P: AsRef<Path>>(path: P) {}
230
231 fn map_str<F>(thunk: F)
232 where
233 F: FnOnce(&str),
234 {
235 }
236
237 fn map_str_to_path<F>(thunk: F)
238 where
239 F: FnOnce(&str) -> &Path,
240 {
241 }
242 map_str(|s| take_asref_path(s));
243 map_str_to_path(|s| s.as_ref());
244}
245
246mod type_param_bound {
247 trait Trait {
248 fn fun();
249 }
250
251 fn take<T: 'static>(_: T) {}
252
253 fn test<X: Trait>() {
254 // don't lint, but it's questionable that rust requires a cast
255 take(|| X::fun());
256 take(X::fun as fn());
257 }
258}
259
260// #8073 Don't replace closure with `Arc<F>` or `Rc<F>`
261fn arc_fp() {
262 let rc = std::rc::Rc::new(|| 7);
263 let arc = std::sync::Arc::new(|n| n + 1);
264 let ref_arc = &std::sync::Arc::new(|_| 5);
265
266 true.then(|| rc());
267 (0..5).map(|n| arc(n));
268 Some(4).map(|n| ref_arc(n));
269}
270
271// #8460 Don't replace closures with params bounded as `ref`
272mod bind_by_ref {
273 struct A;
274 struct B;
275
276 impl From<&A> for B {
277 fn from(A: &A) -> Self {
278 B
279 }
280 }
281
282 fn test() {
283 // should not lint
284 Some(A).map(|a| B::from(&a));
285 // should not lint
286 Some(A).map(|ref a| B::from(a));
287 }
288}
289
290// #7812 False positive on coerced closure
291fn coerced_closure() {
292 fn function_returning_unit<F: FnMut(i32)>(f: F) {}
293 function_returning_unit(|x| std::process::exit(x));
294
295 fn arr() -> &'static [u8; 0] {
296 &[]
297 }
298 fn slice_fn(_: impl FnOnce() -> &'static [u8]) {}
299 slice_fn(|| arr());
300}
301
302// https://github.com/rust-lang/rust-clippy/issues/7861
303fn box_dyn() {
304 fn f(_: impl Fn(usize) -> Box<dyn std::any::Any>) {}
305 f(|x| Box::new(x));
306}
307
308// https://github.com/rust-lang/rust-clippy/issues/5939
309fn not_general_enough() {
310 fn f(_: impl FnMut(&Path) -> std::io::Result<()>) {}
311 f(|path| std::fs::remove_file(path));
312}
313
314// https://github.com/rust-lang/rust-clippy/issues/9369
315pub fn mutable_impl_fn_mut(mut f: impl FnMut(), mut f_used_once: impl FnMut()) -> impl FnMut() {
316 fn takes_fn_mut(_: impl FnMut()) {}
317 takes_fn_mut(&mut f);
318
319 fn takes_fn_once(_: impl FnOnce()) {}
320 takes_fn_once(&mut f);
321
322 f();
323
324 move || takes_fn_mut(&mut f_used_once)
325}
326
327impl dyn TestTrait + '_ {
328 fn method_on_dyn(&self) -> bool {
329 false
330 }
331}
332
333// https://github.com/rust-lang/rust-clippy/issues/7746
334fn angle_brackets_and_args() {
335 let array_opt: Option<&[u8; 3]> = Some(&[4, 8, 7]);
336 array_opt.map(<[u8; 3]>::as_slice);
337
338 let slice_opt: Option<&[u8]> = Some(b"slice");
339 slice_opt.map(<[u8]>::len);
340
341 let ptr_opt: Option<*const usize> = Some(&487);
342 ptr_opt.map(<*const usize>::is_null);
343
344 let test_struct = TestStruct { some_ref: &487 };
345 let dyn_opt: Option<&dyn TestTrait> = Some(&test_struct);
346 dyn_opt.map(<dyn TestTrait>::method_on_dyn);
347}
348
349// https://github.com/rust-lang/rust-clippy/issues/12199
350fn track_caller_fp() {
351 struct S;
352 impl S {
353 #[track_caller]
354 fn add_location(self) {}
355 }
356
357 #[track_caller]
358 fn add_location() {}
359
360 fn foo(_: fn()) {}
361 fn foo2(_: fn(S)) {}
362 foo(|| add_location());
363 foo2(|s| s.add_location());
364}
365
366fn _late_bound_to_early_bound_regions() {
367 struct Foo<'a>(&'a u32);
368 impl<'a> Foo<'a> {
369 fn f(x: &'a u32) -> Self {
370 Foo(x)
371 }
372 }
373 fn f(f: impl for<'a> Fn(&'a u32) -> Foo<'a>) -> Foo<'static> {
374 f(&0)
375 }
376
377 let _ = f(|x| Foo::f(x));
378
379 struct Bar;
380 impl<'a> From<&'a u32> for Bar {
381 fn from(x: &'a u32) -> Bar {
382 Bar
383 }
384 }
385 fn f2(f: impl for<'a> Fn(&'a u32) -> Bar) -> Bar {
386 f(&0)
387 }
388
389 let _ = f2(|x| <Bar>::from(x));
390
391 struct Baz<'a>(&'a u32);
392 fn f3(f: impl Fn(&u32) -> Baz<'_>) -> Baz<'static> {
393 f(&0)
394 }
395
396 let _ = f3(|x| Baz(x));
397}
398
399fn _mixed_late_bound_and_early_bound_regions() {
400 fn f<T>(t: T, f: impl Fn(T, &u32) -> u32) -> u32 {
401 f(t, &0)
402 }
403 fn f2<'a, T: 'a>(_: &'a T, y: &u32) -> u32 {
404 *y
405 }
406 let _ = f(&0, f2);
407}
408
409fn _closure_with_types() {
410 fn f<T>(x: T) -> T {
411 x
412 }
413 fn f2<T: Default>(f: impl Fn(T) -> T) -> T {
414 f(T::default())
415 }
416
417 let _ = f2(|x: u32| f(x));
418 let _ = f2(|x| -> u32 { f(x) });
419}
420
421/// https://github.com/rust-lang/rust-clippy/issues/10854
422/// This is to verify that redundant_closure_for_method_calls resolves suggested paths to relative.
423mod issue_10854 {
424 pub mod test_mod {
425 pub struct Test;
426
427 impl Test {
428 pub fn method(self) -> i32 {
429 0
430 }
431 }
432
433 pub fn calls_test(test: Option<Test>) -> Option<i32> {
434 test.map(Test::method)
435 }
436
437 pub fn calls_outer(test: Option<super::Outer>) -> Option<i32> {
438 test.map(super::Outer::method)
439 }
440 }
441
442 pub struct Outer;
443
444 impl Outer {
445 pub fn method(self) -> i32 {
446 0
447 }
448 }
449
450 pub fn calls_into_mod(test: Option<test_mod::Test>) -> Option<i32> {
451 test.map(test_mod::Test::method)
452 }
453
454 mod a {
455 pub mod b {
456 pub mod c {
457 pub fn extreme_nesting(test: Option<super::super::super::d::Test>) -> Option<i32> {
458 test.map(crate::issue_10854::d::Test::method)
459 }
460 }
461 }
462 }
463
464 mod d {
465 pub struct Test;
466
467 impl Test {
468 pub fn method(self) -> i32 {
469 0
470 }
471 }
472 }
473}