]>
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(foo); | |
33 | meta(foo); | |
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(std::vec::Vec::new); // 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(generic); | |
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(TestStruct::foo); | |
90 | let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); | |
91 | let e = Some(TestStruct { some_ref: &i }).map(TestTrait::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(std::vec::Vec::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(std::string::ToString::to_string); | |
100 | let e = Some("str").map(str::to_string); | |
101 | let e = Some('a').map(char::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(char::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(foo_ptr); | |
188 | } | |
189 | ||
190 | fn test_redundant_closure_with_another_closure() { | |
191 | let closure = |a| println!("{}", a); | |
192 | let a = Some(1u8).map(closure); | |
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 | } |