]> git.lizzy.rs Git - rust.git/blob - tests/ui/methods.rs
Add expect
[rust.git] / tests / ui / methods.rs
1 // aux-build:option_helpers.rs
2 // compile-flags: --edition 2018
3
4 #![warn(
5     clippy::all,
6     clippy::pedantic,
7     clippy::option_unwrap_used,
8     clippy::option_expect_used,
9     clippy::result_expect_used
10 )]
11 #![allow(
12     clippy::blacklisted_name,
13     clippy::default_trait_access,
14     clippy::missing_docs_in_private_items,
15     clippy::non_ascii_literal,
16     clippy::new_without_default,
17     clippy::needless_pass_by_value,
18     clippy::print_stdout,
19     clippy::must_use_candidate,
20     clippy::use_self,
21     clippy::useless_format,
22     clippy::wrong_self_convention,
23     clippy::unused_self,
24     unused
25 )]
26
27 #[macro_use]
28 extern crate option_helpers;
29
30 use std::collections::BTreeMap;
31 use std::collections::HashMap;
32 use std::collections::HashSet;
33 use std::collections::VecDeque;
34 use std::iter::FromIterator;
35 use std::ops::Mul;
36 use std::rc::{self, Rc};
37 use std::sync::{self, Arc};
38
39 use option_helpers::IteratorFalsePositives;
40
41 pub struct T;
42
43 impl T {
44     pub fn add(self, other: T) -> T {
45         self
46     }
47
48     // no error, not public interface
49     pub(crate) fn drop(&mut self) {}
50
51     // no error, private function
52     fn neg(self) -> Self {
53         self
54     }
55
56     // no error, private function
57     fn eq(&self, other: T) -> bool {
58         true
59     }
60
61     // No error; self is a ref.
62     fn sub(&self, other: T) -> &T {
63         self
64     }
65
66     // No error; different number of arguments.
67     fn div(self) -> T {
68         self
69     }
70
71     // No error; wrong return type.
72     fn rem(self, other: T) {}
73
74     // Fine
75     fn into_u32(self) -> u32 {
76         0
77     }
78
79     fn into_u16(&self) -> u16 {
80         0
81     }
82
83     fn to_something(self) -> u32 {
84         0
85     }
86
87     fn new(self) -> Self {
88         unimplemented!();
89     }
90 }
91
92 struct Lt<'a> {
93     foo: &'a u32,
94 }
95
96 impl<'a> Lt<'a> {
97     // The lifetime is different, but that’s irrelevant; see issue #734.
98     #[allow(clippy::needless_lifetimes)]
99     pub fn new<'b>(s: &'b str) -> Lt<'b> {
100         unimplemented!()
101     }
102 }
103
104 struct Lt2<'a> {
105     foo: &'a u32,
106 }
107
108 impl<'a> Lt2<'a> {
109     // The lifetime is different, but that’s irrelevant; see issue #734.
110     pub fn new(s: &str) -> Lt2 {
111         unimplemented!()
112     }
113 }
114
115 struct Lt3<'a> {
116     foo: &'a u32,
117 }
118
119 impl<'a> Lt3<'a> {
120     // The lifetime is different, but that’s irrelevant; see issue #734.
121     pub fn new() -> Lt3<'static> {
122         unimplemented!()
123     }
124 }
125
126 #[derive(Clone, Copy)]
127 struct U;
128
129 impl U {
130     fn new() -> Self {
131         U
132     }
133     // Ok because `U` is `Copy`.
134     fn to_something(self) -> u32 {
135         0
136     }
137 }
138
139 struct V<T> {
140     _dummy: T,
141 }
142
143 impl<T> V<T> {
144     fn new() -> Option<V<T>> {
145         None
146     }
147 }
148
149 struct AsyncNew;
150
151 impl AsyncNew {
152     async fn new() -> Option<Self> {
153         None
154     }
155 }
156
157 struct BadNew;
158
159 impl BadNew {
160     fn new() -> i32 {
161         0
162     }
163 }
164
165 impl Mul<T> for T {
166     type Output = T;
167     // No error, obviously.
168     fn mul(self, other: T) -> T {
169         self
170     }
171 }
172
173 /// Checks implementation of the following lints:
174 /// * `OPTION_MAP_UNWRAP_OR`
175 /// * `OPTION_MAP_UNWRAP_OR_ELSE`
176 #[rustfmt::skip]
177 fn option_methods() {
178     let opt = Some(1);
179
180     // Check `OPTION_MAP_UNWRAP_OR`.
181     // Single line case.
182     let _ = opt.map(|x| x + 1)
183                 // Should lint even though this call is on a separate line.
184                .unwrap_or(0);
185     // Multi-line cases.
186     let _ = opt.map(|x| {
187                         x + 1
188                     }
189               ).unwrap_or(0);
190     let _ = opt.map(|x| x + 1)
191                .unwrap_or({
192                     0
193                 });
194     // Single line `map(f).unwrap_or(None)` case.
195     let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
196     // Multi-line `map(f).unwrap_or(None)` cases.
197     let _ = opt.map(|x| {
198         Some(x + 1)
199     }
200     ).unwrap_or(None);
201     let _ = opt
202         .map(|x| Some(x + 1))
203         .unwrap_or(None);
204     // macro case
205     let _ = opt_map!(opt, |x| x + 1).unwrap_or(0); // should not lint
206
207     // Should not lint if not copyable
208     let id: String = "identifier".to_string();
209     let _ = Some("prefix").map(|p| format!("{}.{}", p, id)).unwrap_or(id);
210     // ...but DO lint if the `unwrap_or` argument is not used in the `map`
211     let id: String = "identifier".to_string();
212     let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
213
214     // Check OPTION_MAP_UNWRAP_OR_ELSE
215     // single line case
216     let _ = opt.map(|x| x + 1)
217                 // Should lint even though this call is on a separate line.
218                .unwrap_or_else(|| 0);
219     // Multi-line cases.
220     let _ = opt.map(|x| {
221                         x + 1
222                     }
223               ).unwrap_or_else(|| 0);
224     let _ = opt.map(|x| x + 1)
225                .unwrap_or_else(||
226                     0
227                 );
228     // Macro case.
229     // Should not lint.
230     let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
231
232     // Issue #4144
233     {
234         let mut frequencies = HashMap::new();
235         let word = "foo";
236
237         frequencies
238             .get_mut(word)
239             .map(|count| {
240                 *count += 1;
241             })
242             .unwrap_or_else(|| {
243                 frequencies.insert(word.to_owned(), 1);
244             });
245     }
246 }
247
248 /// Checks implementation of `FILTER_NEXT` lint.
249 #[rustfmt::skip]
250 fn filter_next() {
251     let v = vec![3, 2, 1, 0, -1, -2, -3];
252
253     // Single-line case.
254     let _ = v.iter().filter(|&x| *x < 0).next();
255
256     // Multi-line case.
257     let _ = v.iter().filter(|&x| {
258                                 *x < 0
259                             }
260                    ).next();
261
262     // Check that hat we don't lint if the caller is not an `Iterator`.
263     let foo = IteratorFalsePositives { foo: 0 };
264     let _ = foo.filter().next();
265 }
266
267 /// Checks implementation of `SEARCH_IS_SOME` lint.
268 #[rustfmt::skip]
269 fn search_is_some() {
270     let v = vec![3, 2, 1, 0, -1, -2, -3];
271     let y = &&42;
272
273     // Check `find().is_some()`, single-line case.
274     let _ = v.iter().find(|&x| *x < 0).is_some();
275     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
276     let _ = (0..1).find(|x| *x == 0).is_some();
277     let _ = v.iter().find(|x| **x == 0).is_some();
278
279     // Check `find().is_some()`, multi-line case.
280     let _ = v.iter().find(|&x| {
281                               *x < 0
282                           }
283                    ).is_some();
284
285     // Check `position().is_some()`, single-line case.
286     let _ = v.iter().position(|&x| x < 0).is_some();
287
288     // Check `position().is_some()`, multi-line case.
289     let _ = v.iter().position(|&x| {
290                                   x < 0
291                               }
292                    ).is_some();
293
294     // Check `rposition().is_some()`, single-line case.
295     let _ = v.iter().rposition(|&x| x < 0).is_some();
296
297     // Check `rposition().is_some()`, multi-line case.
298     let _ = v.iter().rposition(|&x| {
299                                    x < 0
300                                }
301                    ).is_some();
302
303     // Check that we don't lint if the caller is not an `Iterator`.
304     let foo = IteratorFalsePositives { foo: 0 };
305     let _ = foo.find().is_some();
306     let _ = foo.position().is_some();
307     let _ = foo.rposition().is_some();
308 }
309
310 #[allow(clippy::similar_names)]
311 fn main() {
312     let opt = Some(0);
313     let _ = opt.unwrap();
314 }