]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/eta.rs
Rollup merge of #84221 - ABouttefeux:generic-arg-elision, r=estebank
[rust.git] / src / tools / clippy / tests / ui / eta.rs
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) });
51 }
52
53 trait TestTrait {
54     fn trait_foo(self) -> bool;
55     fn trait_foo_ref(&self) -> bool;
56 }
57
58 struct TestStruct<'a> {
59     some_ref: &'a i32,
60 }
61
62 impl<'a> TestStruct<'a> {
63     fn foo(self) -> bool {
64         false
65     }
66     unsafe fn foo_unsafe(self) -> bool {
67         true
68     }
69 }
70
71 impl<'a> TestTrait for TestStruct<'a> {
72     fn trait_foo(self) -> bool {
73         false
74     }
75     fn trait_foo_ref(&self) -> bool {
76         false
77     }
78 }
79
80 impl<'a> std::ops::Deref for TestStruct<'a> {
81     type Target = char;
82     fn deref(&self) -> &char {
83         &'a'
84     }
85 }
86
87 fn test_redundant_closures_containing_method_calls() {
88     let i = 10;
89     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
90     let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo);
91     let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
92     let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref());
93     let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo);
94     let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
95     let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear);
96     unsafe {
97         let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe());
98     }
99     let e = Some("str").map(|s| s.to_string());
100     let e = Some("str").map(str::to_string);
101     let e = Some('a').map(|s| s.to_uppercase());
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(|c| c.to_ascii_uppercase()).collect();
105     let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect();
106     let p = Some(PathBuf::new());
107     let e = p.as_ref().and_then(|s| s.to_str());
108     let c = Some(TestStruct { some_ref: &i })
109         .as_ref()
110         .map(|c| c.to_ascii_uppercase());
111
112     fn test_different_borrow_levels<T>(t: &[&T])
113     where
114         T: TestTrait,
115     {
116         t.iter().filter(|x| x.trait_foo_ref());
117         t.iter().map(|x| x.trait_foo_ref());
118     }
119
120     let mut some = Some(|x| x * x);
121     let arr = [Ok(1), Err(2)];
122     let _: Vec<_> = arr.iter().map(|x| x.map_err(|e| some.take().unwrap()(e))).collect();
123 }
124
125 struct Thunk<T>(Box<dyn FnMut() -> T>);
126
127 impl<T> Thunk<T> {
128     fn new<F: 'static + FnOnce() -> T>(f: F) -> Thunk<T> {
129         let mut option = Some(f);
130         // This should not trigger redundant_closure (#1439)
131         Thunk(Box::new(move || option.take().unwrap()()))
132     }
133
134     fn unwrap(self) -> T {
135         let Thunk(mut f) = self;
136         f()
137     }
138 }
139
140 fn foobar() {
141     let thunk = Thunk::new(|| println!("Hello, world!"));
142     thunk.unwrap()
143 }
144
145 fn meta<F>(f: F)
146 where
147     F: Fn(u8),
148 {
149     f(1u8)
150 }
151
152 fn foo(_: u8) {}
153
154 fn foo2(_: u8) -> u8 {
155     1u8
156 }
157
158 fn all<X, F>(x: &[X], y: &X, f: F) -> bool
159 where
160     F: Fn(&X, &X) -> bool,
161 {
162     x.iter().all(|e| f(e, y))
163 }
164
165 fn below(x: &u8, y: &u8) -> bool {
166     x < y
167 }
168
169 unsafe fn unsafe_fn(_: u8) {}
170
171 fn divergent(_: u8) -> ! {
172     unimplemented!()
173 }
174
175 fn generic<T>(_: T) -> u8 {
176     0
177 }
178
179 fn passes_fn_mut(mut x: Box<dyn FnMut()>) {
180     requires_fn_once(|| x());
181 }
182 fn requires_fn_once<T: FnOnce()>(_: T) {}
183
184 fn test_redundant_closure_with_function_pointer() {
185     type FnPtrType = fn(u8);
186     let foo_ptr: FnPtrType = foo;
187     let a = Some(1u8).map(|a| foo_ptr(a));
188 }
189
190 fn test_redundant_closure_with_another_closure() {
191     let closure = |a| println!("{}", a);
192     let a = Some(1u8).map(|a| closure(a));
193 }
194
195 fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 {
196     // Currently f is called when result of make_lazy is called.
197     // If the closure is removed, f will be called when make_lazy itself is
198     // called. This changes semantics, so the closure must stay.
199     Box::new(move |x| f()(x))
200 }
201
202 fn call<F: FnOnce(&mut String) -> String>(f: F) -> String {
203     f(&mut "Hello".to_owned())
204 }
205 fn test_difference_in_mutability() {
206     call(|s| s.clone());
207 }
208
209 struct Bar;
210 impl std::ops::Deref for Bar {
211     type Target = str;
212     fn deref(&self) -> &str {
213         "hi"
214     }
215 }
216
217 fn test_deref_with_trait_method() {
218     let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
219 }