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