]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/eta.fixed
Auto merge of #99099 - Stargateur:phantomdata_debug, r=joshtriplett
[rust.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 }