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