]> git.lizzy.rs Git - rust.git/blob - tests/ui/methods.rs
Auto merge of #4560 - rust-lang:must-use-pure, r=phansch
[rust.git] / tests / ui / methods.rs
1 // aux-build:option_helpers.rs
2 // compile-flags: --edition 2018
3
4 #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)]
5 #![allow(
6     clippy::blacklisted_name,
7     clippy::default_trait_access,
8     clippy::missing_docs_in_private_items,
9     clippy::non_ascii_literal,
10     clippy::new_without_default,
11     clippy::needless_pass_by_value,
12     clippy::print_stdout,
13     clippy::must_use_candidate,
14     clippy::use_self,
15     clippy::useless_format,
16     clippy::wrong_self_convention,
17     unused
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     let y = &&42;
265
266     // Check `find().is_some()`, single-line case.
267     let _ = v.iter().find(|&x| *x < 0).is_some();
268     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
269     let _ = (0..1).find(|x| *x == 0).is_some();
270     let _ = v.iter().find(|x| **x == 0).is_some();
271
272     // Check `find().is_some()`, multi-line case.
273     let _ = v.iter().find(|&x| {
274                               *x < 0
275                           }
276                    ).is_some();
277
278     // Check `position().is_some()`, single-line case.
279     let _ = v.iter().position(|&x| x < 0).is_some();
280
281     // Check `position().is_some()`, multi-line case.
282     let _ = v.iter().position(|&x| {
283                                   x < 0
284                               }
285                    ).is_some();
286
287     // Check `rposition().is_some()`, single-line case.
288     let _ = v.iter().rposition(|&x| x < 0).is_some();
289
290     // Check `rposition().is_some()`, multi-line case.
291     let _ = v.iter().rposition(|&x| {
292                                    x < 0
293                                }
294                    ).is_some();
295
296     // Check that we don't lint if the caller is not an `Iterator`.
297     let foo = IteratorFalsePositives { foo: 0 };
298     let _ = foo.find().is_some();
299     let _ = foo.position().is_some();
300     let _ = foo.rposition().is_some();
301 }
302
303 #[allow(clippy::similar_names)]
304 fn main() {
305     let opt = Some(0);
306     let _ = opt.unwrap();
307 }