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