]> git.lizzy.rs Git - rust.git/blob - tests/compile-fail/methods.rs
Add a `MISSING_DOCS_IN_PRIVATE_ITEMS` lint
[rust.git] / tests / compile-fail / methods.rs
1 #![feature(plugin)]
2 #![feature(const_fn)]
3 #![plugin(clippy)]
4
5 #![deny(clippy, clippy_pedantic)]
6 #![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default, new_without_default_derive, missing_docs_in_private_items)]
7
8 use std::collections::BTreeMap;
9 use std::collections::HashMap;
10 use std::collections::HashSet;
11 use std::collections::VecDeque;
12 use std::ops::Mul;
13
14 struct T;
15
16 impl T {
17     fn add(self, other: T) -> T { self } //~ERROR defining a method called `add`
18     fn drop(&mut self) { } //~ERROR defining a method called `drop`
19
20     fn sub(&self, other: T) -> &T { self } // no error, self is a ref
21     fn div(self) -> T { self } // no error, different #arguments
22     fn rem(self, other: T) { } // no error, wrong return type
23
24     fn into_u32(self) -> u32 { 0 } // fine
25     fn into_u16(&self) -> u16 { 0 } //~ERROR methods called `into_*` usually take self by value
26
27     fn to_something(self) -> u32 { 0 } //~ERROR methods called `to_*` usually take self by reference
28
29     fn new(self) {}
30     //~^ ERROR methods called `new` usually take no self
31     //~| ERROR methods called `new` usually return `Self`
32 }
33
34 struct Lt<'a> {
35     foo: &'a u32,
36 }
37
38 impl<'a> Lt<'a> {
39     // The lifetime is different, but that’s irrelevant, see #734
40     #[allow(needless_lifetimes)]
41     pub fn new<'b>(s: &'b str) -> Lt<'b> { unimplemented!() }
42 }
43
44 struct Lt2<'a> {
45     foo: &'a u32,
46 }
47
48 impl<'a> Lt2<'a> {
49     // The lifetime is different, but that’s irrelevant, see #734
50     pub fn new(s: &str) -> Lt2 { unimplemented!() }
51 }
52
53 struct Lt3<'a> {
54     foo: &'a u32,
55 }
56
57 impl<'a> Lt3<'a> {
58     // The lifetime is different, but that’s irrelevant, see #734
59     pub fn new() -> Lt3<'static> { unimplemented!() }
60 }
61
62 #[derive(Clone,Copy)]
63 struct U;
64
65 impl U {
66     fn new() -> Self { U }
67     fn to_something(self) -> u32 { 0 } // ok because U is Copy
68 }
69
70 struct V<T> {
71     _dummy: T
72 }
73
74 impl<T> V<T> {
75     fn new() -> Option<V<T>> { None }
76 }
77
78 impl Mul<T> for T {
79     type Output = T;
80     fn mul(self, other: T) -> T { self } // no error, obviously
81 }
82
83 /// Utility macro to test linting behavior in `option_methods()`
84 /// The lints included in `option_methods()` should not lint if the call to map is partially
85 /// within a macro
86 macro_rules! opt_map {
87     ($opt:expr, $map:expr) => {($opt).map($map)};
88 }
89
90 /// Checks implementation of the following lints:
91 /// * `OPTION_MAP_UNWRAP_OR`
92 /// * `OPTION_MAP_UNWRAP_OR_ELSE`
93 fn option_methods() {
94     let opt = Some(1);
95
96     // Check OPTION_MAP_UNWRAP_OR
97     // single line case
98     let _ = opt.map(|x| x + 1) //~  ERROR called `map(f).unwrap_or(a)`
99                                //~| NOTE replace `map(|x| x + 1).unwrap_or(0)`
100                .unwrap_or(0); // should lint even though this call is on a separate line
101     // multi line cases
102     let _ = opt.map(|x| { //~ ERROR called `map(f).unwrap_or(a)`
103                         x + 1
104                     }
105               ).unwrap_or(0);
106     let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or(a)`
107                .unwrap_or({
108                     0
109                 });
110     // macro case
111     let _ = opt_map!(opt, |x| x + 1).unwrap_or(0); // should not lint
112
113     // Check OPTION_MAP_UNWRAP_OR_ELSE
114     // single line case
115     let _ = opt.map(|x| x + 1) //~  ERROR called `map(f).unwrap_or_else(g)`
116                                //~| NOTE replace `map(|x| x + 1).unwrap_or_else(|| 0)`
117                .unwrap_or_else(|| 0); // should lint even though this call is on a separate line
118     // multi line cases
119     let _ = opt.map(|x| { //~ ERROR called `map(f).unwrap_or_else(g)`
120                         x + 1
121                     }
122               ).unwrap_or_else(|| 0);
123     let _ = opt.map(|x| x + 1) //~ ERROR called `map(f).unwrap_or_else(g)`
124                .unwrap_or_else(||
125                     0
126                 );
127     // macro case
128     let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0); // should not lint
129
130 }
131
132 /// Struct to generate false positives for things with .iter()
133 #[derive(Copy, Clone)]
134 struct HasIter;
135
136 impl HasIter {
137     fn iter(self) -> IteratorFalsePositives {
138         IteratorFalsePositives { foo: 0 }
139     }
140
141     fn iter_mut(self) -> IteratorFalsePositives {
142         IteratorFalsePositives { foo: 0 }
143     }
144 }
145
146 /// Struct to generate false positive for Iterator-based lints
147 #[derive(Copy, Clone)]
148 struct IteratorFalsePositives {
149     foo: u32,
150 }
151
152 impl IteratorFalsePositives {
153     fn filter(self) -> IteratorFalsePositives {
154         self
155     }
156
157     fn next(self) -> IteratorFalsePositives {
158         self
159     }
160
161     fn find(self) -> Option<u32> {
162         Some(self.foo)
163     }
164
165     fn position(self) -> Option<u32> {
166         Some(self.foo)
167     }
168
169     fn rposition(self) -> Option<u32> {
170         Some(self.foo)
171     }
172
173     fn nth(self, n: usize) -> Option<u32> {
174         Some(self.foo)
175     }
176 }
177
178 /// Checks implementation of `FILTER_NEXT` lint
179 fn filter_next() {
180     let v = vec![3, 2, 1, 0, -1, -2, -3];
181
182     // check single-line case
183     let _ = v.iter().filter(|&x| *x < 0).next();
184     //~^ ERROR called `filter(p).next()` on an `Iterator`.
185     //~| NOTE replace `filter(|&x| *x < 0).next()`
186
187     // check multi-line case
188     let _ = v.iter().filter(|&x| { //~ERROR called `filter(p).next()` on an `Iterator`.
189                                 *x < 0
190                             }
191                    ).next();
192
193     // check that we don't lint if the caller is not an Iterator
194     let foo = IteratorFalsePositives { foo: 0 };
195     let _ = foo.filter().next();
196 }
197
198 /// Checks implementation of `SEARCH_IS_SOME` lint
199 fn search_is_some() {
200     let v = vec![3, 2, 1, 0, -1, -2, -3];
201
202     // check `find().is_some()`, single-line
203     let _ = v.iter().find(|&x| *x < 0).is_some();
204     //~^ ERROR called `is_some()` after searching
205     //~| NOTE replace `find(|&x| *x < 0).is_some()`
206
207     // check `find().is_some()`, multi-line
208     let _ = v.iter().find(|&x| { //~ERROR called `is_some()` after searching
209                               *x < 0
210                           }
211                    ).is_some();
212
213     // check `position().is_some()`, single-line
214     let _ = v.iter().position(|&x| x < 0).is_some();
215     //~^ ERROR called `is_some()` after searching
216     //~| NOTE replace `position(|&x| x < 0).is_some()`
217
218     // check `position().is_some()`, multi-line
219     let _ = v.iter().position(|&x| { //~ERROR called `is_some()` after searching
220                                   x < 0
221                               }
222                    ).is_some();
223
224     // check `rposition().is_some()`, single-line
225     let _ = v.iter().rposition(|&x| x < 0).is_some();
226     //~^ ERROR called `is_some()` after searching
227     //~| NOTE replace `rposition(|&x| x < 0).is_some()`
228
229     // check `rposition().is_some()`, multi-line
230     let _ = v.iter().rposition(|&x| { //~ERROR called `is_some()` after searching
231                                    x < 0
232                                }
233                    ).is_some();
234
235     // check that we don't lint if the caller is not an Iterator
236     let foo = IteratorFalsePositives { foo: 0 };
237     let _ = foo.find().is_some();
238     let _ = foo.position().is_some();
239     let _ = foo.rposition().is_some();
240 }
241
242 /// Checks implementation of the `OR_FUN_CALL` lint
243 fn or_fun_call() {
244     struct Foo;
245
246     impl Foo {
247         fn new() -> Foo { Foo }
248     }
249
250     enum Enum {
251         A(i32),
252     }
253
254     const fn make_const(i: i32) -> i32 { i }
255
256     fn make<T>() -> T { unimplemented!(); }
257
258     let with_enum = Some(Enum::A(1));
259     with_enum.unwrap_or(Enum::A(5));
260
261     let with_const_fn = Some(1);
262     with_const_fn.unwrap_or(make_const(5));
263
264     let with_constructor = Some(vec![1]);
265     with_constructor.unwrap_or(make());
266     //~^ERROR use of `unwrap_or`
267     //~|HELP try this
268     //~|SUGGESTION with_constructor.unwrap_or_else(make)
269
270     let with_new = Some(vec![1]);
271     with_new.unwrap_or(Vec::new());
272     //~^ERROR use of `unwrap_or`
273     //~|HELP try this
274     //~|SUGGESTION with_new.unwrap_or_default();
275
276     let with_const_args = Some(vec![1]);
277     with_const_args.unwrap_or(Vec::with_capacity(12));
278     //~^ERROR use of `unwrap_or`
279     //~|HELP try this
280     //~|SUGGESTION with_const_args.unwrap_or_else(|| Vec::with_capacity(12));
281
282     let with_err : Result<_, ()> = Ok(vec![1]);
283     with_err.unwrap_or(make());
284     //~^ERROR use of `unwrap_or`
285     //~|HELP try this
286     //~|SUGGESTION with_err.unwrap_or_else(|_| make());
287
288     let with_err_args : Result<_, ()> = Ok(vec![1]);
289     with_err_args.unwrap_or(Vec::with_capacity(12));
290     //~^ERROR use of `unwrap_or`
291     //~|HELP try this
292     //~|SUGGESTION with_err_args.unwrap_or_else(|_| Vec::with_capacity(12));
293
294     let with_default_trait = Some(1);
295     with_default_trait.unwrap_or(Default::default());
296     //~^ERROR use of `unwrap_or`
297     //~|HELP try this
298     //~|SUGGESTION with_default_trait.unwrap_or_default();
299
300     let with_default_type = Some(1);
301     with_default_type.unwrap_or(u64::default());
302     //~^ERROR use of `unwrap_or`
303     //~|HELP try this
304     //~|SUGGESTION with_default_type.unwrap_or_default();
305
306     let with_vec = Some(vec![1]);
307     with_vec.unwrap_or(vec![]);
308     //~^ERROR use of `unwrap_or`
309     //~|HELP try this
310     // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]);
311
312     let without_default = Some(Foo);
313     without_default.unwrap_or(Foo::new());
314     //~^ERROR use of `unwrap_or`
315     //~|HELP try this
316     //~|SUGGESTION without_default.unwrap_or_else(Foo::new);
317
318     let mut map = HashMap::<u64, String>::new();
319     map.entry(42).or_insert(String::new());
320     //~^ERROR use of `or_insert` followed by a function call
321     //~|HELP try this
322     //~|SUGGESTION map.entry(42).or_insert_with(String::new);
323
324     let mut btree = BTreeMap::<u64, String>::new();
325     btree.entry(42).or_insert(String::new());
326     //~^ERROR use of `or_insert` followed by a function call
327     //~|HELP try this
328     //~|SUGGESTION btree.entry(42).or_insert_with(String::new);
329 }
330
331 /// Checks implementation of `ITER_NTH` lint
332 fn iter_nth() {
333     let mut some_vec = vec![0, 1, 2, 3];
334     let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect();
335
336     {
337         // Make sure we lint `.iter()` for relevant types
338         let bad_vec = some_vec.iter().nth(3);
339         //~^ERROR called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable
340         let bad_slice = &some_vec[..].iter().nth(3);
341         //~^ERROR called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable
342         let bad_vec_deque = some_vec_deque.iter().nth(3);
343         //~^ERROR called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable
344     }
345
346     {
347         // Make sure we lint `.iter_mut()` for relevant types
348         let bad_vec = some_vec.iter_mut().nth(3);
349         //~^ERROR called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable
350     }
351     {
352         let bad_slice = &some_vec[..].iter_mut().nth(3);
353         //~^ERROR called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable
354     }
355     {
356         let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
357         //~^ERROR called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable
358     }
359
360     // Make sure we don't lint for non-relevant types
361     let false_positive = HasIter;
362     let ok = false_positive.iter().nth(3);
363     let ok_mut = false_positive.iter_mut().nth(3);
364 }
365
366 #[allow(similar_names)]
367 fn main() {
368     use std::io;
369
370     let opt = Some(0);
371     let _ = opt.unwrap();  //~ERROR used unwrap() on an Option
372
373     let res: Result<i32, ()> = Ok(0);
374     let _ = res.unwrap();  //~ERROR used unwrap() on a Result
375
376     res.ok().expect("disaster!"); //~ERROR called `ok().expect()`
377     // the following should not warn, since `expect` isn't implemented unless
378     // the error type implements `Debug`
379     let res2: Result<i32, MyError> = Ok(0);
380     res2.ok().expect("oh noes!");
381     let res3: Result<u32, MyErrorWithParam<u8>>= Ok(0);
382     res3.ok().expect("whoof"); //~ERROR called `ok().expect()`
383     let res4: Result<u32, io::Error> = Ok(0);
384     res4.ok().expect("argh"); //~ERROR called `ok().expect()`
385     let res5: io::Result<u32> = Ok(0);
386     res5.ok().expect("oops"); //~ERROR called `ok().expect()`
387     let res6: Result<u32, &str> = Ok(0);
388     res6.ok().expect("meh"); //~ERROR called `ok().expect()`
389 }
390
391 struct MyError(()); // doesn't implement Debug
392
393 #[derive(Debug)]
394 struct MyErrorWithParam<T> {
395     x: T
396 }
397
398 #[allow(unnecessary_operation)]
399 fn starts_with() {
400     "".chars().next() == Some(' ');
401     //~^ ERROR starts_with
402     //~| HELP like this
403     //~| SUGGESTION "".starts_with(' ')
404
405     Some(' ') != "".chars().next();
406     //~^ ERROR starts_with
407     //~| HELP like this
408     //~| SUGGESTION !"".starts_with(' ')
409 }
410
411 fn use_extend_from_slice() {
412     let mut v : Vec<&'static str> = vec![];
413     v.extend(&["Hello", "World"]);
414     //~^ ERROR use of `extend`
415     //~| HELP try this
416     //~| SUGGESTION v.extend_from_slice(&["Hello", "World"]);
417     v.extend(&vec!["Some", "more"]);
418     //~^ ERROR use of `extend`
419     //~| HELP try this
420     //~| SUGGESTION v.extend_from_slice(&vec!["Some", "more"]);
421
422     v.extend(vec!["And", "even", "more"].iter());
423     //~^ ERROR use of `extend`
424     //~| HELP try this
425     //FIXME: the suggestion if broken because of the macro
426     let o : Option<&'static str> = None;
427     v.extend(o);
428     v.extend(Some("Bye"));
429     v.extend(vec!["Not", "like", "this"]);
430     v.extend(["But", "this"].iter());
431     //~^ERROR use of `extend
432     //~| HELP try this
433     //~| SUGGESTION v.extend_from_slice(&["But", "this"]);
434 }
435
436 fn clone_on_copy() {
437     42.clone(); //~ERROR using `clone` on a `Copy` type
438                 //~| HELP try removing the `clone` call
439                 //~| SUGGESTION 42
440     vec![1].clone(); // ok, not a Copy type
441     Some(vec![1]).clone(); // ok, not a Copy type
442     (&42).clone(); //~ERROR using `clone` on a `Copy` type
443                    //~| HELP try dereferencing it
444                    //~| SUGGESTION *(&42)
445 }
446
447 fn clone_on_copy_generic<T: Copy>(t: T) {
448     t.clone(); //~ERROR using `clone` on a `Copy` type
449                //~| HELP try removing the `clone` call
450                //~| SUGGESTION t
451     Some(t).clone(); //~ERROR using `clone` on a `Copy` type
452                      //~| HELP try removing the `clone` call
453                      //~| SUGGESTION Some(t)
454 }
455
456 fn clone_on_double_ref() {
457     let x = vec![1];
458     let y = &&x;
459     let z: &Vec<_> = y.clone(); //~ERROR using `clone` on a double
460                                 //~| HELP try dereferencing it
461                                 //~| SUGGESTION let z: &Vec<_> = (*y).clone();
462     println!("{:p} {:p}",*y, z);
463 }
464
465 fn single_char_pattern() {
466     let x = "foo";
467     x.split("x");
468     //~^ ERROR single-character string constant used as pattern
469     //~| HELP try using a char instead:
470     //~| SUGGESTION x.split('x');
471
472     x.split("xx");
473
474     x.split('x');
475
476     let y = "x";
477     x.split(y);
478
479     // Not yet testing for multi-byte characters
480     // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_single_char_pattern`
481     // should have done this but produced an ICE
482     //
483     // We may not want to suggest changing these anyway
484     // See: https://github.com/Manishearth/rust-clippy/issues/650#issuecomment-184328984
485     x.split("ß");
486     x.split("ℝ");
487     x.split("💣");
488     // Can't use this lint for unicode code points which don't fit in a char
489     x.split("❤️");
490
491     x.contains("x");
492     //~^ ERROR single-character string constant used as pattern
493     //~| HELP try using a char instead:
494     //~| SUGGESTION x.contains('x');
495     x.starts_with("x");
496     //~^ ERROR single-character string constant used as pattern
497     //~| HELP try using a char instead:
498     //~| SUGGESTION x.starts_with('x');
499     x.ends_with("x");
500     //~^ ERROR single-character string constant used as pattern
501     //~| HELP try using a char instead:
502     //~| SUGGESTION x.ends_with('x');
503     x.find("x");
504     //~^ ERROR single-character string constant used as pattern
505     //~| HELP try using a char instead:
506     //~| SUGGESTION x.find('x');
507     x.rfind("x");
508     //~^ ERROR single-character string constant used as pattern
509     //~| HELP try using a char instead:
510     //~| SUGGESTION x.rfind('x');
511     x.rsplit("x");
512     //~^ ERROR single-character string constant used as pattern
513     //~| HELP try using a char instead:
514     //~| SUGGESTION x.rsplit('x');
515     x.split_terminator("x");
516     //~^ ERROR single-character string constant used as pattern
517     //~| HELP try using a char instead:
518     //~| SUGGESTION x.split_terminator('x');
519     x.rsplit_terminator("x");
520     //~^ ERROR single-character string constant used as pattern
521     //~| HELP try using a char instead:
522     //~| SUGGESTION x.rsplit_terminator('x');
523     x.splitn(0, "x");
524     //~^ ERROR single-character string constant used as pattern
525     //~| HELP try using a char instead:
526     //~| SUGGESTION x.splitn(0, 'x');
527     x.rsplitn(0, "x");
528     //~^ ERROR single-character string constant used as pattern
529     //~| HELP try using a char instead:
530     //~| SUGGESTION x.rsplitn(0, 'x');
531     x.matches("x");
532     //~^ ERROR single-character string constant used as pattern
533     //~| HELP try using a char instead:
534     //~| SUGGESTION x.matches('x');
535     x.rmatches("x");
536     //~^ ERROR single-character string constant used as pattern
537     //~| HELP try using a char instead:
538     //~| SUGGESTION x.rmatches('x');
539     x.match_indices("x");
540     //~^ ERROR single-character string constant used as pattern
541     //~| HELP try using a char instead:
542     //~| SUGGESTION x.match_indices('x');
543     x.rmatch_indices("x");
544     //~^ ERROR single-character string constant used as pattern
545     //~| HELP try using a char instead:
546     //~| SUGGESTION x.rmatch_indices('x');
547     x.trim_left_matches("x");
548     //~^ ERROR single-character string constant used as pattern
549     //~| HELP try using a char instead:
550     //~| SUGGESTION x.trim_left_matches('x');
551     x.trim_right_matches("x");
552     //~^ ERROR single-character string constant used as pattern
553     //~| HELP try using a char instead:
554     //~| SUGGESTION x.trim_right_matches('x');
555
556     let h = HashSet::<String>::new();
557     h.contains("X"); // should not warn
558 }
559
560 #[allow(result_unwrap_used)]
561 fn temporary_cstring() {
562     use std::ffi::CString;
563
564     CString::new("foo").unwrap().as_ptr();
565     //~^ ERROR you are getting the inner pointer of a temporary `CString`
566     //~| NOTE that pointer will be invalid outside this expression
567     //~| HELP assign the `CString` to a variable to extend its lifetime
568 }