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