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