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