]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/methods/mod.rs
Merge commit 'dc5423ad448877e33cca28db2f1445c9c4473c75' into clippyup
[rust.git] / clippy_lints / src / methods / mod.rs
1 mod bind_instead_of_map;
2 mod bytes_nth;
3 mod chars_cmp;
4 mod chars_cmp_with_unwrap;
5 mod chars_last_cmp;
6 mod chars_last_cmp_with_unwrap;
7 mod chars_next_cmp;
8 mod chars_next_cmp_with_unwrap;
9 mod clone_on_copy;
10 mod clone_on_ref_ptr;
11 mod cloned_instead_of_copied;
12 mod expect_fun_call;
13 mod expect_used;
14 mod extend_with_drain;
15 mod filetype_is_file;
16 mod filter_map;
17 mod filter_map_identity;
18 mod filter_map_next;
19 mod filter_next;
20 mod flat_map_identity;
21 mod flat_map_option;
22 mod from_iter_instead_of_collect;
23 mod get_unwrap;
24 mod implicit_clone;
25 mod inefficient_to_string;
26 mod inspect_for_each;
27 mod into_iter_on_ref;
28 mod iter_cloned_collect;
29 mod iter_count;
30 mod iter_next_slice;
31 mod iter_nth;
32 mod iter_nth_zero;
33 mod iter_overeager_cloned;
34 mod iter_skip_next;
35 mod iter_with_drain;
36 mod iterator_step_by_zero;
37 mod manual_saturating_arithmetic;
38 mod manual_str_repeat;
39 mod map_collect_result_unit;
40 mod map_flatten;
41 mod map_identity;
42 mod map_unwrap_or;
43 mod ok_expect;
44 mod option_as_ref_deref;
45 mod option_map_or_none;
46 mod option_map_unwrap_or;
47 mod or_fun_call;
48 mod search_is_some;
49 mod single_char_add_str;
50 mod single_char_insert_string;
51 mod single_char_pattern;
52 mod single_char_push_string;
53 mod skip_while_next;
54 mod str_splitn;
55 mod string_extend_chars;
56 mod suspicious_map;
57 mod suspicious_splitn;
58 mod uninit_assumed_init;
59 mod unnecessary_filter_map;
60 mod unnecessary_fold;
61 mod unnecessary_iter_cloned;
62 mod unnecessary_lazy_eval;
63 mod unnecessary_to_owned;
64 mod unwrap_or_else_default;
65 mod unwrap_used;
66 mod useless_asref;
67 mod utils;
68 mod wrong_self_convention;
69 mod zst_offset;
70
71 use bind_instead_of_map::BindInsteadOfMap;
72 use clippy_utils::consts::{constant, Constant};
73 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
74 use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
75 use clippy_utils::{contains_return, get_trait_def_id, iter_input_pats, meets_msrv, msrvs, paths, return_ty};
76 use if_chain::if_chain;
77 use rustc_hir as hir;
78 use rustc_hir::def::Res;
79 use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TraitItem, TraitItemKind};
80 use rustc_lint::{LateContext, LateLintPass, LintContext};
81 use rustc_middle::lint::in_external_macro;
82 use rustc_middle::ty::{self, TraitRef, Ty};
83 use rustc_semver::RustcVersion;
84 use rustc_session::{declare_tool_lint, impl_lint_pass};
85 use rustc_span::{sym, Span};
86 use rustc_typeck::hir_ty_to_ty;
87
88 declare_clippy_lint! {
89     /// ### What it does
90     /// Checks for usages of `cloned()` on an `Iterator` or `Option` where
91     /// `copied()` could be used instead.
92     ///
93     /// ### Why is this bad?
94     /// `copied()` is better because it guarantees that the type being cloned
95     /// implements `Copy`.
96     ///
97     /// ### Example
98     /// ```rust
99     /// [1, 2, 3].iter().cloned();
100     /// ```
101     /// Use instead:
102     /// ```rust
103     /// [1, 2, 3].iter().copied();
104     /// ```
105     #[clippy::version = "1.53.0"]
106     pub CLONED_INSTEAD_OF_COPIED,
107     pedantic,
108     "used `cloned` where `copied` could be used instead"
109 }
110
111 declare_clippy_lint! {
112     /// ### What it does
113     /// Checks for usage of `_.cloned().<func>()` where call to `.cloned()` can be postponed.
114     ///
115     /// ### Why is this bad?
116     /// It's often inefficient to clone all elements of an iterator, when eventually, only some
117     /// of them will be consumed.
118     ///
119     /// ### Examples
120     /// ```rust
121     /// # let vec = vec!["string".to_string()];
122     ///
123     /// // Bad
124     /// vec.iter().cloned().take(10);
125     ///
126     /// // Good
127     /// vec.iter().take(10).cloned();
128     ///
129     /// // Bad
130     /// vec.iter().cloned().last();
131     ///
132     /// // Good
133     /// vec.iter().last().cloned();
134     ///
135     /// ```
136     /// ### Known Problems
137     /// This `lint` removes the side of effect of cloning items in the iterator.
138     /// A code that relies on that side-effect could fail.
139     ///
140     #[clippy::version = "1.59.0"]
141     pub ITER_OVEREAGER_CLONED,
142     perf,
143     "using `cloned()` early with `Iterator::iter()` can lead to some performance inefficiencies"
144 }
145
146 declare_clippy_lint! {
147     /// ### What it does
148     /// Checks for usages of `Iterator::flat_map()` where `filter_map()` could be
149     /// used instead.
150     ///
151     /// ### Why is this bad?
152     /// When applicable, `filter_map()` is more clear since it shows that
153     /// `Option` is used to produce 0 or 1 items.
154     ///
155     /// ### Example
156     /// ```rust
157     /// let nums: Vec<i32> = ["1", "2", "whee!"].iter().flat_map(|x| x.parse().ok()).collect();
158     /// ```
159     /// Use instead:
160     /// ```rust
161     /// let nums: Vec<i32> = ["1", "2", "whee!"].iter().filter_map(|x| x.parse().ok()).collect();
162     /// ```
163     #[clippy::version = "1.53.0"]
164     pub FLAT_MAP_OPTION,
165     pedantic,
166     "used `flat_map` where `filter_map` could be used instead"
167 }
168
169 declare_clippy_lint! {
170     /// ### What it does
171     /// Checks for `.unwrap()` calls on `Option`s and on `Result`s.
172     ///
173     /// ### Why is this bad?
174     /// It is better to handle the `None` or `Err` case,
175     /// or at least call `.expect(_)` with a more helpful message. Still, for a lot of
176     /// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is
177     /// `Allow` by default.
178     ///
179     /// `result.unwrap()` will let the thread panic on `Err` values.
180     /// Normally, you want to implement more sophisticated error handling,
181     /// and propagate errors upwards with `?` operator.
182     ///
183     /// Even if you want to panic on errors, not all `Error`s implement good
184     /// messages on display. Therefore, it may be beneficial to look at the places
185     /// where they may get displayed. Activate this lint to do just that.
186     ///
187     /// ### Examples
188     /// ```rust
189     /// # let opt = Some(1);
190     ///
191     /// // Bad
192     /// opt.unwrap();
193     ///
194     /// // Good
195     /// opt.expect("more helpful message");
196     /// ```
197     ///
198     /// // or
199     ///
200     /// ```rust
201     /// # let res: Result<usize, ()> = Ok(1);
202     ///
203     /// // Bad
204     /// res.unwrap();
205     ///
206     /// // Good
207     /// res.expect("more helpful message");
208     /// ```
209     #[clippy::version = "1.45.0"]
210     pub UNWRAP_USED,
211     restriction,
212     "using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()`"
213 }
214
215 declare_clippy_lint! {
216     /// ### What it does
217     /// Checks for `.expect()` calls on `Option`s and `Result`s.
218     ///
219     /// ### Why is this bad?
220     /// Usually it is better to handle the `None` or `Err` case.
221     /// Still, for a lot of quick-and-dirty code, `expect` is a good choice, which is why
222     /// this lint is `Allow` by default.
223     ///
224     /// `result.expect()` will let the thread panic on `Err`
225     /// values. Normally, you want to implement more sophisticated error handling,
226     /// and propagate errors upwards with `?` operator.
227     ///
228     /// ### Examples
229     /// ```rust,ignore
230     /// # let opt = Some(1);
231     ///
232     /// // Bad
233     /// opt.expect("one");
234     ///
235     /// // Good
236     /// let opt = Some(1);
237     /// opt?;
238     /// ```
239     ///
240     /// // or
241     ///
242     /// ```rust
243     /// # let res: Result<usize, ()> = Ok(1);
244     ///
245     /// // Bad
246     /// res.expect("one");
247     ///
248     /// // Good
249     /// res?;
250     /// # Ok::<(), ()>(())
251     /// ```
252     #[clippy::version = "1.45.0"]
253     pub EXPECT_USED,
254     restriction,
255     "using `.expect()` on `Result` or `Option`, which might be better handled"
256 }
257
258 declare_clippy_lint! {
259     /// ### What it does
260     /// Checks for methods that should live in a trait
261     /// implementation of a `std` trait (see [llogiq's blog
262     /// post](http://llogiq.github.io/2015/07/30/traits.html) for further
263     /// information) instead of an inherent implementation.
264     ///
265     /// ### Why is this bad?
266     /// Implementing the traits improve ergonomics for users of
267     /// the code, often with very little cost. Also people seeing a `mul(...)`
268     /// method
269     /// may expect `*` to work equally, so you should have good reason to disappoint
270     /// them.
271     ///
272     /// ### Example
273     /// ```rust
274     /// struct X;
275     /// impl X {
276     ///     fn add(&self, other: &X) -> X {
277     ///         // ..
278     /// # X
279     ///     }
280     /// }
281     /// ```
282     #[clippy::version = "pre 1.29.0"]
283     pub SHOULD_IMPLEMENT_TRAIT,
284     style,
285     "defining a method that should be implementing a std trait"
286 }
287
288 declare_clippy_lint! {
289     /// ### What it does
290     /// Checks for methods with certain name prefixes and which
291     /// doesn't match how self is taken. The actual rules are:
292     ///
293     /// |Prefix |Postfix     |`self` taken           | `self` type  |
294     /// |-------|------------|-----------------------|--------------|
295     /// |`as_`  | none       |`&self` or `&mut self` | any          |
296     /// |`from_`| none       | none                  | any          |
297     /// |`into_`| none       |`self`                 | any          |
298     /// |`is_`  | none       |`&self` or none        | any          |
299     /// |`to_`  | `_mut`     |`&mut self`            | any          |
300     /// |`to_`  | not `_mut` |`self`                 | `Copy`       |
301     /// |`to_`  | not `_mut` |`&self`                | not `Copy`   |
302     ///
303     /// Note: Clippy doesn't trigger methods with `to_` prefix in:
304     /// - Traits definition.
305     /// Clippy can not tell if a type that implements a trait is `Copy` or not.
306     /// - Traits implementation, when `&self` is taken.
307     /// The method signature is controlled by the trait and often `&self` is required for all types that implement the trait
308     /// (see e.g. the `std::string::ToString` trait).
309     ///
310     /// Clippy allows `Pin<&Self>` and `Pin<&mut Self>` if `&self` and `&mut self` is required.
311     ///
312     /// Please find more info here:
313     /// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
314     ///
315     /// ### Why is this bad?
316     /// Consistency breeds readability. If you follow the
317     /// conventions, your users won't be surprised that they, e.g., need to supply a
318     /// mutable reference to a `as_..` function.
319     ///
320     /// ### Example
321     /// ```rust
322     /// # struct X;
323     /// impl X {
324     ///     fn as_str(self) -> &'static str {
325     ///         // ..
326     /// # ""
327     ///     }
328     /// }
329     /// ```
330     #[clippy::version = "pre 1.29.0"]
331     pub WRONG_SELF_CONVENTION,
332     style,
333     "defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
334 }
335
336 declare_clippy_lint! {
337     /// ### What it does
338     /// Checks for usage of `ok().expect(..)`.
339     ///
340     /// ### Why is this bad?
341     /// Because you usually call `expect()` on the `Result`
342     /// directly to get a better error message.
343     ///
344     /// ### Known problems
345     /// The error type needs to implement `Debug`
346     ///
347     /// ### Example
348     /// ```rust
349     /// # let x = Ok::<_, ()>(());
350     ///
351     /// // Bad
352     /// x.ok().expect("why did I do this again?");
353     ///
354     /// // Good
355     /// x.expect("why did I do this again?");
356     /// ```
357     #[clippy::version = "pre 1.29.0"]
358     pub OK_EXPECT,
359     style,
360     "using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result"
361 }
362
363 declare_clippy_lint! {
364     /// ### What it does
365     /// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and
366     /// `Result` values.
367     ///
368     /// ### Why is this bad?
369     /// Readability, these can be written as `_.unwrap_or_default`, which is
370     /// simpler and more concise.
371     ///
372     /// ### Examples
373     /// ```rust
374     /// # let x = Some(1);
375     ///
376     /// // Bad
377     /// x.unwrap_or_else(Default::default);
378     /// x.unwrap_or_else(u32::default);
379     ///
380     /// // Good
381     /// x.unwrap_or_default();
382     /// ```
383     #[clippy::version = "1.56.0"]
384     pub UNWRAP_OR_ELSE_DEFAULT,
385     style,
386     "using `.unwrap_or_else(Default::default)`, which is more succinctly expressed as `.unwrap_or_default()`"
387 }
388
389 declare_clippy_lint! {
390     /// ### What it does
391     /// Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
392     /// `result.map(_).unwrap_or_else(_)`.
393     ///
394     /// ### Why is this bad?
395     /// Readability, these can be written more concisely (resp.) as
396     /// `option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`.
397     ///
398     /// ### Known problems
399     /// The order of the arguments is not in execution order
400     ///
401     /// ### Examples
402     /// ```rust
403     /// # let x = Some(1);
404     ///
405     /// // Bad
406     /// x.map(|a| a + 1).unwrap_or(0);
407     ///
408     /// // Good
409     /// x.map_or(0, |a| a + 1);
410     /// ```
411     ///
412     /// // or
413     ///
414     /// ```rust
415     /// # let x: Result<usize, ()> = Ok(1);
416     /// # fn some_function(foo: ()) -> usize { 1 }
417     ///
418     /// // Bad
419     /// x.map(|a| a + 1).unwrap_or_else(some_function);
420     ///
421     /// // Good
422     /// x.map_or_else(some_function, |a| a + 1);
423     /// ```
424     #[clippy::version = "1.45.0"]
425     pub MAP_UNWRAP_OR,
426     pedantic,
427     "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`"
428 }
429
430 declare_clippy_lint! {
431     /// ### What it does
432     /// Checks for usage of `_.map_or(None, _)`.
433     ///
434     /// ### Why is this bad?
435     /// Readability, this can be written more concisely as
436     /// `_.and_then(_)`.
437     ///
438     /// ### Known problems
439     /// The order of the arguments is not in execution order.
440     ///
441     /// ### Example
442     /// ```rust
443     /// # let opt = Some(1);
444     ///
445     /// // Bad
446     /// opt.map_or(None, |a| Some(a + 1));
447     ///
448     /// // Good
449     /// opt.and_then(|a| Some(a + 1));
450     /// ```
451     #[clippy::version = "pre 1.29.0"]
452     pub OPTION_MAP_OR_NONE,
453     style,
454     "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`"
455 }
456
457 declare_clippy_lint! {
458     /// ### What it does
459     /// Checks for usage of `_.map_or(None, Some)`.
460     ///
461     /// ### Why is this bad?
462     /// Readability, this can be written more concisely as
463     /// `_.ok()`.
464     ///
465     /// ### Example
466     /// Bad:
467     /// ```rust
468     /// # let r: Result<u32, &str> = Ok(1);
469     /// assert_eq!(Some(1), r.map_or(None, Some));
470     /// ```
471     ///
472     /// Good:
473     /// ```rust
474     /// # let r: Result<u32, &str> = Ok(1);
475     /// assert_eq!(Some(1), r.ok());
476     /// ```
477     #[clippy::version = "1.44.0"]
478     pub RESULT_MAP_OR_INTO_OPTION,
479     style,
480     "using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`"
481 }
482
483 declare_clippy_lint! {
484     /// ### What it does
485     /// Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or
486     /// `_.or_else(|x| Err(y))`.
487     ///
488     /// ### Why is this bad?
489     /// Readability, this can be written more concisely as
490     /// `_.map(|x| y)` or `_.map_err(|x| y)`.
491     ///
492     /// ### Example
493     /// ```rust
494     /// # fn opt() -> Option<&'static str> { Some("42") }
495     /// # fn res() -> Result<&'static str, &'static str> { Ok("42") }
496     /// let _ = opt().and_then(|s| Some(s.len()));
497     /// let _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) });
498     /// let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) });
499     /// ```
500     ///
501     /// The correct use would be:
502     ///
503     /// ```rust
504     /// # fn opt() -> Option<&'static str> { Some("42") }
505     /// # fn res() -> Result<&'static str, &'static str> { Ok("42") }
506     /// let _ = opt().map(|s| s.len());
507     /// let _ = res().map(|s| if s.len() == 42 { 10 } else { 20 });
508     /// let _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 });
509     /// ```
510     #[clippy::version = "1.45.0"]
511     pub BIND_INSTEAD_OF_MAP,
512     complexity,
513     "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`"
514 }
515
516 declare_clippy_lint! {
517     /// ### What it does
518     /// Checks for usage of `_.filter(_).next()`.
519     ///
520     /// ### Why is this bad?
521     /// Readability, this can be written more concisely as
522     /// `_.find(_)`.
523     ///
524     /// ### Example
525     /// ```rust
526     /// # let vec = vec![1];
527     /// vec.iter().filter(|x| **x == 0).next();
528     /// ```
529     /// Could be written as
530     /// ```rust
531     /// # let vec = vec![1];
532     /// vec.iter().find(|x| **x == 0);
533     /// ```
534     #[clippy::version = "pre 1.29.0"]
535     pub FILTER_NEXT,
536     complexity,
537     "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`"
538 }
539
540 declare_clippy_lint! {
541     /// ### What it does
542     /// Checks for usage of `_.skip_while(condition).next()`.
543     ///
544     /// ### Why is this bad?
545     /// Readability, this can be written more concisely as
546     /// `_.find(!condition)`.
547     ///
548     /// ### Example
549     /// ```rust
550     /// # let vec = vec![1];
551     /// vec.iter().skip_while(|x| **x == 0).next();
552     /// ```
553     /// Could be written as
554     /// ```rust
555     /// # let vec = vec![1];
556     /// vec.iter().find(|x| **x != 0);
557     /// ```
558     #[clippy::version = "1.42.0"]
559     pub SKIP_WHILE_NEXT,
560     complexity,
561     "using `skip_while(p).next()`, which is more succinctly expressed as `.find(!p)`"
562 }
563
564 declare_clippy_lint! {
565     /// ### What it does
566     /// Checks for usage of `_.map(_).flatten(_)` on `Iterator` and `Option`
567     ///
568     /// ### Why is this bad?
569     /// Readability, this can be written more concisely as
570     /// `_.flat_map(_)` for `Iterator` or `_.and_then(_)` for `Option`
571     ///
572     /// ### Example
573     /// ```rust
574     /// let vec = vec![vec![1]];
575     /// let opt = Some(5);
576     ///
577     /// // Bad
578     /// vec.iter().map(|x| x.iter()).flatten();
579     /// opt.map(|x| Some(x * 2)).flatten();
580     ///
581     /// // Good
582     /// vec.iter().flat_map(|x| x.iter());
583     /// opt.and_then(|x| Some(x * 2));
584     /// ```
585     #[clippy::version = "1.31.0"]
586     pub MAP_FLATTEN,
587     complexity,
588     "using combinations of `flatten` and `map` which can usually be written as a single method call"
589 }
590
591 declare_clippy_lint! {
592     /// ### What it does
593     /// Checks for usage of `_.filter(_).map(_)` that can be written more simply
594     /// as `filter_map(_)`.
595     ///
596     /// ### Why is this bad?
597     /// Redundant code in the `filter` and `map` operations is poor style and
598     /// less performant.
599     ///
600      /// ### Example
601     /// Bad:
602     /// ```rust
603     /// (0_i32..10)
604     ///     .filter(|n| n.checked_add(1).is_some())
605     ///     .map(|n| n.checked_add(1).unwrap());
606     /// ```
607     ///
608     /// Good:
609     /// ```rust
610     /// (0_i32..10).filter_map(|n| n.checked_add(1));
611     /// ```
612     #[clippy::version = "1.51.0"]
613     pub MANUAL_FILTER_MAP,
614     complexity,
615     "using `_.filter(_).map(_)` in a way that can be written more simply as `filter_map(_)`"
616 }
617
618 declare_clippy_lint! {
619     /// ### What it does
620     /// Checks for usage of `_.find(_).map(_)` that can be written more simply
621     /// as `find_map(_)`.
622     ///
623     /// ### Why is this bad?
624     /// Redundant code in the `find` and `map` operations is poor style and
625     /// less performant.
626     ///
627      /// ### Example
628     /// Bad:
629     /// ```rust
630     /// (0_i32..10)
631     ///     .find(|n| n.checked_add(1).is_some())
632     ///     .map(|n| n.checked_add(1).unwrap());
633     /// ```
634     ///
635     /// Good:
636     /// ```rust
637     /// (0_i32..10).find_map(|n| n.checked_add(1));
638     /// ```
639     #[clippy::version = "1.51.0"]
640     pub MANUAL_FIND_MAP,
641     complexity,
642     "using `_.find(_).map(_)` in a way that can be written more simply as `find_map(_)`"
643 }
644
645 declare_clippy_lint! {
646     /// ### What it does
647     /// Checks for usage of `_.filter_map(_).next()`.
648     ///
649     /// ### Why is this bad?
650     /// Readability, this can be written more concisely as
651     /// `_.find_map(_)`.
652     ///
653     /// ### Example
654     /// ```rust
655     ///  (0..3).filter_map(|x| if x == 2 { Some(x) } else { None }).next();
656     /// ```
657     /// Can be written as
658     ///
659     /// ```rust
660     ///  (0..3).find_map(|x| if x == 2 { Some(x) } else { None });
661     /// ```
662     #[clippy::version = "1.36.0"]
663     pub FILTER_MAP_NEXT,
664     pedantic,
665     "using combination of `filter_map` and `next` which can usually be written as a single method call"
666 }
667
668 declare_clippy_lint! {
669     /// ### What it does
670     /// Checks for usage of `flat_map(|x| x)`.
671     ///
672     /// ### Why is this bad?
673     /// Readability, this can be written more concisely by using `flatten`.
674     ///
675     /// ### Example
676     /// ```rust
677     /// # let iter = vec![vec![0]].into_iter();
678     /// iter.flat_map(|x| x);
679     /// ```
680     /// Can be written as
681     /// ```rust
682     /// # let iter = vec![vec![0]].into_iter();
683     /// iter.flatten();
684     /// ```
685     #[clippy::version = "1.39.0"]
686     pub FLAT_MAP_IDENTITY,
687     complexity,
688     "call to `flat_map` where `flatten` is sufficient"
689 }
690
691 declare_clippy_lint! {
692     /// ### What it does
693     /// Checks for an iterator or string search (such as `find()`,
694     /// `position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`.
695     ///
696     /// ### Why is this bad?
697     /// Readability, this can be written more concisely as:
698     /// * `_.any(_)`, or `_.contains(_)` for `is_some()`,
699     /// * `!_.any(_)`, or `!_.contains(_)` for `is_none()`.
700     ///
701     /// ### Example
702     /// ```rust
703     /// let vec = vec![1];
704     /// vec.iter().find(|x| **x == 0).is_some();
705     ///
706     /// let _ = "hello world".find("world").is_none();
707     /// ```
708     /// Could be written as
709     /// ```rust
710     /// let vec = vec![1];
711     /// vec.iter().any(|x| *x == 0);
712     ///
713     /// let _ = !"hello world".contains("world");
714     /// ```
715     #[clippy::version = "pre 1.29.0"]
716     pub SEARCH_IS_SOME,
717     complexity,
718     "using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`)"
719 }
720
721 declare_clippy_lint! {
722     /// ### What it does
723     /// Checks for usage of `.chars().next()` on a `str` to check
724     /// if it starts with a given char.
725     ///
726     /// ### Why is this bad?
727     /// Readability, this can be written more concisely as
728     /// `_.starts_with(_)`.
729     ///
730     /// ### Example
731     /// ```rust
732     /// let name = "foo";
733     /// if name.chars().next() == Some('_') {};
734     /// ```
735     /// Could be written as
736     /// ```rust
737     /// let name = "foo";
738     /// if name.starts_with('_') {};
739     /// ```
740     #[clippy::version = "pre 1.29.0"]
741     pub CHARS_NEXT_CMP,
742     style,
743     "using `.chars().next()` to check if a string starts with a char"
744 }
745
746 declare_clippy_lint! {
747     /// ### What it does
748     /// Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`,
749     /// etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or
750     /// `unwrap_or_default` instead.
751     ///
752     /// ### Why is this bad?
753     /// The function will always be called and potentially
754     /// allocate an object acting as the default.
755     ///
756     /// ### Known problems
757     /// If the function has side-effects, not calling it will
758     /// change the semantic of the program, but you shouldn't rely on that anyway.
759     ///
760     /// ### Example
761     /// ```rust
762     /// # let foo = Some(String::new());
763     /// foo.unwrap_or(String::new());
764     /// ```
765     /// this can instead be written:
766     /// ```rust
767     /// # let foo = Some(String::new());
768     /// foo.unwrap_or_else(String::new);
769     /// ```
770     /// or
771     /// ```rust
772     /// # let foo = Some(String::new());
773     /// foo.unwrap_or_default();
774     /// ```
775     #[clippy::version = "pre 1.29.0"]
776     pub OR_FUN_CALL,
777     perf,
778     "using any `*or` method with a function call, which suggests `*or_else`"
779 }
780
781 declare_clippy_lint! {
782     /// ### What it does
783     /// Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`,
784     /// etc., and suggests to use `unwrap_or_else` instead
785     ///
786     /// ### Why is this bad?
787     /// The function will always be called.
788     ///
789     /// ### Known problems
790     /// If the function has side-effects, not calling it will
791     /// change the semantics of the program, but you shouldn't rely on that anyway.
792     ///
793     /// ### Example
794     /// ```rust
795     /// # let foo = Some(String::new());
796     /// # let err_code = "418";
797     /// # let err_msg = "I'm a teapot";
798     /// foo.expect(&format!("Err {}: {}", err_code, err_msg));
799     /// ```
800     /// or
801     /// ```rust
802     /// # let foo = Some(String::new());
803     /// # let err_code = "418";
804     /// # let err_msg = "I'm a teapot";
805     /// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str());
806     /// ```
807     /// this can instead be written:
808     /// ```rust
809     /// # let foo = Some(String::new());
810     /// # let err_code = "418";
811     /// # let err_msg = "I'm a teapot";
812     /// foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg));
813     /// ```
814     #[clippy::version = "pre 1.29.0"]
815     pub EXPECT_FUN_CALL,
816     perf,
817     "using any `expect` method with a function call"
818 }
819
820 declare_clippy_lint! {
821     /// ### What it does
822     /// Checks for usage of `.clone()` on a `Copy` type.
823     ///
824     /// ### Why is this bad?
825     /// The only reason `Copy` types implement `Clone` is for
826     /// generics, not for using the `clone` method on a concrete type.
827     ///
828     /// ### Example
829     /// ```rust
830     /// 42u64.clone();
831     /// ```
832     #[clippy::version = "pre 1.29.0"]
833     pub CLONE_ON_COPY,
834     complexity,
835     "using `clone` on a `Copy` type"
836 }
837
838 declare_clippy_lint! {
839     /// ### What it does
840     /// Checks for usage of `.clone()` on a ref-counted pointer,
841     /// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified
842     /// function syntax instead (e.g., `Rc::clone(foo)`).
843     ///
844     /// ### Why is this bad?
845     /// Calling '.clone()' on an Rc, Arc, or Weak
846     /// can obscure the fact that only the pointer is being cloned, not the underlying
847     /// data.
848     ///
849     /// ### Example
850     /// ```rust
851     /// # use std::rc::Rc;
852     /// let x = Rc::new(1);
853     ///
854     /// // Bad
855     /// x.clone();
856     ///
857     /// // Good
858     /// Rc::clone(&x);
859     /// ```
860     #[clippy::version = "pre 1.29.0"]
861     pub CLONE_ON_REF_PTR,
862     restriction,
863     "using 'clone' on a ref-counted pointer"
864 }
865
866 declare_clippy_lint! {
867     /// ### What it does
868     /// Checks for usage of `.clone()` on an `&&T`.
869     ///
870     /// ### Why is this bad?
871     /// Cloning an `&&T` copies the inner `&T`, instead of
872     /// cloning the underlying `T`.
873     ///
874     /// ### Example
875     /// ```rust
876     /// fn main() {
877     ///     let x = vec![1];
878     ///     let y = &&x;
879     ///     let z = y.clone();
880     ///     println!("{:p} {:p}", *y, z); // prints out the same pointer
881     /// }
882     /// ```
883     #[clippy::version = "pre 1.29.0"]
884     pub CLONE_DOUBLE_REF,
885     correctness,
886     "using `clone` on `&&T`"
887 }
888
889 declare_clippy_lint! {
890     /// ### What it does
891     /// Checks for usage of `.to_string()` on an `&&T` where
892     /// `T` implements `ToString` directly (like `&&str` or `&&String`).
893     ///
894     /// ### Why is this bad?
895     /// This bypasses the specialized implementation of
896     /// `ToString` and instead goes through the more expensive string formatting
897     /// facilities.
898     ///
899     /// ### Example
900     /// ```rust
901     /// // Generic implementation for `T: Display` is used (slow)
902     /// ["foo", "bar"].iter().map(|s| s.to_string());
903     ///
904     /// // OK, the specialized impl is used
905     /// ["foo", "bar"].iter().map(|&s| s.to_string());
906     /// ```
907     #[clippy::version = "1.40.0"]
908     pub INEFFICIENT_TO_STRING,
909     pedantic,
910     "using `to_string` on `&&T` where `T: ToString`"
911 }
912
913 declare_clippy_lint! {
914     /// ### What it does
915     /// Checks for `new` not returning a type that contains `Self`.
916     ///
917     /// ### Why is this bad?
918     /// As a convention, `new` methods are used to make a new
919     /// instance of a type.
920     ///
921     /// ### Example
922     /// In an impl block:
923     /// ```rust
924     /// # struct Foo;
925     /// # struct NotAFoo;
926     /// impl Foo {
927     ///     fn new() -> NotAFoo {
928     /// # NotAFoo
929     ///     }
930     /// }
931     /// ```
932     ///
933     /// ```rust
934     /// # struct Foo;
935     /// struct Bar(Foo);
936     /// impl Foo {
937     ///     // Bad. The type name must contain `Self`
938     ///     fn new() -> Bar {
939     /// # Bar(Foo)
940     ///     }
941     /// }
942     /// ```
943     ///
944     /// ```rust
945     /// # struct Foo;
946     /// # struct FooError;
947     /// impl Foo {
948     ///     // Good. Return type contains `Self`
949     ///     fn new() -> Result<Foo, FooError> {
950     /// # Ok(Foo)
951     ///     }
952     /// }
953     /// ```
954     ///
955     /// Or in a trait definition:
956     /// ```rust
957     /// pub trait Trait {
958     ///     // Bad. The type name must contain `Self`
959     ///     fn new();
960     /// }
961     /// ```
962     ///
963     /// ```rust
964     /// pub trait Trait {
965     ///     // Good. Return type contains `Self`
966     ///     fn new() -> Self;
967     /// }
968     /// ```
969     #[clippy::version = "pre 1.29.0"]
970     pub NEW_RET_NO_SELF,
971     style,
972     "not returning type containing `Self` in a `new` method"
973 }
974
975 declare_clippy_lint! {
976     /// ### What it does
977     /// Checks for string methods that receive a single-character
978     /// `str` as an argument, e.g., `_.split("x")`.
979     ///
980     /// ### Why is this bad?
981     /// Performing these methods using a `char` is faster than
982     /// using a `str`.
983     ///
984     /// ### Known problems
985     /// Does not catch multi-byte unicode characters.
986     ///
987     /// ### Example
988     /// ```rust,ignore
989     /// // Bad
990     /// _.split("x");
991     ///
992     /// // Good
993     /// _.split('x');
994     #[clippy::version = "pre 1.29.0"]
995     pub SINGLE_CHAR_PATTERN,
996     perf,
997     "using a single-character str where a char could be used, e.g., `_.split(\"x\")`"
998 }
999
1000 declare_clippy_lint! {
1001     /// ### What it does
1002     /// Checks for calling `.step_by(0)` on iterators which panics.
1003     ///
1004     /// ### Why is this bad?
1005     /// This very much looks like an oversight. Use `panic!()` instead if you
1006     /// actually intend to panic.
1007     ///
1008     /// ### Example
1009     /// ```rust,should_panic
1010     /// for x in (0..100).step_by(0) {
1011     ///     //..
1012     /// }
1013     /// ```
1014     #[clippy::version = "pre 1.29.0"]
1015     pub ITERATOR_STEP_BY_ZERO,
1016     correctness,
1017     "using `Iterator::step_by(0)`, which will panic at runtime"
1018 }
1019
1020 declare_clippy_lint! {
1021     /// ### What it does
1022     /// Checks for indirect collection of populated `Option`
1023     ///
1024     /// ### Why is this bad?
1025     /// `Option` is like a collection of 0-1 things, so `flatten`
1026     /// automatically does this without suspicious-looking `unwrap` calls.
1027     ///
1028     /// ### Example
1029     /// ```rust
1030     /// let _ = std::iter::empty::<Option<i32>>().filter(Option::is_some).map(Option::unwrap);
1031     /// ```
1032     /// Use instead:
1033     /// ```rust
1034     /// let _ = std::iter::empty::<Option<i32>>().flatten();
1035     /// ```
1036     #[clippy::version = "1.53.0"]
1037     pub OPTION_FILTER_MAP,
1038     complexity,
1039     "filtering `Option` for `Some` then force-unwrapping, which can be one type-safe operation"
1040 }
1041
1042 declare_clippy_lint! {
1043     /// ### What it does
1044     /// Checks for the use of `iter.nth(0)`.
1045     ///
1046     /// ### Why is this bad?
1047     /// `iter.next()` is equivalent to
1048     /// `iter.nth(0)`, as they both consume the next element,
1049     ///  but is more readable.
1050     ///
1051     /// ### Example
1052     /// ```rust
1053     /// # use std::collections::HashSet;
1054     /// // Bad
1055     /// # let mut s = HashSet::new();
1056     /// # s.insert(1);
1057     /// let x = s.iter().nth(0);
1058     ///
1059     /// // Good
1060     /// # let mut s = HashSet::new();
1061     /// # s.insert(1);
1062     /// let x = s.iter().next();
1063     /// ```
1064     #[clippy::version = "1.42.0"]
1065     pub ITER_NTH_ZERO,
1066     style,
1067     "replace `iter.nth(0)` with `iter.next()`"
1068 }
1069
1070 declare_clippy_lint! {
1071     /// ### What it does
1072     /// Checks for use of `.iter().nth()` (and the related
1073     /// `.iter_mut().nth()`) on standard library types with *O*(1) element access.
1074     ///
1075     /// ### Why is this bad?
1076     /// `.get()` and `.get_mut()` are more efficient and more
1077     /// readable.
1078     ///
1079     /// ### Example
1080     /// ```rust
1081     /// let some_vec = vec![0, 1, 2, 3];
1082     /// let bad_vec = some_vec.iter().nth(3);
1083     /// let bad_slice = &some_vec[..].iter().nth(3);
1084     /// ```
1085     /// The correct use would be:
1086     /// ```rust
1087     /// let some_vec = vec![0, 1, 2, 3];
1088     /// let bad_vec = some_vec.get(3);
1089     /// let bad_slice = &some_vec[..].get(3);
1090     /// ```
1091     #[clippy::version = "pre 1.29.0"]
1092     pub ITER_NTH,
1093     perf,
1094     "using `.iter().nth()` on a standard library type with O(1) element access"
1095 }
1096
1097 declare_clippy_lint! {
1098     /// ### What it does
1099     /// Checks for use of `.skip(x).next()` on iterators.
1100     ///
1101     /// ### Why is this bad?
1102     /// `.nth(x)` is cleaner
1103     ///
1104     /// ### Example
1105     /// ```rust
1106     /// let some_vec = vec![0, 1, 2, 3];
1107     /// let bad_vec = some_vec.iter().skip(3).next();
1108     /// let bad_slice = &some_vec[..].iter().skip(3).next();
1109     /// ```
1110     /// The correct use would be:
1111     /// ```rust
1112     /// let some_vec = vec![0, 1, 2, 3];
1113     /// let bad_vec = some_vec.iter().nth(3);
1114     /// let bad_slice = &some_vec[..].iter().nth(3);
1115     /// ```
1116     #[clippy::version = "pre 1.29.0"]
1117     pub ITER_SKIP_NEXT,
1118     style,
1119     "using `.skip(x).next()` on an iterator"
1120 }
1121
1122 declare_clippy_lint! {
1123     /// ### What it does
1124     /// Checks for use of `.drain(..)` on `Vec` and `VecDeque` for iteration.
1125     ///
1126     /// ### Why is this bad?
1127     /// `.into_iter()` is simpler with better performance.
1128     ///
1129     /// ### Example
1130     /// ```rust
1131     /// # use std::collections::HashSet;
1132     /// let mut foo = vec![0, 1, 2, 3];
1133     /// let bar: HashSet<usize> = foo.drain(..).collect();
1134     /// ```
1135     /// Use instead:
1136     /// ```rust
1137     /// # use std::collections::HashSet;
1138     /// let foo = vec![0, 1, 2, 3];
1139     /// let bar: HashSet<usize> = foo.into_iter().collect();
1140     /// ```
1141     #[clippy::version = "1.61.0"]
1142     pub ITER_WITH_DRAIN,
1143     perf,
1144     "replace `.drain(..)` with `.into_iter()`"
1145 }
1146
1147 declare_clippy_lint! {
1148     /// ### What it does
1149     /// Checks for use of `.get().unwrap()` (or
1150     /// `.get_mut().unwrap`) on a standard library type which implements `Index`
1151     ///
1152     /// ### Why is this bad?
1153     /// Using the Index trait (`[]`) is more clear and more
1154     /// concise.
1155     ///
1156     /// ### Known problems
1157     /// Not a replacement for error handling: Using either
1158     /// `.unwrap()` or the Index trait (`[]`) carries the risk of causing a `panic`
1159     /// if the value being accessed is `None`. If the use of `.get().unwrap()` is a
1160     /// temporary placeholder for dealing with the `Option` type, then this does
1161     /// not mitigate the need for error handling. If there is a chance that `.get()`
1162     /// will be `None` in your program, then it is advisable that the `None` case
1163     /// is handled in a future refactor instead of using `.unwrap()` or the Index
1164     /// trait.
1165     ///
1166     /// ### Example
1167     /// ```rust
1168     /// let mut some_vec = vec![0, 1, 2, 3];
1169     /// let last = some_vec.get(3).unwrap();
1170     /// *some_vec.get_mut(0).unwrap() = 1;
1171     /// ```
1172     /// The correct use would be:
1173     /// ```rust
1174     /// let mut some_vec = vec![0, 1, 2, 3];
1175     /// let last = some_vec[3];
1176     /// some_vec[0] = 1;
1177     /// ```
1178     #[clippy::version = "pre 1.29.0"]
1179     pub GET_UNWRAP,
1180     restriction,
1181     "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead"
1182 }
1183
1184 declare_clippy_lint! {
1185     /// ### What it does
1186     /// Checks for occurrences where one vector gets extended instead of append
1187     ///
1188     /// ### Why is this bad?
1189     /// Using `append` instead of `extend` is more concise and faster
1190     ///
1191     /// ### Example
1192     /// ```rust
1193     /// let mut a = vec![1, 2, 3];
1194     /// let mut b = vec![4, 5, 6];
1195     ///
1196     /// // Bad
1197     /// a.extend(b.drain(..));
1198     ///
1199     /// // Good
1200     /// a.append(&mut b);
1201     /// ```
1202     #[clippy::version = "1.55.0"]
1203     pub EXTEND_WITH_DRAIN,
1204     perf,
1205     "using vec.append(&mut vec) to move the full range of a vecor to another"
1206 }
1207
1208 declare_clippy_lint! {
1209     /// ### What it does
1210     /// Checks for the use of `.extend(s.chars())` where s is a
1211     /// `&str` or `String`.
1212     ///
1213     /// ### Why is this bad?
1214     /// `.push_str(s)` is clearer
1215     ///
1216     /// ### Example
1217     /// ```rust
1218     /// let abc = "abc";
1219     /// let def = String::from("def");
1220     /// let mut s = String::new();
1221     /// s.extend(abc.chars());
1222     /// s.extend(def.chars());
1223     /// ```
1224     /// The correct use would be:
1225     /// ```rust
1226     /// let abc = "abc";
1227     /// let def = String::from("def");
1228     /// let mut s = String::new();
1229     /// s.push_str(abc);
1230     /// s.push_str(&def);
1231     /// ```
1232     #[clippy::version = "pre 1.29.0"]
1233     pub STRING_EXTEND_CHARS,
1234     style,
1235     "using `x.extend(s.chars())` where s is a `&str` or `String`"
1236 }
1237
1238 declare_clippy_lint! {
1239     /// ### What it does
1240     /// Checks for the use of `.cloned().collect()` on slice to
1241     /// create a `Vec`.
1242     ///
1243     /// ### Why is this bad?
1244     /// `.to_vec()` is clearer
1245     ///
1246     /// ### Example
1247     /// ```rust
1248     /// let s = [1, 2, 3, 4, 5];
1249     /// let s2: Vec<isize> = s[..].iter().cloned().collect();
1250     /// ```
1251     /// The better use would be:
1252     /// ```rust
1253     /// let s = [1, 2, 3, 4, 5];
1254     /// let s2: Vec<isize> = s.to_vec();
1255     /// ```
1256     #[clippy::version = "pre 1.29.0"]
1257     pub ITER_CLONED_COLLECT,
1258     style,
1259     "using `.cloned().collect()` on slice to create a `Vec`"
1260 }
1261
1262 declare_clippy_lint! {
1263     /// ### What it does
1264     /// Checks for usage of `_.chars().last()` or
1265     /// `_.chars().next_back()` on a `str` to check if it ends with a given char.
1266     ///
1267     /// ### Why is this bad?
1268     /// Readability, this can be written more concisely as
1269     /// `_.ends_with(_)`.
1270     ///
1271     /// ### Example
1272     /// ```rust
1273     /// # let name = "_";
1274     ///
1275     /// // Bad
1276     /// name.chars().last() == Some('_') || name.chars().next_back() == Some('-');
1277     ///
1278     /// // Good
1279     /// name.ends_with('_') || name.ends_with('-');
1280     /// ```
1281     #[clippy::version = "pre 1.29.0"]
1282     pub CHARS_LAST_CMP,
1283     style,
1284     "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char"
1285 }
1286
1287 declare_clippy_lint! {
1288     /// ### What it does
1289     /// Checks for usage of `.as_ref()` or `.as_mut()` where the
1290     /// types before and after the call are the same.
1291     ///
1292     /// ### Why is this bad?
1293     /// The call is unnecessary.
1294     ///
1295     /// ### Example
1296     /// ```rust
1297     /// # fn do_stuff(x: &[i32]) {}
1298     /// let x: &[i32] = &[1, 2, 3, 4, 5];
1299     /// do_stuff(x.as_ref());
1300     /// ```
1301     /// The correct use would be:
1302     /// ```rust
1303     /// # fn do_stuff(x: &[i32]) {}
1304     /// let x: &[i32] = &[1, 2, 3, 4, 5];
1305     /// do_stuff(x);
1306     /// ```
1307     #[clippy::version = "pre 1.29.0"]
1308     pub USELESS_ASREF,
1309     complexity,
1310     "using `as_ref` where the types before and after the call are the same"
1311 }
1312
1313 declare_clippy_lint! {
1314     /// ### What it does
1315     /// Checks for using `fold` when a more succinct alternative exists.
1316     /// Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
1317     /// `sum` or `product`.
1318     ///
1319     /// ### Why is this bad?
1320     /// Readability.
1321     ///
1322     /// ### Example
1323     /// ```rust
1324     /// let _ = (0..3).fold(false, |acc, x| acc || x > 2);
1325     /// ```
1326     /// This could be written as:
1327     /// ```rust
1328     /// let _ = (0..3).any(|x| x > 2);
1329     /// ```
1330     #[clippy::version = "pre 1.29.0"]
1331     pub UNNECESSARY_FOLD,
1332     style,
1333     "using `fold` when a more succinct alternative exists"
1334 }
1335
1336 declare_clippy_lint! {
1337     /// ### What it does
1338     /// Checks for `filter_map` calls that could be replaced by `filter` or `map`.
1339     /// More specifically it checks if the closure provided is only performing one of the
1340     /// filter or map operations and suggests the appropriate option.
1341     ///
1342     /// ### Why is this bad?
1343     /// Complexity. The intent is also clearer if only a single
1344     /// operation is being performed.
1345     ///
1346     /// ### Example
1347     /// ```rust
1348     /// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None });
1349     ///
1350     /// // As there is no transformation of the argument this could be written as:
1351     /// let _ = (0..3).filter(|&x| x > 2);
1352     /// ```
1353     ///
1354     /// ```rust
1355     /// let _ = (0..4).filter_map(|x| Some(x + 1));
1356     ///
1357     /// // As there is no conditional check on the argument this could be written as:
1358     /// let _ = (0..4).map(|x| x + 1);
1359     /// ```
1360     #[clippy::version = "1.31.0"]
1361     pub UNNECESSARY_FILTER_MAP,
1362     complexity,
1363     "using `filter_map` when a more succinct alternative exists"
1364 }
1365
1366 declare_clippy_lint! {
1367     /// ### What it does
1368     /// Checks for `find_map` calls that could be replaced by `find` or `map`. More
1369     /// specifically it checks if the closure provided is only performing one of the
1370     /// find or map operations and suggests the appropriate option.
1371     ///
1372     /// ### Why is this bad?
1373     /// Complexity. The intent is also clearer if only a single
1374     /// operation is being performed.
1375     ///
1376     /// ### Example
1377     /// ```rust
1378     /// let _ = (0..3).find_map(|x| if x > 2 { Some(x) } else { None });
1379     ///
1380     /// // As there is no transformation of the argument this could be written as:
1381     /// let _ = (0..3).find(|&x| x > 2);
1382     /// ```
1383     ///
1384     /// ```rust
1385     /// let _ = (0..4).find_map(|x| Some(x + 1));
1386     ///
1387     /// // As there is no conditional check on the argument this could be written as:
1388     /// let _ = (0..4).map(|x| x + 1).next();
1389     /// ```
1390     #[clippy::version = "1.61.0"]
1391     pub UNNECESSARY_FIND_MAP,
1392     complexity,
1393     "using `find_map` when a more succinct alternative exists"
1394 }
1395
1396 declare_clippy_lint! {
1397     /// ### What it does
1398     /// Checks for `into_iter` calls on references which should be replaced by `iter`
1399     /// or `iter_mut`.
1400     ///
1401     /// ### Why is this bad?
1402     /// Readability. Calling `into_iter` on a reference will not move out its
1403     /// content into the resulting iterator, which is confusing. It is better just call `iter` or
1404     /// `iter_mut` directly.
1405     ///
1406     /// ### Example
1407     /// ```rust
1408     /// // Bad
1409     /// let _ = (&vec![3, 4, 5]).into_iter();
1410     ///
1411     /// // Good
1412     /// let _ = (&vec![3, 4, 5]).iter();
1413     /// ```
1414     #[clippy::version = "1.32.0"]
1415     pub INTO_ITER_ON_REF,
1416     style,
1417     "using `.into_iter()` on a reference"
1418 }
1419
1420 declare_clippy_lint! {
1421     /// ### What it does
1422     /// Checks for calls to `map` followed by a `count`.
1423     ///
1424     /// ### Why is this bad?
1425     /// It looks suspicious. Maybe `map` was confused with `filter`.
1426     /// If the `map` call is intentional, this should be rewritten
1427     /// using `inspect`. Or, if you intend to drive the iterator to
1428     /// completion, you can just use `for_each` instead.
1429     ///
1430     /// ### Example
1431     /// ```rust
1432     /// let _ = (0..3).map(|x| x + 2).count();
1433     /// ```
1434     #[clippy::version = "1.39.0"]
1435     pub SUSPICIOUS_MAP,
1436     suspicious,
1437     "suspicious usage of map"
1438 }
1439
1440 declare_clippy_lint! {
1441     /// ### What it does
1442     /// Checks for `MaybeUninit::uninit().assume_init()`.
1443     ///
1444     /// ### Why is this bad?
1445     /// For most types, this is undefined behavior.
1446     ///
1447     /// ### Known problems
1448     /// For now, we accept empty tuples and tuples / arrays
1449     /// of `MaybeUninit`. There may be other types that allow uninitialized
1450     /// data, but those are not yet rigorously defined.
1451     ///
1452     /// ### Example
1453     /// ```rust
1454     /// // Beware the UB
1455     /// use std::mem::MaybeUninit;
1456     ///
1457     /// let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
1458     /// ```
1459     ///
1460     /// Note that the following is OK:
1461     ///
1462     /// ```rust
1463     /// use std::mem::MaybeUninit;
1464     ///
1465     /// let _: [MaybeUninit<bool>; 5] = unsafe {
1466     ///     MaybeUninit::uninit().assume_init()
1467     /// };
1468     /// ```
1469     #[clippy::version = "1.39.0"]
1470     pub UNINIT_ASSUMED_INIT,
1471     correctness,
1472     "`MaybeUninit::uninit().assume_init()`"
1473 }
1474
1475 declare_clippy_lint! {
1476     /// ### What it does
1477     /// Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`.
1478     ///
1479     /// ### Why is this bad?
1480     /// These can be written simply with `saturating_add/sub` methods.
1481     ///
1482     /// ### Example
1483     /// ```rust
1484     /// # let y: u32 = 0;
1485     /// # let x: u32 = 100;
1486     /// let add = x.checked_add(y).unwrap_or(u32::MAX);
1487     /// let sub = x.checked_sub(y).unwrap_or(u32::MIN);
1488     /// ```
1489     ///
1490     /// can be written using dedicated methods for saturating addition/subtraction as:
1491     ///
1492     /// ```rust
1493     /// # let y: u32 = 0;
1494     /// # let x: u32 = 100;
1495     /// let add = x.saturating_add(y);
1496     /// let sub = x.saturating_sub(y);
1497     /// ```
1498     #[clippy::version = "1.39.0"]
1499     pub MANUAL_SATURATING_ARITHMETIC,
1500     style,
1501     "`.chcked_add/sub(x).unwrap_or(MAX/MIN)`"
1502 }
1503
1504 declare_clippy_lint! {
1505     /// ### What it does
1506     /// Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to
1507     /// zero-sized types
1508     ///
1509     /// ### Why is this bad?
1510     /// This is a no-op, and likely unintended
1511     ///
1512     /// ### Example
1513     /// ```rust
1514     /// unsafe { (&() as *const ()).offset(1) };
1515     /// ```
1516     #[clippy::version = "1.41.0"]
1517     pub ZST_OFFSET,
1518     correctness,
1519     "Check for offset calculations on raw pointers to zero-sized types"
1520 }
1521
1522 declare_clippy_lint! {
1523     /// ### What it does
1524     /// Checks for `FileType::is_file()`.
1525     ///
1526     /// ### Why is this bad?
1527     /// When people testing a file type with `FileType::is_file`
1528     /// they are testing whether a path is something they can get bytes from. But
1529     /// `is_file` doesn't cover special file types in unix-like systems, and doesn't cover
1530     /// symlink in windows. Using `!FileType::is_dir()` is a better way to that intention.
1531     ///
1532     /// ### Example
1533     /// ```rust
1534     /// # || {
1535     /// let metadata = std::fs::metadata("foo.txt")?;
1536     /// let filetype = metadata.file_type();
1537     ///
1538     /// if filetype.is_file() {
1539     ///     // read file
1540     /// }
1541     /// # Ok::<_, std::io::Error>(())
1542     /// # };
1543     /// ```
1544     ///
1545     /// should be written as:
1546     ///
1547     /// ```rust
1548     /// # || {
1549     /// let metadata = std::fs::metadata("foo.txt")?;
1550     /// let filetype = metadata.file_type();
1551     ///
1552     /// if !filetype.is_dir() {
1553     ///     // read file
1554     /// }
1555     /// # Ok::<_, std::io::Error>(())
1556     /// # };
1557     /// ```
1558     #[clippy::version = "1.42.0"]
1559     pub FILETYPE_IS_FILE,
1560     restriction,
1561     "`FileType::is_file` is not recommended to test for readable file type"
1562 }
1563
1564 declare_clippy_lint! {
1565     /// ### What it does
1566     /// Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str).
1567     ///
1568     /// ### Why is this bad?
1569     /// Readability, this can be written more concisely as
1570     /// `_.as_deref()`.
1571     ///
1572     /// ### Example
1573     /// ```rust
1574     /// # let opt = Some("".to_string());
1575     /// opt.as_ref().map(String::as_str)
1576     /// # ;
1577     /// ```
1578     /// Can be written as
1579     /// ```rust
1580     /// # let opt = Some("".to_string());
1581     /// opt.as_deref()
1582     /// # ;
1583     /// ```
1584     #[clippy::version = "1.42.0"]
1585     pub OPTION_AS_REF_DEREF,
1586     complexity,
1587     "using `as_ref().map(Deref::deref)`, which is more succinctly expressed as `as_deref()`"
1588 }
1589
1590 declare_clippy_lint! {
1591     /// ### What it does
1592     /// Checks for usage of `iter().next()` on a Slice or an Array
1593     ///
1594     /// ### Why is this bad?
1595     /// These can be shortened into `.get()`
1596     ///
1597     /// ### Example
1598     /// ```rust
1599     /// # let a = [1, 2, 3];
1600     /// # let b = vec![1, 2, 3];
1601     /// a[2..].iter().next();
1602     /// b.iter().next();
1603     /// ```
1604     /// should be written as:
1605     /// ```rust
1606     /// # let a = [1, 2, 3];
1607     /// # let b = vec![1, 2, 3];
1608     /// a.get(2);
1609     /// b.get(0);
1610     /// ```
1611     #[clippy::version = "1.46.0"]
1612     pub ITER_NEXT_SLICE,
1613     style,
1614     "using `.iter().next()` on a sliced array, which can be shortened to just `.get()`"
1615 }
1616
1617 declare_clippy_lint! {
1618     /// ### What it does
1619     /// Warns when using `push_str`/`insert_str` with a single-character string literal
1620     /// where `push`/`insert` with a `char` would work fine.
1621     ///
1622     /// ### Why is this bad?
1623     /// It's less clear that we are pushing a single character.
1624     ///
1625     /// ### Example
1626     /// ```rust
1627     /// let mut string = String::new();
1628     /// string.insert_str(0, "R");
1629     /// string.push_str("R");
1630     /// ```
1631     /// Could be written as
1632     /// ```rust
1633     /// let mut string = String::new();
1634     /// string.insert(0, 'R');
1635     /// string.push('R');
1636     /// ```
1637     #[clippy::version = "1.49.0"]
1638     pub SINGLE_CHAR_ADD_STR,
1639     style,
1640     "`push_str()` or `insert_str()` used with a single-character string literal as parameter"
1641 }
1642
1643 declare_clippy_lint! {
1644     /// ### What it does
1645     /// As the counterpart to `or_fun_call`, this lint looks for unnecessary
1646     /// lazily evaluated closures on `Option` and `Result`.
1647     ///
1648     /// This lint suggests changing the following functions, when eager evaluation results in
1649     /// simpler code:
1650     ///  - `unwrap_or_else` to `unwrap_or`
1651     ///  - `and_then` to `and`
1652     ///  - `or_else` to `or`
1653     ///  - `get_or_insert_with` to `get_or_insert`
1654     ///  - `ok_or_else` to `ok_or`
1655     ///
1656     /// ### Why is this bad?
1657     /// Using eager evaluation is shorter and simpler in some cases.
1658     ///
1659     /// ### Known problems
1660     /// It is possible, but not recommended for `Deref` and `Index` to have
1661     /// side effects. Eagerly evaluating them can change the semantics of the program.
1662     ///
1663     /// ### Example
1664     /// ```rust
1665     /// // example code where clippy issues a warning
1666     /// let opt: Option<u32> = None;
1667     ///
1668     /// opt.unwrap_or_else(|| 42);
1669     /// ```
1670     /// Use instead:
1671     /// ```rust
1672     /// let opt: Option<u32> = None;
1673     ///
1674     /// opt.unwrap_or(42);
1675     /// ```
1676     #[clippy::version = "1.48.0"]
1677     pub UNNECESSARY_LAZY_EVALUATIONS,
1678     style,
1679     "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation"
1680 }
1681
1682 declare_clippy_lint! {
1683     /// ### What it does
1684     /// Checks for usage of `_.map(_).collect::<Result<(), _>()`.
1685     ///
1686     /// ### Why is this bad?
1687     /// Using `try_for_each` instead is more readable and idiomatic.
1688     ///
1689     /// ### Example
1690     /// ```rust
1691     /// (0..3).map(|t| Err(t)).collect::<Result<(), _>>();
1692     /// ```
1693     /// Use instead:
1694     /// ```rust
1695     /// (0..3).try_for_each(|t| Err(t));
1696     /// ```
1697     #[clippy::version = "1.49.0"]
1698     pub MAP_COLLECT_RESULT_UNIT,
1699     style,
1700     "using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`"
1701 }
1702
1703 declare_clippy_lint! {
1704     /// ### What it does
1705     /// Checks for `from_iter()` function calls on types that implement the `FromIterator`
1706     /// trait.
1707     ///
1708     /// ### Why is this bad?
1709     /// It is recommended style to use collect. See
1710     /// [FromIterator documentation](https://doc.rust-lang.org/std/iter/trait.FromIterator.html)
1711     ///
1712     /// ### Example
1713     /// ```rust
1714     /// use std::iter::FromIterator;
1715     ///
1716     /// let five_fives = std::iter::repeat(5).take(5);
1717     ///
1718     /// let v = Vec::from_iter(five_fives);
1719     ///
1720     /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
1721     /// ```
1722     /// Use instead:
1723     /// ```rust
1724     /// let five_fives = std::iter::repeat(5).take(5);
1725     ///
1726     /// let v: Vec<i32> = five_fives.collect();
1727     ///
1728     /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
1729     /// ```
1730     #[clippy::version = "1.49.0"]
1731     pub FROM_ITER_INSTEAD_OF_COLLECT,
1732     pedantic,
1733     "use `.collect()` instead of `::from_iter()`"
1734 }
1735
1736 declare_clippy_lint! {
1737     /// ### What it does
1738     /// Checks for usage of `inspect().for_each()`.
1739     ///
1740     /// ### Why is this bad?
1741     /// It is the same as performing the computation
1742     /// inside `inspect` at the beginning of the closure in `for_each`.
1743     ///
1744     /// ### Example
1745     /// ```rust
1746     /// [1,2,3,4,5].iter()
1747     /// .inspect(|&x| println!("inspect the number: {}", x))
1748     /// .for_each(|&x| {
1749     ///     assert!(x >= 0);
1750     /// });
1751     /// ```
1752     /// Can be written as
1753     /// ```rust
1754     /// [1,2,3,4,5].iter()
1755     /// .for_each(|&x| {
1756     ///     println!("inspect the number: {}", x);
1757     ///     assert!(x >= 0);
1758     /// });
1759     /// ```
1760     #[clippy::version = "1.51.0"]
1761     pub INSPECT_FOR_EACH,
1762     complexity,
1763     "using `.inspect().for_each()`, which can be replaced with `.for_each()`"
1764 }
1765
1766 declare_clippy_lint! {
1767     /// ### What it does
1768     /// Checks for usage of `filter_map(|x| x)`.
1769     ///
1770     /// ### Why is this bad?
1771     /// Readability, this can be written more concisely by using `flatten`.
1772     ///
1773     /// ### Example
1774     /// ```rust
1775     /// # let iter = vec![Some(1)].into_iter();
1776     /// iter.filter_map(|x| x);
1777     /// ```
1778     /// Use instead:
1779     /// ```rust
1780     /// # let iter = vec![Some(1)].into_iter();
1781     /// iter.flatten();
1782     /// ```
1783     #[clippy::version = "1.52.0"]
1784     pub FILTER_MAP_IDENTITY,
1785     complexity,
1786     "call to `filter_map` where `flatten` is sufficient"
1787 }
1788
1789 declare_clippy_lint! {
1790     /// ### What it does
1791     /// Checks for instances of `map(f)` where `f` is the identity function.
1792     ///
1793     /// ### Why is this bad?
1794     /// It can be written more concisely without the call to `map`.
1795     ///
1796     /// ### Example
1797     /// ```rust
1798     /// let x = [1, 2, 3];
1799     /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
1800     /// ```
1801     /// Use instead:
1802     /// ```rust
1803     /// let x = [1, 2, 3];
1804     /// let y: Vec<_> = x.iter().map(|x| 2*x).collect();
1805     /// ```
1806     #[clippy::version = "1.52.0"]
1807     pub MAP_IDENTITY,
1808     complexity,
1809     "using iterator.map(|x| x)"
1810 }
1811
1812 declare_clippy_lint! {
1813     /// ### What it does
1814     /// Checks for the use of `.bytes().nth()`.
1815     ///
1816     /// ### Why is this bad?
1817     /// `.as_bytes().get()` is more efficient and more
1818     /// readable.
1819     ///
1820     /// ### Example
1821     /// ```rust
1822     /// // Bad
1823     /// let _ = "Hello".bytes().nth(3);
1824     ///
1825     /// // Good
1826     /// let _ = "Hello".as_bytes().get(3);
1827     /// ```
1828     #[clippy::version = "1.52.0"]
1829     pub BYTES_NTH,
1830     style,
1831     "replace `.bytes().nth()` with `.as_bytes().get()`"
1832 }
1833
1834 declare_clippy_lint! {
1835     /// ### What it does
1836     /// Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer.
1837     ///
1838     /// ### Why is this bad?
1839     /// These methods do the same thing as `_.clone()` but may be confusing as
1840     /// to why we are calling `to_vec` on something that is already a `Vec` or calling `to_owned` on something that is already owned.
1841     ///
1842     /// ### Example
1843     /// ```rust
1844     /// let a = vec![1, 2, 3];
1845     /// let b = a.to_vec();
1846     /// let c = a.to_owned();
1847     /// ```
1848     /// Use instead:
1849     /// ```rust
1850     /// let a = vec![1, 2, 3];
1851     /// let b = a.clone();
1852     /// let c = a.clone();
1853     /// ```
1854     #[clippy::version = "1.52.0"]
1855     pub IMPLICIT_CLONE,
1856     pedantic,
1857     "implicitly cloning a value by invoking a function on its dereferenced type"
1858 }
1859
1860 declare_clippy_lint! {
1861     /// ### What it does
1862     /// Checks for the use of `.iter().count()`.
1863     ///
1864     /// ### Why is this bad?
1865     /// `.len()` is more efficient and more
1866     /// readable.
1867     ///
1868     /// ### Example
1869     /// ```rust
1870     /// // Bad
1871     /// let some_vec = vec![0, 1, 2, 3];
1872     /// let _ = some_vec.iter().count();
1873     /// let _ = &some_vec[..].iter().count();
1874     ///
1875     /// // Good
1876     /// let some_vec = vec![0, 1, 2, 3];
1877     /// let _ = some_vec.len();
1878     /// let _ = &some_vec[..].len();
1879     /// ```
1880     #[clippy::version = "1.52.0"]
1881     pub ITER_COUNT,
1882     complexity,
1883     "replace `.iter().count()` with `.len()`"
1884 }
1885
1886 declare_clippy_lint! {
1887     /// ### What it does
1888     /// Checks for calls to [`splitn`]
1889     /// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
1890     /// related functions with either zero or one splits.
1891     ///
1892     /// ### Why is this bad?
1893     /// These calls don't actually split the value and are
1894     /// likely to be intended as a different number.
1895     ///
1896     /// ### Example
1897     /// ```rust
1898     /// // Bad
1899     /// let s = "";
1900     /// for x in s.splitn(1, ":") {
1901     ///     // use x
1902     /// }
1903     ///
1904     /// // Good
1905     /// let s = "";
1906     /// for x in s.splitn(2, ":") {
1907     ///     // use x
1908     /// }
1909     /// ```
1910     #[clippy::version = "1.54.0"]
1911     pub SUSPICIOUS_SPLITN,
1912     correctness,
1913     "checks for `.splitn(0, ..)` and `.splitn(1, ..)`"
1914 }
1915
1916 declare_clippy_lint! {
1917     /// ### What it does
1918     /// Checks for manual implementations of `str::repeat`
1919     ///
1920     /// ### Why is this bad?
1921     /// These are both harder to read, as well as less performant.
1922     ///
1923     /// ### Example
1924     /// ```rust
1925     /// // Bad
1926     /// let x: String = std::iter::repeat('x').take(10).collect();
1927     ///
1928     /// // Good
1929     /// let x: String = "x".repeat(10);
1930     /// ```
1931     #[clippy::version = "1.54.0"]
1932     pub MANUAL_STR_REPEAT,
1933     perf,
1934     "manual implementation of `str::repeat`"
1935 }
1936
1937 declare_clippy_lint! {
1938     /// ### What it does
1939     /// Checks for usages of `str::splitn(2, _)`
1940     ///
1941     /// ### Why is this bad?
1942     /// `split_once` is both clearer in intent and slightly more efficient.
1943     ///
1944     /// ### Example
1945     /// ```rust,ignore
1946     /// // Bad
1947     ///  let (key, value) = _.splitn(2, '=').next_tuple()?;
1948     ///  let value = _.splitn(2, '=').nth(1)?;
1949     ///
1950     /// // Good
1951     /// let (key, value) = _.split_once('=')?;
1952     /// let value = _.split_once('=')?.1;
1953     /// ```
1954     #[clippy::version = "1.57.0"]
1955     pub MANUAL_SPLIT_ONCE,
1956     complexity,
1957     "replace `.splitn(2, pat)` with `.split_once(pat)`"
1958 }
1959
1960 declare_clippy_lint! {
1961     /// ### What it does
1962     /// Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same.
1963     /// ### Why is this bad?
1964     /// The function `split` is simpler and there is no performance difference in these cases, considering
1965     /// that both functions return a lazy iterator.
1966     /// ### Example
1967     /// ```rust
1968     /// // Bad
1969     /// let str = "key=value=add";
1970     /// let _ = str.splitn(3, '=').next().unwrap();
1971     /// ```
1972     /// Use instead:
1973     /// ```rust
1974     /// // Good
1975     /// let str = "key=value=add";
1976     /// let _ = str.split('=').next().unwrap();
1977     /// ```
1978     #[clippy::version = "1.58.0"]
1979     pub NEEDLESS_SPLITN,
1980     complexity,
1981     "usages of `str::splitn` that can be replaced with `str::split`"
1982 }
1983
1984 declare_clippy_lint! {
1985     /// ### What it does
1986     /// Checks for unnecessary calls to [`ToOwned::to_owned`](https://doc.rust-lang.org/std/borrow/trait.ToOwned.html#tymethod.to_owned)
1987     /// and other `to_owned`-like functions.
1988     ///
1989     /// ### Why is this bad?
1990     /// The unnecessary calls result in useless allocations.
1991     ///
1992     /// ### Known problems
1993     /// `unnecessary_to_owned` can falsely trigger if `IntoIterator::into_iter` is applied to an
1994     /// owned copy of a resource and the resource is later used mutably. See
1995     /// [#8148](https://github.com/rust-lang/rust-clippy/issues/8148).
1996     ///
1997     /// ### Example
1998     /// ```rust
1999     /// let path = std::path::Path::new("x");
2000     /// foo(&path.to_string_lossy().to_string());
2001     /// fn foo(s: &str) {}
2002     /// ```
2003     /// Use instead:
2004     /// ```rust
2005     /// let path = std::path::Path::new("x");
2006     /// foo(&path.to_string_lossy());
2007     /// fn foo(s: &str) {}
2008     /// ```
2009     #[clippy::version = "1.58.0"]
2010     pub UNNECESSARY_TO_OWNED,
2011     perf,
2012     "unnecessary calls to `to_owned`-like functions"
2013 }
2014
2015 pub struct Methods {
2016     avoid_breaking_exported_api: bool,
2017     msrv: Option<RustcVersion>,
2018 }
2019
2020 impl Methods {
2021     #[must_use]
2022     pub fn new(avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>) -> Self {
2023         Self {
2024             avoid_breaking_exported_api,
2025             msrv,
2026         }
2027     }
2028 }
2029
2030 impl_lint_pass!(Methods => [
2031     UNWRAP_USED,
2032     EXPECT_USED,
2033     SHOULD_IMPLEMENT_TRAIT,
2034     WRONG_SELF_CONVENTION,
2035     OK_EXPECT,
2036     UNWRAP_OR_ELSE_DEFAULT,
2037     MAP_UNWRAP_OR,
2038     RESULT_MAP_OR_INTO_OPTION,
2039     OPTION_MAP_OR_NONE,
2040     BIND_INSTEAD_OF_MAP,
2041     OR_FUN_CALL,
2042     EXPECT_FUN_CALL,
2043     CHARS_NEXT_CMP,
2044     CHARS_LAST_CMP,
2045     CLONE_ON_COPY,
2046     CLONE_ON_REF_PTR,
2047     CLONE_DOUBLE_REF,
2048     ITER_OVEREAGER_CLONED,
2049     CLONED_INSTEAD_OF_COPIED,
2050     FLAT_MAP_OPTION,
2051     INEFFICIENT_TO_STRING,
2052     NEW_RET_NO_SELF,
2053     SINGLE_CHAR_PATTERN,
2054     SINGLE_CHAR_ADD_STR,
2055     SEARCH_IS_SOME,
2056     FILTER_NEXT,
2057     SKIP_WHILE_NEXT,
2058     FILTER_MAP_IDENTITY,
2059     MAP_IDENTITY,
2060     MANUAL_FILTER_MAP,
2061     MANUAL_FIND_MAP,
2062     OPTION_FILTER_MAP,
2063     FILTER_MAP_NEXT,
2064     FLAT_MAP_IDENTITY,
2065     MAP_FLATTEN,
2066     ITERATOR_STEP_BY_ZERO,
2067     ITER_NEXT_SLICE,
2068     ITER_COUNT,
2069     ITER_NTH,
2070     ITER_NTH_ZERO,
2071     BYTES_NTH,
2072     ITER_SKIP_NEXT,
2073     GET_UNWRAP,
2074     STRING_EXTEND_CHARS,
2075     ITER_CLONED_COLLECT,
2076     ITER_WITH_DRAIN,
2077     USELESS_ASREF,
2078     UNNECESSARY_FOLD,
2079     UNNECESSARY_FILTER_MAP,
2080     UNNECESSARY_FIND_MAP,
2081     INTO_ITER_ON_REF,
2082     SUSPICIOUS_MAP,
2083     UNINIT_ASSUMED_INIT,
2084     MANUAL_SATURATING_ARITHMETIC,
2085     ZST_OFFSET,
2086     FILETYPE_IS_FILE,
2087     OPTION_AS_REF_DEREF,
2088     UNNECESSARY_LAZY_EVALUATIONS,
2089     MAP_COLLECT_RESULT_UNIT,
2090     FROM_ITER_INSTEAD_OF_COLLECT,
2091     INSPECT_FOR_EACH,
2092     IMPLICIT_CLONE,
2093     SUSPICIOUS_SPLITN,
2094     MANUAL_STR_REPEAT,
2095     EXTEND_WITH_DRAIN,
2096     MANUAL_SPLIT_ONCE,
2097     NEEDLESS_SPLITN,
2098     UNNECESSARY_TO_OWNED,
2099 ]);
2100
2101 /// Extracts a method call name, args, and `Span` of the method name.
2102 fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx str, &'tcx [hir::Expr<'tcx>], Span)> {
2103     if let ExprKind::MethodCall(path, args, _) = recv.kind {
2104         if !args.iter().any(|e| e.span.from_expansion()) {
2105             let name = path.ident.name.as_str();
2106             return Some((name, args, path.ident.span));
2107         }
2108     }
2109     None
2110 }
2111
2112 impl<'tcx> LateLintPass<'tcx> for Methods {
2113     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
2114         if expr.span.from_expansion() {
2115             return;
2116         }
2117
2118         check_methods(cx, expr, self.msrv.as_ref());
2119
2120         match expr.kind {
2121             hir::ExprKind::Call(func, args) => {
2122                 from_iter_instead_of_collect::check(cx, expr, args, func);
2123             },
2124             hir::ExprKind::MethodCall(method_call, args, _) => {
2125                 let method_span = method_call.ident.span;
2126                 or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args);
2127                 expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args);
2128                 clone_on_copy::check(cx, expr, method_call.ident.name, args);
2129                 clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args);
2130                 inefficient_to_string::check(cx, expr, method_call.ident.name, args);
2131                 single_char_add_str::check(cx, expr, args);
2132                 into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, args);
2133                 single_char_pattern::check(cx, expr, method_call.ident.name, args);
2134                 unnecessary_to_owned::check(cx, expr, method_call.ident.name, args);
2135             },
2136             hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
2137                 let mut info = BinaryExprInfo {
2138                     expr,
2139                     chain: lhs,
2140                     other: rhs,
2141                     eq: op.node == hir::BinOpKind::Eq,
2142                 };
2143                 lint_binary_expr_with_method_call(cx, &mut info);
2144             },
2145             _ => (),
2146         }
2147     }
2148
2149     #[allow(clippy::too_many_lines)]
2150     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
2151         if in_external_macro(cx.sess(), impl_item.span) {
2152             return;
2153         }
2154         let name = impl_item.ident.name.as_str();
2155         let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
2156         let item = cx.tcx.hir().expect_item(parent);
2157         let self_ty = cx.tcx.type_of(item.def_id);
2158
2159         let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
2160         if_chain! {
2161             if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
2162             if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next();
2163
2164             let method_sig = cx.tcx.fn_sig(impl_item.def_id);
2165             let method_sig = cx.tcx.erase_late_bound_regions(method_sig);
2166
2167             let first_arg_ty = method_sig.inputs().iter().next();
2168
2169             // check conventions w.r.t. conversion method names and predicates
2170             if let Some(first_arg_ty) = first_arg_ty;
2171
2172             then {
2173                 // if this impl block implements a trait, lint in trait definition instead
2174                 if !implements_trait && cx.access_levels.is_exported(impl_item.def_id) {
2175                     // check missing trait implementations
2176                     for method_config in &TRAIT_METHODS {
2177                         if name == method_config.method_name &&
2178                             sig.decl.inputs.len() == method_config.param_count &&
2179                             method_config.output_type.matches(&sig.decl.output) &&
2180                             method_config.self_kind.matches(cx, self_ty, *first_arg_ty) &&
2181                             fn_header_equals(method_config.fn_header, sig.header) &&
2182                             method_config.lifetime_param_cond(impl_item)
2183                         {
2184                             span_lint_and_help(
2185                                 cx,
2186                                 SHOULD_IMPLEMENT_TRAIT,
2187                                 impl_item.span,
2188                                 &format!(
2189                                     "method `{}` can be confused for the standard trait method `{}::{}`",
2190                                     method_config.method_name,
2191                                     method_config.trait_name,
2192                                     method_config.method_name
2193                                 ),
2194                                 None,
2195                                 &format!(
2196                                     "consider implementing the trait `{}` or choosing a less ambiguous method name",
2197                                     method_config.trait_name
2198                                 )
2199                             );
2200                         }
2201                     }
2202                 }
2203
2204                 if sig.decl.implicit_self.has_implicit_self()
2205                     && !(self.avoid_breaking_exported_api
2206                         && cx.access_levels.is_exported(impl_item.def_id))
2207                 {
2208                     wrong_self_convention::check(
2209                         cx,
2210                         name,
2211                         self_ty,
2212                         *first_arg_ty,
2213                         first_arg.pat.span,
2214                         implements_trait,
2215                         false
2216                     );
2217                 }
2218             }
2219         }
2220
2221         // if this impl block implements a trait, lint in trait definition instead
2222         if implements_trait {
2223             return;
2224         }
2225
2226         if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
2227             let ret_ty = return_ty(cx, impl_item.hir_id());
2228
2229             // walk the return type and check for Self (this does not check associated types)
2230             if let Some(self_adt) = self_ty.ty_adt_def() {
2231                 if contains_adt_constructor(ret_ty, self_adt) {
2232                     return;
2233                 }
2234             } else if contains_ty(ret_ty, self_ty) {
2235                 return;
2236             }
2237
2238             // if return type is impl trait, check the associated types
2239             if let ty::Opaque(def_id, _) = *ret_ty.kind() {
2240                 // one of the associated types must be Self
2241                 for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
2242                     if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
2243                         let assoc_ty = match projection_predicate.term {
2244                             ty::Term::Ty(ty) => ty,
2245                             ty::Term::Const(_c) => continue,
2246                         };
2247                         // walk the associated type and check for Self
2248                         if let Some(self_adt) = self_ty.ty_adt_def() {
2249                             if contains_adt_constructor(assoc_ty, self_adt) {
2250                                 return;
2251                             }
2252                         } else if contains_ty(assoc_ty, self_ty) {
2253                             return;
2254                         }
2255                     }
2256                 }
2257             }
2258
2259             if name == "new" && ret_ty != self_ty {
2260                 span_lint(
2261                     cx,
2262                     NEW_RET_NO_SELF,
2263                     impl_item.span,
2264                     "methods called `new` usually return `Self`",
2265                 );
2266             }
2267         }
2268     }
2269
2270     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
2271         if in_external_macro(cx.tcx.sess, item.span) {
2272             return;
2273         }
2274
2275         if_chain! {
2276             if let TraitItemKind::Fn(ref sig, _) = item.kind;
2277             if sig.decl.implicit_self.has_implicit_self();
2278             if let Some(first_arg_ty) = sig.decl.inputs.iter().next();
2279
2280             then {
2281                 let first_arg_span = first_arg_ty.span;
2282                 let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
2283                 let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
2284                 wrong_self_convention::check(
2285                     cx,
2286                     item.ident.name.as_str(),
2287                     self_ty,
2288                     first_arg_ty,
2289                     first_arg_span,
2290                     false,
2291                     true
2292                 );
2293             }
2294         }
2295
2296         if_chain! {
2297             if item.ident.name == sym::new;
2298             if let TraitItemKind::Fn(_, _) = item.kind;
2299             let ret_ty = return_ty(cx, item.hir_id());
2300             let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
2301             if !contains_ty(ret_ty, self_ty);
2302
2303             then {
2304                 span_lint(
2305                     cx,
2306                     NEW_RET_NO_SELF,
2307                     item.span,
2308                     "methods called `new` usually return `Self`",
2309                 );
2310             }
2311         }
2312     }
2313
2314     extract_msrv_attr!(LateContext);
2315 }
2316
2317 #[allow(clippy::too_many_lines)]
2318 fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Option<&RustcVersion>) {
2319     if let Some((name, [recv, args @ ..], span)) = method_call(expr) {
2320         match (name, args) {
2321             ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
2322                 zst_offset::check(cx, expr, recv);
2323             },
2324             ("and_then", [arg]) => {
2325                 let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
2326                 let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, recv, arg);
2327                 if !biom_option_linted && !biom_result_linted {
2328                     unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
2329                 }
2330             },
2331             ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv),
2332             ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv),
2333             ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
2334             ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, msrv),
2335             ("collect", []) => match method_call(recv) {
2336                 Some((name @ ("cloned" | "copied"), [recv2], _)) => {
2337                     iter_cloned_collect::check(cx, name, expr, recv2);
2338                 },
2339                 Some(("map", [m_recv, m_arg], _)) => {
2340                     map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
2341                 },
2342                 Some(("take", [take_self_arg, take_arg], _)) => {
2343                     if meets_msrv(msrv, &msrvs::STR_REPEAT) {
2344                         manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
2345                     }
2346                 },
2347                 _ => {},
2348             },
2349             (name @ "count", args @ []) => match method_call(recv) {
2350                 Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv2, name, args),
2351                 Some((name2 @ ("into_iter" | "iter" | "iter_mut"), [recv2], _)) => {
2352                     iter_count::check(cx, expr, recv2, name2);
2353                 },
2354                 Some(("map", [_, arg], _)) => suspicious_map::check(cx, expr, recv, arg),
2355                 _ => {},
2356             },
2357             ("drain", [arg]) => {
2358                 iter_with_drain::check(cx, expr, recv, span, arg);
2359             },
2360             ("expect", [_]) => match method_call(recv) {
2361                 Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
2362                 _ => expect_used::check(cx, expr, recv),
2363             },
2364             ("extend", [arg]) => {
2365                 string_extend_chars::check(cx, expr, recv, arg);
2366                 extend_with_drain::check(cx, expr, recv, arg);
2367             },
2368             ("filter_map", [arg]) => {
2369                 unnecessary_filter_map::check(cx, expr, arg, name);
2370                 filter_map_identity::check(cx, expr, arg, span);
2371             },
2372             ("find_map", [arg]) => {
2373                 unnecessary_filter_map::check(cx, expr, arg, name);
2374             },
2375             ("flat_map", [arg]) => {
2376                 flat_map_identity::check(cx, expr, arg, span);
2377                 flat_map_option::check(cx, expr, arg, span);
2378             },
2379             (name @ "flatten", args @ []) => match method_call(recv) {
2380                 Some(("map", [recv, map_arg], _)) => map_flatten::check(cx, expr, recv, map_arg),
2381                 Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv2, name, args),
2382                 _ => {},
2383             },
2384             ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span),
2385             ("for_each", [_]) => {
2386                 if let Some(("inspect", [_, _], span2)) = method_call(recv) {
2387                     inspect_for_each::check(cx, expr, span2);
2388                 }
2389             },
2390             ("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"),
2391             ("is_file", []) => filetype_is_file::check(cx, expr, recv),
2392             ("is_none", []) => check_is_some_is_none(cx, expr, recv, false),
2393             ("is_some", []) => check_is_some_is_none(cx, expr, recv, true),
2394             ("last", args @ []) | ("skip", args @ [_]) => {
2395                 if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) {
2396                     if let ("cloned", []) = (name2, args2) {
2397                         iter_overeager_cloned::check(cx, expr, recv2, name, args);
2398                     }
2399                 }
2400             },
2401             ("map", [m_arg]) => {
2402                 if let Some((name, [recv2, args @ ..], span2)) = method_call(recv) {
2403                     match (name, args) {
2404                         ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv),
2405                         ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, msrv),
2406                         ("filter", [f_arg]) => {
2407                             filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false);
2408                         },
2409                         ("find", [f_arg]) => filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, true),
2410                         _ => {},
2411                     }
2412                 }
2413                 map_identity::check(cx, expr, recv, m_arg, span);
2414             },
2415             ("map_or", [def, map]) => option_map_or_none::check(cx, expr, recv, def, map),
2416             (name @ "next", args @ []) => {
2417                 if let Some((name2, [recv2, args2 @ ..], _)) = method_call(recv) {
2418                     match (name2, args2) {
2419                         ("cloned", []) => iter_overeager_cloned::check(cx, expr, recv2, name, args),
2420                         ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
2421                         ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, msrv),
2422                         ("iter", []) => iter_next_slice::check(cx, expr, recv2),
2423                         ("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg),
2424                         ("skip_while", [_]) => skip_while_next::check(cx, expr),
2425                         _ => {},
2426                     }
2427                 }
2428             },
2429             ("nth", args @ [n_arg]) => match method_call(recv) {
2430                 Some(("bytes", [recv2], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
2431                 Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv2, name, args),
2432                 Some(("iter", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
2433                 Some(("iter_mut", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
2434                 _ => iter_nth_zero::check(cx, expr, recv, n_arg),
2435             },
2436             ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
2437             ("or_else", [arg]) => {
2438                 if !bind_instead_of_map::ResultOrElseErrInfo::check(cx, expr, recv, arg) {
2439                     unnecessary_lazy_eval::check(cx, expr, recv, arg, "or");
2440                 }
2441             },
2442             ("splitn" | "rsplitn", [count_arg, pat_arg]) => {
2443                 if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
2444                     suspicious_splitn::check(cx, name, expr, recv, count);
2445                     if count == 2 && meets_msrv(msrv, &msrvs::STR_SPLIT_ONCE) {
2446                         str_splitn::check_manual_split_once(cx, name, expr, recv, pat_arg);
2447                     }
2448                     if count >= 2 {
2449                         str_splitn::check_needless_splitn(cx, name, expr, recv, pat_arg, count);
2450                     }
2451                 }
2452             },
2453             ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
2454                 if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
2455                     suspicious_splitn::check(cx, name, expr, recv, count);
2456                 }
2457             },
2458             ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
2459             ("take", args @ [_arg]) => {
2460                 if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) {
2461                     if let ("cloned", []) = (name2, args2) {
2462                         iter_overeager_cloned::check(cx, expr, recv2, name, args);
2463                     }
2464                 }
2465             },
2466             ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
2467                 implicit_clone::check(cx, name, expr, recv);
2468             },
2469             ("unwrap", []) => {
2470                 match method_call(recv) {
2471                     Some(("get", [recv, get_arg], _)) => {
2472                         get_unwrap::check(cx, expr, recv, get_arg, false);
2473                     },
2474                     Some(("get_mut", [recv, get_arg], _)) => {
2475                         get_unwrap::check(cx, expr, recv, get_arg, true);
2476                     },
2477                     _ => {},
2478                 }
2479                 unwrap_used::check(cx, expr, recv);
2480             },
2481             ("unwrap_or", [u_arg]) => match method_call(recv) {
2482                 Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => {
2483                     manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
2484                 },
2485                 Some(("map", [m_recv, m_arg], span)) => {
2486                     option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
2487                 },
2488                 _ => {},
2489             },
2490             ("unwrap_or_else", [u_arg]) => match method_call(recv) {
2491                 Some(("map", [recv, map_arg], _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, msrv) => {},
2492                 _ => {
2493                     unwrap_or_else_default::check(cx, expr, recv, u_arg);
2494                     unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
2495                 },
2496             },
2497             _ => {},
2498         }
2499     }
2500 }
2501
2502 fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
2503     if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call(recv) {
2504         search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span);
2505     }
2506 }
2507
2508 /// Used for `lint_binary_expr_with_method_call`.
2509 #[derive(Copy, Clone)]
2510 struct BinaryExprInfo<'a> {
2511     expr: &'a hir::Expr<'a>,
2512     chain: &'a hir::Expr<'a>,
2513     other: &'a hir::Expr<'a>,
2514     eq: bool,
2515 }
2516
2517 /// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
2518 fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExprInfo<'_>) {
2519     macro_rules! lint_with_both_lhs_and_rhs {
2520         ($func:expr, $cx:expr, $info:ident) => {
2521             if !$func($cx, $info) {
2522                 ::std::mem::swap(&mut $info.chain, &mut $info.other);
2523                 if $func($cx, $info) {
2524                     return;
2525                 }
2526             }
2527         };
2528     }
2529
2530     lint_with_both_lhs_and_rhs!(chars_next_cmp::check, cx, info);
2531     lint_with_both_lhs_and_rhs!(chars_last_cmp::check, cx, info);
2532     lint_with_both_lhs_and_rhs!(chars_next_cmp_with_unwrap::check, cx, info);
2533     lint_with_both_lhs_and_rhs!(chars_last_cmp_with_unwrap::check, cx, info);
2534 }
2535
2536 const FN_HEADER: hir::FnHeader = hir::FnHeader {
2537     unsafety: hir::Unsafety::Normal,
2538     constness: hir::Constness::NotConst,
2539     asyncness: hir::IsAsync::NotAsync,
2540     abi: rustc_target::spec::abi::Abi::Rust,
2541 };
2542
2543 struct ShouldImplTraitCase {
2544     trait_name: &'static str,
2545     method_name: &'static str,
2546     param_count: usize,
2547     fn_header: hir::FnHeader,
2548     // implicit self kind expected (none, self, &self, ...)
2549     self_kind: SelfKind,
2550     // checks against the output type
2551     output_type: OutType,
2552     // certain methods with explicit lifetimes can't implement the equivalent trait method
2553     lint_explicit_lifetime: bool,
2554 }
2555 impl ShouldImplTraitCase {
2556     const fn new(
2557         trait_name: &'static str,
2558         method_name: &'static str,
2559         param_count: usize,
2560         fn_header: hir::FnHeader,
2561         self_kind: SelfKind,
2562         output_type: OutType,
2563         lint_explicit_lifetime: bool,
2564     ) -> ShouldImplTraitCase {
2565         ShouldImplTraitCase {
2566             trait_name,
2567             method_name,
2568             param_count,
2569             fn_header,
2570             self_kind,
2571             output_type,
2572             lint_explicit_lifetime,
2573         }
2574     }
2575
2576     fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
2577         self.lint_explicit_lifetime
2578             || !impl_item.generics.params.iter().any(|p| {
2579                 matches!(
2580                     p.kind,
2581                     hir::GenericParamKind::Lifetime {
2582                         kind: hir::LifetimeParamKind::Explicit
2583                     }
2584                 )
2585             })
2586     }
2587 }
2588
2589 #[rustfmt::skip]
2590 const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
2591     ShouldImplTraitCase::new("std::ops::Add", "add",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2592     ShouldImplTraitCase::new("std::convert::AsMut", "as_mut",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
2593     ShouldImplTraitCase::new("std::convert::AsRef", "as_ref",  1,  FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
2594     ShouldImplTraitCase::new("std::ops::BitAnd", "bitand",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2595     ShouldImplTraitCase::new("std::ops::BitOr", "bitor",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2596     ShouldImplTraitCase::new("std::ops::BitXor", "bitxor",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2597     ShouldImplTraitCase::new("std::borrow::Borrow", "borrow",  1,  FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
2598     ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
2599     ShouldImplTraitCase::new("std::clone::Clone", "clone",  1,  FN_HEADER,  SelfKind::Ref,  OutType::Any, true),
2600     ShouldImplTraitCase::new("std::cmp::Ord", "cmp",  2,  FN_HEADER,  SelfKind::Ref,  OutType::Any, true),
2601     // FIXME: default doesn't work
2602     ShouldImplTraitCase::new("std::default::Default", "default",  0,  FN_HEADER,  SelfKind::No,  OutType::Any, true),
2603     ShouldImplTraitCase::new("std::ops::Deref", "deref",  1,  FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
2604     ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
2605     ShouldImplTraitCase::new("std::ops::Div", "div",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2606     ShouldImplTraitCase::new("std::ops::Drop", "drop",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Unit, true),
2607     ShouldImplTraitCase::new("std::cmp::PartialEq", "eq",  2,  FN_HEADER,  SelfKind::Ref,  OutType::Bool, true),
2608     ShouldImplTraitCase::new("std::iter::FromIterator", "from_iter",  1,  FN_HEADER,  SelfKind::No,  OutType::Any, true),
2609     ShouldImplTraitCase::new("std::str::FromStr", "from_str",  1,  FN_HEADER,  SelfKind::No,  OutType::Any, true),
2610     ShouldImplTraitCase::new("std::hash::Hash", "hash",  2,  FN_HEADER,  SelfKind::Ref,  OutType::Unit, true),
2611     ShouldImplTraitCase::new("std::ops::Index", "index",  2,  FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
2612     ShouldImplTraitCase::new("std::ops::IndexMut", "index_mut",  2,  FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
2613     ShouldImplTraitCase::new("std::iter::IntoIterator", "into_iter",  1,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2614     ShouldImplTraitCase::new("std::ops::Mul", "mul",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2615     ShouldImplTraitCase::new("std::ops::Neg", "neg",  1,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2616     ShouldImplTraitCase::new("std::iter::Iterator", "next",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Any, false),
2617     ShouldImplTraitCase::new("std::ops::Not", "not",  1,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2618     ShouldImplTraitCase::new("std::ops::Rem", "rem",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2619     ShouldImplTraitCase::new("std::ops::Shl", "shl",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2620     ShouldImplTraitCase::new("std::ops::Shr", "shr",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2621     ShouldImplTraitCase::new("std::ops::Sub", "sub",  2,  FN_HEADER,  SelfKind::Value,  OutType::Any, true),
2622 ];
2623
2624 #[derive(Clone, Copy, PartialEq, Debug)]
2625 enum SelfKind {
2626     Value,
2627     Ref,
2628     RefMut,
2629     No,
2630 }
2631
2632 impl SelfKind {
2633     fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
2634         fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'_>, ty: Ty<'_>) -> bool {
2635             if ty == parent_ty {
2636                 true
2637             } else if ty.is_box() {
2638                 ty.boxed_ty() == parent_ty
2639             } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
2640                 if let ty::Adt(_, substs) = ty.kind() {
2641                     substs.types().next().map_or(false, |t| t == parent_ty)
2642                 } else {
2643                     false
2644                 }
2645             } else {
2646                 false
2647             }
2648         }
2649
2650         fn matches_ref<'a>(cx: &LateContext<'a>, mutability: hir::Mutability, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
2651             if let ty::Ref(_, t, m) = *ty.kind() {
2652                 return m == mutability && t == parent_ty;
2653             }
2654
2655             let trait_path = match mutability {
2656                 hir::Mutability::Not => &paths::ASREF_TRAIT,
2657                 hir::Mutability::Mut => &paths::ASMUT_TRAIT,
2658             };
2659
2660             let trait_def_id = match get_trait_def_id(cx, trait_path) {
2661                 Some(did) => did,
2662                 None => return false,
2663             };
2664             implements_trait(cx, ty, trait_def_id, &[parent_ty.into()])
2665         }
2666
2667         fn matches_none<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
2668             !matches_value(cx, parent_ty, ty)
2669                 && !matches_ref(cx, hir::Mutability::Not, parent_ty, ty)
2670                 && !matches_ref(cx, hir::Mutability::Mut, parent_ty, ty)
2671         }
2672
2673         match self {
2674             Self::Value => matches_value(cx, parent_ty, ty),
2675             Self::Ref => matches_ref(cx, hir::Mutability::Not, parent_ty, ty) || ty == parent_ty && is_copy(cx, ty),
2676             Self::RefMut => matches_ref(cx, hir::Mutability::Mut, parent_ty, ty),
2677             Self::No => matches_none(cx, parent_ty, ty),
2678         }
2679     }
2680
2681     #[must_use]
2682     fn description(self) -> &'static str {
2683         match self {
2684             Self::Value => "`self` by value",
2685             Self::Ref => "`self` by reference",
2686             Self::RefMut => "`self` by mutable reference",
2687             Self::No => "no `self`",
2688         }
2689     }
2690 }
2691
2692 #[derive(Clone, Copy)]
2693 enum OutType {
2694     Unit,
2695     Bool,
2696     Any,
2697     Ref,
2698 }
2699
2700 impl OutType {
2701     fn matches(self, ty: &hir::FnRetTy<'_>) -> bool {
2702         let is_unit = |ty: &hir::Ty<'_>| matches!(ty.kind, hir::TyKind::Tup(&[]));
2703         match (self, ty) {
2704             (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true,
2705             (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true,
2706             (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true,
2707             (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true,
2708             (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)),
2709             _ => false,
2710         }
2711     }
2712 }
2713
2714 fn is_bool(ty: &hir::Ty<'_>) -> bool {
2715     if let hir::TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
2716         matches!(path.res, Res::PrimTy(PrimTy::Bool))
2717     } else {
2718         false
2719     }
2720 }
2721
2722 fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool {
2723     expected.constness == actual.constness
2724         && expected.unsafety == actual.unsafety
2725         && expected.asyncness == actual.asyncness
2726 }