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