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