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