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