]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/types.rs
Merge pull request #3336 from HMPerson1/clone_on_copy_deref
[rust.git] / clippy_lints / src / types.rs
1 // Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10
11 #![allow(clippy::default_hash_types)]
12
13 use crate::consts::{constant, Constant};
14 use crate::reexport::*;
15 use crate::rustc::hir;
16 use crate::rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
17 use crate::rustc::hir::*;
18 use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
19 use crate::rustc::ty::layout::LayoutOf;
20 use crate::rustc::ty::{self, Ty, TyCtxt, TypeckTables};
21 use crate::rustc::{declare_tool_lint, lint_array};
22 use crate::rustc_errors::Applicability;
23 use crate::rustc_target::spec::abi::Abi;
24 use crate::rustc_typeck::hir_ty_to_ty;
25 use crate::syntax::ast::{FloatTy, IntTy, UintTy};
26 use crate::syntax::errors::DiagnosticBuilder;
27 use crate::syntax::source_map::Span;
28 use crate::utils::paths;
29 use crate::utils::{
30     clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
31     match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt,
32     snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
33 };
34 use if_chain::if_chain;
35 use std::borrow::Cow;
36 use std::cmp::Ordering;
37 use std::collections::BTreeMap;
38
39 /// Handles all the linting of funky types
40 pub struct TypePass;
41
42 /// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
43 ///
44 /// **Why is this bad?** `Vec` already keeps its contents in a separate area on
45 /// the heap. So if you `Box` it, you just add another level of indirection
46 /// without any benefit whatsoever.
47 ///
48 /// **Known problems:** None.
49 ///
50 /// **Example:**
51 /// ```rust
52 /// struct X {
53 ///     values: Box<Vec<Foo>>,
54 /// }
55 /// ```
56 ///
57 /// Better:
58 ///
59 /// ```rust
60 /// struct X {
61 ///     values: Vec<Foo>,
62 /// }
63 /// ```
64 declare_clippy_lint! {
65     pub BOX_VEC,
66     perf,
67     "usage of `Box<Vec<T>>`, vector elements are already on the heap"
68 }
69
70 /// **What it does:** Checks for use of `Option<Option<_>>` in function signatures and type
71 /// definitions
72 ///
73 /// **Why is this bad?** `Option<_>` represents an optional value. `Option<Option<_>>`
74 /// represents an optional optional value which is logically the same thing as an optional
75 /// value but has an unneeded extra level of wrapping.
76 ///
77 /// **Known problems:** None.
78 ///
79 /// **Example**
80 /// ```rust
81 /// fn x() -> Option<Option<u32>> {
82 ///     None
83 /// }
84 declare_clippy_lint! {
85     pub OPTION_OPTION,
86     complexity,
87     "usage of `Option<Option<T>>`"
88 }
89
90 /// **What it does:** Checks for usage of any `LinkedList`, suggesting to use a
91 /// `Vec` or a `VecDeque` (formerly called `RingBuf`).
92 ///
93 /// **Why is this bad?** Gankro says:
94 ///
95 /// > The TL;DR of `LinkedList` is that it's built on a massive amount of
96 /// pointers and indirection.
97 /// > It wastes memory, it has terrible cache locality, and is all-around slow.
98 /// `RingBuf`, while
99 /// > "only" amortized for push/pop, should be faster in the general case for
100 /// almost every possible
101 /// > workload, and isn't even amortized at all if you can predict the capacity
102 /// you need.
103 /// >
104 /// > `LinkedList`s are only really good if you're doing a lot of merging or
105 /// splitting of lists.
106 /// > This is because they can just mangle some pointers instead of actually
107 /// copying the data. Even
108 /// > if you're doing a lot of insertion in the middle of the list, `RingBuf`
109 /// can still be better
110 /// > because of how expensive it is to seek to the middle of a `LinkedList`.
111 ///
112 /// **Known problems:** False positives – the instances where using a
113 /// `LinkedList` makes sense are few and far between, but they can still happen.
114 ///
115 /// **Example:**
116 /// ```rust
117 /// let x = LinkedList::new();
118 /// ```
119 declare_clippy_lint! {
120     pub LINKEDLIST,
121     pedantic,
122     "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque"
123 }
124
125 /// **What it does:** Checks for use of `&Box<T>` anywhere in the code.
126 ///
127 /// **Why is this bad?** Any `&Box<T>` can also be a `&T`, which is more
128 /// general.
129 ///
130 /// **Known problems:** None.
131 ///
132 /// **Example:**
133 /// ```rust
134 /// fn foo(bar: &Box<T>) { ... }
135 /// ```
136 ///
137 /// Better:
138 ///
139 /// ```rust
140 /// fn foo(bar: &T) { ... }
141 /// ```
142 declare_clippy_lint! {
143     pub BORROWED_BOX,
144     complexity,
145     "a borrow of a boxed type"
146 }
147
148 impl LintPass for TypePass {
149     fn get_lints(&self) -> LintArray {
150         lint_array!(BOX_VEC, OPTION_OPTION, LINKEDLIST, BORROWED_BOX)
151     }
152 }
153
154 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
155     fn check_fn(&mut self, cx: &LateContext<'_, '_>, _: FnKind<'_>, decl: &FnDecl, _: &Body, _: Span, id: NodeId) {
156         // skip trait implementations, see #605
157         if let Some(hir::Node::Item(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) {
158             if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node {
159                 return;
160             }
161         }
162
163         check_fn_decl(cx, decl);
164     }
165
166     fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &StructField) {
167         check_ty(cx, &field.ty, false);
168     }
169
170     fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &TraitItem) {
171         match item.node {
172             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty, false),
173             TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl),
174             _ => (),
175         }
176     }
177
178     fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local) {
179         if let Some(ref ty) = local.ty {
180             check_ty(cx, ty, true);
181         }
182     }
183 }
184
185 fn check_fn_decl(cx: &LateContext<'_, '_>, decl: &FnDecl) {
186     for input in &decl.inputs {
187         check_ty(cx, input, false);
188     }
189
190     if let FunctionRetTy::Return(ref ty) = decl.output {
191         check_ty(cx, ty, false);
192     }
193 }
194
195 /// Check if `qpath` has last segment with type parameter matching `path`
196 fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) -> bool {
197     let last = last_path_segment(qpath);
198     if_chain! {
199         if let Some(ref params) = last.args;
200         if !params.parenthesized;
201         if let Some(ty) = params.args.iter().find_map(|arg| match arg {
202             GenericArg::Type(ty) => Some(ty),
203             GenericArg::Lifetime(_) => None,
204         });
205         if let TyKind::Path(ref qpath) = ty.node;
206         if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id)));
207         if match_def_path(cx.tcx, did, path);
208         then {
209             return true;
210         }
211     }
212     false
213 }
214
215 /// Recursively check for `TypePass` lints in the given type. Stop at the first
216 /// lint found.
217 ///
218 /// The parameter `is_local` distinguishes the context of the type; types from
219 /// local bindings should only be checked for the `BORROWED_BOX` lint.
220 fn check_ty(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool) {
221     if in_macro(ast_ty.span) {
222         return;
223     }
224     match ast_ty.node {
225         TyKind::Path(ref qpath) if !is_local => {
226             let hir_id = cx.tcx.hir.node_to_hir_id(ast_ty.id);
227             let def = cx.tables.qpath_def(qpath, hir_id);
228             if let Some(def_id) = opt_def_id(def) {
229                 if Some(def_id) == cx.tcx.lang_items().owned_box() {
230                     if match_type_parameter(cx, qpath, &paths::VEC) {
231                         span_help_and_lint(
232                             cx,
233                             BOX_VEC,
234                             ast_ty.span,
235                             "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`",
236                             "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation.",
237                         );
238                         return; // don't recurse into the type
239                     }
240                 } else if match_def_path(cx.tcx, def_id, &paths::OPTION) {
241                     if match_type_parameter(cx, qpath, &paths::OPTION) {
242                         span_lint(
243                             cx,
244                             OPTION_OPTION,
245                             ast_ty.span,
246                             "consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
247                              enum if you need to distinguish all 3 cases",
248                         );
249                         return; // don't recurse into the type
250                     }
251                 } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) {
252                     span_help_and_lint(
253                         cx,
254                         LINKEDLIST,
255                         ast_ty.span,
256                         "I see you're using a LinkedList! Perhaps you meant some other data structure?",
257                         "a VecDeque might work",
258                     );
259                     return; // don't recurse into the type
260                 }
261             }
262             match *qpath {
263                 QPath::Resolved(Some(ref ty), ref p) => {
264                     check_ty(cx, ty, is_local);
265                     for ty in p.segments.iter().flat_map(|seg| {
266                         seg.args
267                             .as_ref()
268                             .map_or_else(|| [].iter(), |params| params.args.iter())
269                             .filter_map(|arg| match arg {
270                                 GenericArg::Type(ty) => Some(ty),
271                                 GenericArg::Lifetime(_) => None,
272                             })
273                     }) {
274                         check_ty(cx, ty, is_local);
275                     }
276                 },
277                 QPath::Resolved(None, ref p) => {
278                     for ty in p.segments.iter().flat_map(|seg| {
279                         seg.args
280                             .as_ref()
281                             .map_or_else(|| [].iter(), |params| params.args.iter())
282                             .filter_map(|arg| match arg {
283                                 GenericArg::Type(ty) => Some(ty),
284                                 GenericArg::Lifetime(_) => None,
285                             })
286                     }) {
287                         check_ty(cx, ty, is_local);
288                     }
289                 },
290                 QPath::TypeRelative(ref ty, ref seg) => {
291                     check_ty(cx, ty, is_local);
292                     if let Some(ref params) = seg.args {
293                         for ty in params.args.iter().filter_map(|arg| match arg {
294                             GenericArg::Type(ty) => Some(ty),
295                             GenericArg::Lifetime(_) => None,
296                         }) {
297                             check_ty(cx, ty, is_local);
298                         }
299                     }
300                 },
301             }
302         },
303         TyKind::Rptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty),
304         // recurse
305         TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => {
306             check_ty(cx, ty, is_local)
307         },
308         TyKind::Tup(ref tys) => {
309             for ty in tys {
310                 check_ty(cx, ty, is_local);
311             }
312         },
313         _ => {},
314     }
315 }
316
317 fn check_ty_rptr(cx: &LateContext<'_, '_>, ast_ty: &hir::Ty, is_local: bool, lt: &Lifetime, mut_ty: &MutTy) {
318     match mut_ty.ty.node {
319         TyKind::Path(ref qpath) => {
320             let hir_id = cx.tcx.hir.node_to_hir_id(mut_ty.ty.id);
321             let def = cx.tables.qpath_def(qpath, hir_id);
322             if_chain! {
323                 if let Some(def_id) = opt_def_id(def);
324                 if Some(def_id) == cx.tcx.lang_items().owned_box();
325                 if let QPath::Resolved(None, ref path) = *qpath;
326                 if let [ref bx] = *path.segments;
327                 if let Some(ref params) = bx.args;
328                 if !params.parenthesized;
329                 if let Some(inner) = params.args.iter().find_map(|arg| match arg {
330                     GenericArg::Type(ty) => Some(ty),
331                     GenericArg::Lifetime(_) => None,
332                 });
333                 then {
334                     if is_any_trait(inner) {
335                         // Ignore `Box<Any>` types, see #1884 for details.
336                         return;
337                     }
338
339                     let ltopt = if lt.is_elided() {
340                         String::new()
341                     } else {
342                         format!("{} ", lt.name.ident().as_str())
343                     };
344                     let mutopt = if mut_ty.mutbl == Mutability::MutMutable {
345                         "mut "
346                     } else {
347                         ""
348                     };
349                     let mut applicability = Applicability::MachineApplicable;
350                     span_lint_and_sugg(
351                         cx,
352                         BORROWED_BOX,
353                         ast_ty.span,
354                         "you seem to be trying to use `&Box<T>`. Consider using just `&T`",
355                         "try",
356                         format!(
357                             "&{}{}{}",
358                             ltopt,
359                             mutopt,
360                             &snippet_with_applicability(cx, inner.span, "..", &mut applicability)
361                         ),
362                         Applicability::Unspecified,
363                     );
364                     return; // don't recurse into the type
365                 }
366             };
367             check_ty(cx, &mut_ty.ty, is_local);
368         },
369         _ => check_ty(cx, &mut_ty.ty, is_local),
370     }
371 }
372
373 // Returns true if given type is `Any` trait.
374 fn is_any_trait(t: &hir::Ty) -> bool {
375     if_chain! {
376         if let TyKind::TraitObject(ref traits, _) = t.node;
377         if traits.len() >= 1;
378         // Only Send/Sync can be used as additional traits, so it is enough to
379         // check only the first trait.
380         if match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT);
381         then {
382             return true;
383         }
384     }
385
386     false
387 }
388
389 pub struct LetPass;
390
391 /// **What it does:** Checks for binding a unit value.
392 ///
393 /// **Why is this bad?** A unit value cannot usefully be used anywhere. So
394 /// binding one is kind of pointless.
395 ///
396 /// **Known problems:** None.
397 ///
398 /// **Example:**
399 /// ```rust
400 /// let x = {
401 ///     1;
402 /// };
403 /// ```
404 declare_clippy_lint! {
405     pub LET_UNIT_VALUE,
406     style,
407     "creating a let binding to a value of unit type, which usually can't be used afterwards"
408 }
409
410 fn check_let_unit(cx: &LateContext<'_, '_>, decl: &Decl) {
411     if let DeclKind::Local(ref local) = decl.node {
412         if is_unit(cx.tables.pat_ty(&local.pat)) {
413             if in_external_macro(cx.sess(), decl.span) || in_macro(local.pat.span) {
414                 return;
415             }
416             if higher::is_from_for_desugar(decl) {
417                 return;
418             }
419             span_lint(
420                 cx,
421                 LET_UNIT_VALUE,
422                 decl.span,
423                 &format!(
424                     "this let-binding has unit value. Consider omitting `let {} =`",
425                     snippet(cx, local.pat.span, "..")
426                 ),
427             );
428         }
429     }
430 }
431
432 impl LintPass for LetPass {
433     fn get_lints(&self) -> LintArray {
434         lint_array!(LET_UNIT_VALUE)
435     }
436 }
437
438 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass {
439     fn check_decl(&mut self, cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl) {
440         check_let_unit(cx, decl)
441     }
442 }
443
444 /// **What it does:** Checks for comparisons to unit.
445 ///
446 /// **Why is this bad?** Unit is always equal to itself, and thus is just a
447 /// clumsily written constant. Mostly this happens when someone accidentally
448 /// adds semicolons at the end of the operands.
449 ///
450 /// **Known problems:** None.
451 ///
452 /// **Example:**
453 /// ```rust
454 /// if {
455 ///     foo();
456 /// } == {
457 ///     bar();
458 /// } {
459 ///     baz();
460 /// }
461 /// ```
462 /// is equal to
463 /// ```rust
464 /// {
465 ///     foo();
466 ///     bar();
467 ///     baz();
468 /// }
469 /// ```
470 declare_clippy_lint! {
471     pub UNIT_CMP,
472     correctness,
473     "comparing unit values"
474 }
475
476 pub struct UnitCmp;
477
478 impl LintPass for UnitCmp {
479     fn get_lints(&self) -> LintArray {
480         lint_array!(UNIT_CMP)
481     }
482 }
483
484 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp {
485     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
486         if in_macro(expr.span) {
487             return;
488         }
489         if let ExprKind::Binary(ref cmp, ref left, _) = expr.node {
490             let op = cmp.node;
491             if op.is_comparison() && is_unit(cx.tables.expr_ty(left)) {
492                 let result = match op {
493                     BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true",
494                     _ => "false",
495                 };
496                 span_lint(
497                     cx,
498                     UNIT_CMP,
499                     expr.span,
500                     &format!(
501                         "{}-comparison of unit values detected. This will always be {}",
502                         op.as_str(),
503                         result
504                     ),
505                 );
506             }
507         }
508     }
509 }
510
511 /// **What it does:** Checks for passing a unit value as an argument to a function without using a
512 /// unit literal (`()`).
513 ///
514 /// **Why is this bad?** This is likely the result of an accidental semicolon.
515 ///
516 /// **Known problems:** None.
517 ///
518 /// **Example:**
519 /// ```rust
520 /// foo({
521 ///     let a = bar();
522 ///     baz(a);
523 /// })
524 /// ```
525 declare_clippy_lint! {
526     pub UNIT_ARG,
527     complexity,
528     "passing unit to a function"
529 }
530
531 pub struct UnitArg;
532
533 impl LintPass for UnitArg {
534     fn get_lints(&self) -> LintArray {
535         lint_array!(UNIT_ARG)
536     }
537 }
538
539 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg {
540     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
541         if in_macro(expr.span) {
542             return;
543         }
544         match expr.node {
545             ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => {
546                 for arg in args {
547                     if is_unit(cx.tables.expr_ty(arg)) && !is_unit_literal(arg) {
548                         let map = &cx.tcx.hir;
549                         // apparently stuff in the desugaring of `?` can trigger this
550                         // so check for that here
551                         // only the calls to `Try::from_error` is marked as desugared,
552                         // so we need to check both the current Expr and its parent.
553                         if !is_questionmark_desugar_marked_call(expr) {
554                             if_chain! {
555                                 let opt_parent_node = map.find(map.get_parent_node(expr.id));
556                                 if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
557                                 if is_questionmark_desugar_marked_call(parent_expr);
558                                 then {}
559                                 else {
560                                     // `expr` and `parent_expr` where _both_ not from
561                                     // desugaring `?`, so lint
562                                     span_lint_and_sugg(
563                                         cx,
564                                         UNIT_ARG,
565                                         arg.span,
566                                         "passing a unit value to a function",
567                                         "if you intended to pass a unit value, use a unit literal instead",
568                                         "()".to_string(),
569                                         Applicability::MachineApplicable,
570                                     );
571                                 }
572                             }
573                         }
574                     }
575                 }
576             },
577             _ => (),
578         }
579     }
580 }
581
582 fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool {
583     use crate::syntax_pos::hygiene::CompilerDesugaringKind;
584     if let ExprKind::Call(ref callee, _) = expr.node {
585         callee.span.is_compiler_desugaring(CompilerDesugaringKind::QuestionMark)
586     } else {
587         false
588     }
589 }
590
591 fn is_unit(ty: Ty<'_>) -> bool {
592     match ty.sty {
593         ty::Tuple(slice) if slice.is_empty() => true,
594         _ => false,
595     }
596 }
597
598 fn is_unit_literal(expr: &Expr) -> bool {
599     match expr.node {
600         ExprKind::Tup(ref slice) if slice.is_empty() => true,
601         _ => false,
602     }
603 }
604
605 pub struct CastPass;
606
607 /// **What it does:** Checks for casts from any numerical to a float type where
608 /// the receiving type cannot store all values from the original type without
609 /// rounding errors. This possible rounding is to be expected, so this lint is
610 /// `Allow` by default.
611 ///
612 /// Basically, this warns on casting any integer with 32 or more bits to `f32`
613 /// or any 64-bit integer to `f64`.
614 ///
615 /// **Why is this bad?** It's not bad at all. But in some applications it can be
616 /// helpful to know where precision loss can take place. This lint can help find
617 /// those places in the code.
618 ///
619 /// **Known problems:** None.
620 ///
621 /// **Example:**
622 /// ```rust
623 /// let x = u64::MAX;
624 /// x as f64
625 /// ```
626 declare_clippy_lint! {
627     pub CAST_PRECISION_LOSS,
628     pedantic,
629     "casts that cause loss of precision, e.g. `x as f32` where `x: u64`"
630 }
631
632 /// **What it does:** Checks for casts from a signed to an unsigned numerical
633 /// type. In this case, negative values wrap around to large positive values,
634 /// which can be quite surprising in practice. However, as the cast works as
635 /// defined, this lint is `Allow` by default.
636 ///
637 /// **Why is this bad?** Possibly surprising results. You can activate this lint
638 /// as a one-time check to see where numerical wrapping can arise.
639 ///
640 /// **Known problems:** None.
641 ///
642 /// **Example:**
643 /// ```rust
644 /// let y: i8 = -1;
645 /// y as u128 // will return 18446744073709551615
646 /// ```
647 declare_clippy_lint! {
648     pub CAST_SIGN_LOSS,
649     pedantic,
650     "casts from signed types to unsigned types, e.g. `x as u32` where `x: i32`"
651 }
652
653 /// **What it does:** Checks for on casts between numerical types that may
654 /// truncate large values. This is expected behavior, so the cast is `Allow` by
655 /// default.
656 ///
657 /// **Why is this bad?** In some problem domains, it is good practice to avoid
658 /// truncation. This lint can be activated to help assess where additional
659 /// checks could be beneficial.
660 ///
661 /// **Known problems:** None.
662 ///
663 /// **Example:**
664 /// ```rust
665 /// fn as_u8(x: u64) -> u8 {
666 ///     x as u8
667 /// }
668 /// ```
669 declare_clippy_lint! {
670     pub CAST_POSSIBLE_TRUNCATION,
671     pedantic,
672     "casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32`"
673 }
674
675 /// **What it does:** Checks for casts from an unsigned type to a signed type of
676 /// the same size. Performing such a cast is a 'no-op' for the compiler,
677 /// i.e. nothing is changed at the bit level, and the binary representation of
678 /// the value is reinterpreted. This can cause wrapping if the value is too big
679 /// for the target signed type. However, the cast works as defined, so this lint
680 /// is `Allow` by default.
681 ///
682 /// **Why is this bad?** While such a cast is not bad in itself, the results can
683 /// be surprising when this is not the intended behavior, as demonstrated by the
684 /// example below.
685 ///
686 /// **Known problems:** None.
687 ///
688 /// **Example:**
689 /// ```rust
690 /// u32::MAX as i32 // will yield a value of `-1`
691 /// ```
692 declare_clippy_lint! {
693     pub CAST_POSSIBLE_WRAP,
694     pedantic,
695     "casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX`"
696 }
697
698 /// **What it does:** Checks for on casts between numerical types that may
699 /// be replaced by safe conversion functions.
700 ///
701 /// **Why is this bad?** Rust's `as` keyword will perform many kinds of
702 /// conversions, including silently lossy conversions. Conversion functions such
703 /// as `i32::from` will only perform lossless conversions. Using the conversion
704 /// functions prevents conversions from turning into silent lossy conversions if
705 /// the types of the input expressions ever change, and make it easier for
706 /// people reading the code to know that the conversion is lossless.
707 ///
708 /// **Known problems:** None.
709 ///
710 /// **Example:**
711 /// ```rust
712 /// fn as_u64(x: u8) -> u64 {
713 ///     x as u64
714 /// }
715 /// ```
716 ///
717 /// Using `::from` would look like this:
718 ///
719 /// ```rust
720 /// fn as_u64(x: u8) -> u64 {
721 ///     u64::from(x)
722 /// }
723 /// ```
724 declare_clippy_lint! {
725     pub CAST_LOSSLESS,
726     complexity,
727     "casts using `as` that are known to be lossless, e.g. `x as u64` where `x: u8`"
728 }
729
730 /// **What it does:** Checks for casts to the same type.
731 ///
732 /// **Why is this bad?** It's just unnecessary.
733 ///
734 /// **Known problems:** None.
735 ///
736 /// **Example:**
737 /// ```rust
738 /// let _ = 2i32 as i32
739 /// ```
740 declare_clippy_lint! {
741     pub UNNECESSARY_CAST,
742     complexity,
743     "cast to the same type, e.g. `x as i32` where `x: i32`"
744 }
745
746 /// **What it does:** Checks for casts from a less-strictly-aligned pointer to a
747 /// more-strictly-aligned pointer
748 ///
749 /// **Why is this bad?** Dereferencing the resulting pointer may be undefined
750 /// behavior.
751 ///
752 /// **Known problems:** None.
753 ///
754 /// **Example:**
755 /// ```rust
756 /// let _ = (&1u8 as *const u8) as *const u16;
757 /// let _ = (&mut 1u8 as *mut u8) as *mut u16;
758 /// ```
759 declare_clippy_lint! {
760     pub CAST_PTR_ALIGNMENT,
761     correctness,
762     "cast from a pointer to a more-strictly-aligned pointer"
763 }
764
765 /// **What it does:** Checks for casts of function pointers to something other than usize
766 ///
767 /// **Why is this bad?**
768 /// Casting a function pointer to anything other than usize/isize is not portable across
769 /// architectures, because you end up losing bits if the target type is too small or end up with a
770 /// bunch of extra bits that waste space and add more instructions to the final binary than
771 /// strictly necessary for the problem
772 ///
773 /// Casting to isize also doesn't make sense since there are no signed addresses.
774 ///
775 /// **Example**
776 ///
777 /// ```rust
778 /// // Bad
779 /// fn fun() -> i32 {}
780 /// let a = fun as i64;
781 ///
782 /// // Good
783 /// fn fun2() -> i32 {}
784 /// let a = fun2 as usize;
785 /// ```
786 declare_clippy_lint! {
787     pub FN_TO_NUMERIC_CAST,
788     style,
789     "casting a function pointer to a numeric type other than usize"
790 }
791
792 /// **What it does:** Checks for casts of a function pointer to a numeric type not wide enough to
793 /// store address.
794 ///
795 /// **Why is this bad?**
796 /// Such a cast discards some bits of the function's address. If this is intended, it would be more
797 /// clearly expressed by casting to usize first, then casting the usize to the intended type (with
798 /// a comment) to perform the truncation.
799 ///
800 /// **Example**
801 ///
802 /// ```rust
803 /// // Bad
804 /// fn fn1() -> i16 {
805 ///     1
806 /// };
807 /// let _ = fn1 as i32;
808 ///
809 /// // Better: Cast to usize first, then comment with the reason for the truncation
810 /// fn fn2() -> i16 {
811 ///     1
812 /// };
813 /// let fn_ptr = fn2 as usize;
814 /// let fn_ptr_truncated = fn_ptr as i32;
815 /// ```
816 declare_clippy_lint! {
817     pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
818     style,
819     "casting a function pointer to a numeric type not wide enough to store the address"
820 }
821
822 /// Returns the size in bits of an integral type.
823 /// Will return 0 if the type is not an int or uint variant
824 fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 {
825     match typ.sty {
826         ty::Int(i) => match i {
827             IntTy::Isize => tcx.data_layout.pointer_size.bits(),
828             IntTy::I8 => 8,
829             IntTy::I16 => 16,
830             IntTy::I32 => 32,
831             IntTy::I64 => 64,
832             IntTy::I128 => 128,
833         },
834         ty::Uint(i) => match i {
835             UintTy::Usize => tcx.data_layout.pointer_size.bits(),
836             UintTy::U8 => 8,
837             UintTy::U16 => 16,
838             UintTy::U32 => 32,
839             UintTy::U64 => 64,
840             UintTy::U128 => 128,
841         },
842         _ => 0,
843     }
844 }
845
846 fn is_isize_or_usize(typ: Ty<'_>) -> bool {
847     match typ.sty {
848         ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => true,
849         _ => false,
850     }
851 }
852
853 fn span_precision_loss_lint(cx: &LateContext<'_, '_>, expr: &Expr, cast_from: Ty<'_>, cast_to_f64: bool) {
854     let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
855     let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
856     let arch_dependent_str = "on targets with 64-bit wide pointers ";
857     let from_nbits_str = if arch_dependent {
858         "64".to_owned()
859     } else if is_isize_or_usize(cast_from) {
860         "32 or 64".to_owned()
861     } else {
862         int_ty_to_nbits(cast_from, cx.tcx).to_string()
863     };
864     span_lint(
865         cx,
866         CAST_PRECISION_LOSS,
867         expr.span,
868         &format!(
869             "casting {0} to {1} causes a loss of precision {2}({0} is {3} bits wide, but {1}'s mantissa \
870              is only {4} bits wide)",
871             cast_from,
872             if cast_to_f64 { "f64" } else { "f32" },
873             if arch_dependent { arch_dependent_str } else { "" },
874             from_nbits_str,
875             mantissa_nbits
876         ),
877     );
878 }
879
880 fn should_strip_parens(op: &Expr, snip: &str) -> bool {
881     if let ExprKind::Binary(_, _, _) = op.node {
882         if snip.starts_with('(') && snip.ends_with(')') {
883             return true;
884         }
885     }
886     false
887 }
888
889 fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) {
890     // Do not suggest using From in consts/statics until it is valid to do so (see #2267).
891     if in_constant(cx, expr.id) {
892         return;
893     }
894     // The suggestion is to use a function call, so if the original expression
895     // has parens on the outside, they are no longer needed.
896     let mut applicability = Applicability::MachineApplicable;
897     let opt = snippet_opt(cx, op.span);
898     let sugg = if let Some(ref snip) = opt {
899         if should_strip_parens(op, snip) {
900             &snip[1..snip.len() - 1]
901         } else {
902             snip.as_str()
903         }
904     } else {
905         applicability = Applicability::HasPlaceholders;
906         ".."
907     };
908
909     span_lint_and_sugg(
910         cx,
911         CAST_LOSSLESS,
912         expr.span,
913         &format!(
914             "casting {} to {} may become silently lossy if types change",
915             cast_from, cast_to
916         ),
917         "try",
918         format!("{}::from({})", cast_to, sugg),
919         applicability,
920     );
921 }
922
923 enum ArchSuffix {
924     _32,
925     _64,
926     None,
927 }
928
929 fn check_truncation_and_wrapping(cx: &LateContext<'_, '_>, expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) {
930     let arch_64_suffix = " on targets with 64-bit wide pointers";
931     let arch_32_suffix = " on targets with 32-bit wide pointers";
932     let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed();
933     let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
934     let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
935     let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) =
936         match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
937             (true, true) | (false, false) => (
938                 to_nbits < from_nbits,
939                 ArchSuffix::None,
940                 to_nbits == from_nbits && cast_unsigned_to_signed,
941                 ArchSuffix::None,
942             ),
943             (true, false) => (
944                 to_nbits <= 32,
945                 if to_nbits == 32 {
946                     ArchSuffix::_64
947                 } else {
948                     ArchSuffix::None
949                 },
950                 to_nbits <= 32 && cast_unsigned_to_signed,
951                 ArchSuffix::_32,
952             ),
953             (false, true) => (
954                 from_nbits == 64,
955                 ArchSuffix::_32,
956                 cast_unsigned_to_signed,
957                 if from_nbits == 64 {
958                     ArchSuffix::_64
959                 } else {
960                     ArchSuffix::_32
961                 },
962             ),
963         };
964     if span_truncation {
965         span_lint(
966             cx,
967             CAST_POSSIBLE_TRUNCATION,
968             expr.span,
969             &format!(
970                 "casting {} to {} may truncate the value{}",
971                 cast_from,
972                 cast_to,
973                 match suffix_truncation {
974                     ArchSuffix::_32 => arch_32_suffix,
975                     ArchSuffix::_64 => arch_64_suffix,
976                     ArchSuffix::None => "",
977                 }
978             ),
979         );
980     }
981     if span_wrap {
982         span_lint(
983             cx,
984             CAST_POSSIBLE_WRAP,
985             expr.span,
986             &format!(
987                 "casting {} to {} may wrap around the value{}",
988                 cast_from,
989                 cast_to,
990                 match suffix_wrap {
991                     ArchSuffix::_32 => arch_32_suffix,
992                     ArchSuffix::_64 => arch_64_suffix,
993                     ArchSuffix::None => "",
994                 }
995             ),
996         );
997     }
998 }
999
1000 fn check_lossless(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1001     let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed();
1002     let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
1003     let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
1004     if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && !cast_signed_to_unsigned
1005     {
1006         span_lossless_lint(cx, expr, op, cast_from, cast_to);
1007     }
1008 }
1009
1010 impl LintPass for CastPass {
1011     fn get_lints(&self) -> LintArray {
1012         lint_array!(
1013             CAST_PRECISION_LOSS,
1014             CAST_SIGN_LOSS,
1015             CAST_POSSIBLE_TRUNCATION,
1016             CAST_POSSIBLE_WRAP,
1017             CAST_LOSSLESS,
1018             UNNECESSARY_CAST,
1019             CAST_PTR_ALIGNMENT,
1020             FN_TO_NUMERIC_CAST,
1021             FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
1022         )
1023     }
1024 }
1025
1026 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass {
1027     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
1028         if let ExprKind::Cast(ref ex, _) = expr.node {
1029             let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr));
1030             lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
1031             if let ExprKind::Lit(ref lit) = ex.node {
1032                 use crate::syntax::ast::{LitIntType, LitKind};
1033                 match lit.node {
1034                     LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {},
1035                     _ => {
1036                         if cast_from.sty == cast_to.sty && !in_external_macro(cx.sess(), expr.span) {
1037                             span_lint(
1038                                 cx,
1039                                 UNNECESSARY_CAST,
1040                                 expr.span,
1041                                 &format!(
1042                                     "casting to the same type is unnecessary (`{}` -> `{}`)",
1043                                     cast_from, cast_to
1044                                 ),
1045                             );
1046                         }
1047                     },
1048                 }
1049             }
1050             if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
1051                 match (cast_from.is_integral(), cast_to.is_integral()) {
1052                     (true, false) => {
1053                         let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
1054                         let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.sty {
1055                             32
1056                         } else {
1057                             64
1058                         };
1059                         if is_isize_or_usize(cast_from) || from_nbits >= to_nbits {
1060                             span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64);
1061                         }
1062                         if from_nbits < to_nbits {
1063                             span_lossless_lint(cx, expr, ex, cast_from, cast_to);
1064                         }
1065                     },
1066                     (false, true) => {
1067                         span_lint(
1068                             cx,
1069                             CAST_POSSIBLE_TRUNCATION,
1070                             expr.span,
1071                             &format!("casting {} to {} may truncate the value", cast_from, cast_to),
1072                         );
1073                         if !cast_to.is_signed() {
1074                             span_lint(
1075                                 cx,
1076                                 CAST_SIGN_LOSS,
1077                                 expr.span,
1078                                 &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to),
1079                             );
1080                         }
1081                     },
1082                     (true, true) => {
1083                         if cast_from.is_signed() && !cast_to.is_signed() {
1084                             span_lint(
1085                                 cx,
1086                                 CAST_SIGN_LOSS,
1087                                 expr.span,
1088                                 &format!("casting {} to {} may lose the sign of the value", cast_from, cast_to),
1089                             );
1090                         }
1091                         check_truncation_and_wrapping(cx, expr, cast_from, cast_to);
1092                         check_lossless(cx, expr, ex, cast_from, cast_to);
1093                     },
1094                     (false, false) => {
1095                         if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) {
1096                             span_lint(
1097                                 cx,
1098                                 CAST_POSSIBLE_TRUNCATION,
1099                                 expr.span,
1100                                 "casting f64 to f32 may truncate the value",
1101                             );
1102                         }
1103                         if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) {
1104                             span_lossless_lint(cx, expr, ex, cast_from, cast_to);
1105                         }
1106                     },
1107                 }
1108             }
1109
1110             if_chain! {
1111                 if let ty::RawPtr(from_ptr_ty) = &cast_from.sty;
1112                 if let ty::RawPtr(to_ptr_ty) = &cast_to.sty;
1113                 if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi);
1114                 if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi);
1115                 if from_align < to_align;
1116                 // with c_void, we inherently need to trust the user
1117                 if ! (
1118                     match_type(cx, from_ptr_ty.ty, &paths::C_VOID)
1119                     || match_type(cx, from_ptr_ty.ty, &paths::C_VOID_LIBC)
1120                 );
1121                 then {
1122                     span_lint(
1123                         cx,
1124                         CAST_PTR_ALIGNMENT,
1125                         expr.span,
1126                         &format!("casting from `{}` to a more-strictly-aligned pointer (`{}`)", cast_from, cast_to)
1127                     );
1128                 }
1129             }
1130         }
1131     }
1132 }
1133
1134 fn lint_fn_to_numeric_cast(
1135     cx: &LateContext<'_, '_>,
1136     expr: &Expr,
1137     cast_expr: &Expr,
1138     cast_from: Ty<'_>,
1139     cast_to: Ty<'_>,
1140 ) {
1141     // We only want to check casts to `ty::Uint` or `ty::Int`
1142     match cast_to.sty {
1143         ty::Uint(_) | ty::Int(..) => { /* continue on */ },
1144         _ => return,
1145     }
1146     match cast_from.sty {
1147         ty::FnDef(..) | ty::FnPtr(_) => {
1148             let mut applicability = Applicability::MachineApplicable;
1149             let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
1150
1151             let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
1152             if to_nbits < cx.tcx.data_layout.pointer_size.bits() {
1153                 span_lint_and_sugg(
1154                     cx,
1155                     FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
1156                     expr.span,
1157                     &format!(
1158                         "casting function pointer `{}` to `{}`, which truncates the value",
1159                         from_snippet, cast_to
1160                     ),
1161                     "try",
1162                     format!("{} as usize", from_snippet),
1163                     applicability,
1164                 );
1165             } else if cast_to.sty != ty::Uint(UintTy::Usize) {
1166                 span_lint_and_sugg(
1167                     cx,
1168                     FN_TO_NUMERIC_CAST,
1169                     expr.span,
1170                     &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
1171                     "try",
1172                     format!("{} as usize", from_snippet),
1173                     applicability,
1174                 );
1175             }
1176         },
1177         _ => {},
1178     }
1179 }
1180
1181 /// **What it does:** Checks for types used in structs, parameters and `let`
1182 /// declarations above a certain complexity threshold.
1183 ///
1184 /// **Why is this bad?** Too complex types make the code less readable. Consider
1185 /// using a `type` definition to simplify them.
1186 ///
1187 /// **Known problems:** None.
1188 ///
1189 /// **Example:**
1190 /// ```rust
1191 /// struct Foo {
1192 ///     inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
1193 /// }
1194 /// ```
1195 declare_clippy_lint! {
1196     pub TYPE_COMPLEXITY,
1197     complexity,
1198     "usage of very complex types that might be better factored into `type` definitions"
1199 }
1200
1201 pub struct TypeComplexityPass {
1202     threshold: u64,
1203 }
1204
1205 impl TypeComplexityPass {
1206     pub fn new(threshold: u64) -> Self {
1207         Self { threshold }
1208     }
1209 }
1210
1211 impl LintPass for TypeComplexityPass {
1212     fn get_lints(&self) -> LintArray {
1213         lint_array!(TYPE_COMPLEXITY)
1214     }
1215 }
1216
1217 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass {
1218     fn check_fn(
1219         &mut self,
1220         cx: &LateContext<'a, 'tcx>,
1221         _: FnKind<'tcx>,
1222         decl: &'tcx FnDecl,
1223         _: &'tcx Body,
1224         _: Span,
1225         _: NodeId,
1226     ) {
1227         self.check_fndecl(cx, decl);
1228     }
1229
1230     fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx StructField) {
1231         // enum variants are also struct fields now
1232         self.check_type(cx, &field.ty);
1233     }
1234
1235     fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
1236         match item.node {
1237             ItemKind::Static(ref ty, _, _) | ItemKind::Const(ref ty, _) => self.check_type(cx, ty),
1238             // functions, enums, structs, impls and traits are covered
1239             _ => (),
1240         }
1241     }
1242
1243     fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
1244         match item.node {
1245             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty),
1246             TraitItemKind::Method(MethodSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl),
1247             // methods with default impl are covered by check_fn
1248             _ => (),
1249         }
1250     }
1251
1252     fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
1253         match item.node {
1254             ImplItemKind::Const(ref ty, _) | ImplItemKind::Type(ref ty) => self.check_type(cx, ty),
1255             // methods are covered by check_fn
1256             _ => (),
1257         }
1258     }
1259
1260     fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local) {
1261         if let Some(ref ty) = local.ty {
1262             self.check_type(cx, ty);
1263         }
1264     }
1265 }
1266
1267 impl<'a, 'tcx> TypeComplexityPass {
1268     fn check_fndecl(&self, cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl) {
1269         for arg in &decl.inputs {
1270             self.check_type(cx, arg);
1271         }
1272         if let Return(ref ty) = decl.output {
1273             self.check_type(cx, ty);
1274         }
1275     }
1276
1277     fn check_type(&self, cx: &LateContext<'_, '_>, ty: &hir::Ty) {
1278         if in_macro(ty.span) {
1279             return;
1280         }
1281         let score = {
1282             let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
1283             visitor.visit_ty(ty);
1284             visitor.score
1285         };
1286
1287         if score > self.threshold {
1288             span_lint(
1289                 cx,
1290                 TYPE_COMPLEXITY,
1291                 ty.span,
1292                 "very complex type used. Consider factoring parts into `type` definitions",
1293             );
1294         }
1295     }
1296 }
1297
1298 /// Walks a type and assigns a complexity score to it.
1299 struct TypeComplexityVisitor {
1300     /// total complexity score of the type
1301     score: u64,
1302     /// current nesting level
1303     nest: u64,
1304 }
1305
1306 impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
1307     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
1308         let (add_score, sub_nest) = match ty.node {
1309             // _, &x and *x have only small overhead; don't mess with nesting level
1310             TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0),
1311
1312             // the "normal" components of a type: named types, arrays/tuples
1313             TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1),
1314
1315             // function types bring a lot of overhead
1316             TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
1317
1318             TyKind::TraitObject(ref param_bounds, _) => {
1319                 let has_lifetime_parameters = param_bounds.iter().any(|bound| {
1320                     bound.bound_generic_params.iter().any(|gen| match gen.kind {
1321                         GenericParamKind::Lifetime { .. } => true,
1322                         _ => false,
1323                     })
1324                 });
1325                 if has_lifetime_parameters {
1326                     // complex trait bounds like A<'a, 'b>
1327                     (50 * self.nest, 1)
1328                 } else {
1329                     // simple trait bounds like A + B
1330                     (20 * self.nest, 0)
1331                 }
1332             },
1333
1334             _ => (0, 0),
1335         };
1336         self.score += add_score;
1337         self.nest += sub_nest;
1338         walk_ty(self, ty);
1339         self.nest -= sub_nest;
1340     }
1341     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1342         NestedVisitorMap::None
1343     }
1344 }
1345
1346 /// **What it does:** Checks for expressions where a character literal is cast
1347 /// to `u8` and suggests using a byte literal instead.
1348 ///
1349 /// **Why is this bad?** In general, casting values to smaller types is
1350 /// error-prone and should be avoided where possible. In the particular case of
1351 /// converting a character literal to u8, it is easy to avoid by just using a
1352 /// byte literal instead. As an added bonus, `b'a'` is even slightly shorter
1353 /// than `'a' as u8`.
1354 ///
1355 /// **Known problems:** None.
1356 ///
1357 /// **Example:**
1358 /// ```rust
1359 /// 'x' as u8
1360 /// ```
1361 ///
1362 /// A better version, using the byte literal:
1363 ///
1364 /// ```rust
1365 /// b'x'
1366 /// ```
1367 declare_clippy_lint! {
1368     pub CHAR_LIT_AS_U8,
1369     complexity,
1370     "casting a character literal to u8"
1371 }
1372
1373 pub struct CharLitAsU8;
1374
1375 impl LintPass for CharLitAsU8 {
1376     fn get_lints(&self) -> LintArray {
1377         lint_array!(CHAR_LIT_AS_U8)
1378     }
1379 }
1380
1381 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 {
1382     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
1383         use crate::syntax::ast::{LitKind, UintTy};
1384
1385         if let ExprKind::Cast(ref e, _) = expr.node {
1386             if let ExprKind::Lit(ref l) = e.node {
1387                 if let LitKind::Char(_) = l.node {
1388                     if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !in_macro(expr.span) {
1389                         let msg = "casting character literal to u8. `char`s \
1390                                    are 4 bytes wide in rust, so casting to u8 \
1391                                    truncates them";
1392                         let help = format!(
1393                             "Consider using a byte literal instead:\nb{}",
1394                             snippet(cx, e.span, "'x'")
1395                         );
1396                         span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help);
1397                     }
1398                 }
1399             }
1400         }
1401     }
1402 }
1403
1404 /// **What it does:** Checks for comparisons where one side of the relation is
1405 /// either the minimum or maximum value for its type and warns if it involves a
1406 /// case that is always true or always false. Only integer and boolean types are
1407 /// checked.
1408 ///
1409 /// **Why is this bad?** An expression like `min <= x` may misleadingly imply
1410 /// that is is possible for `x` to be less than the minimum. Expressions like
1411 /// `max < x` are probably mistakes.
1412 ///
1413 /// **Known problems:** For `usize` the size of the current compile target will
1414 /// be assumed (e.g. 64 bits on 64 bit systems). This means code that uses such
1415 /// a comparison to detect target pointer width will trigger this lint. One can
1416 /// use `mem::sizeof` and compare its value or conditional compilation
1417 /// attributes
1418 /// like `#[cfg(target_pointer_width = "64")] ..` instead.
1419 ///
1420 /// **Example:**
1421 /// ```rust
1422 /// vec.len() <= 0
1423 /// 100 > std::i32::MAX
1424 /// ```
1425 declare_clippy_lint! {
1426     pub ABSURD_EXTREME_COMPARISONS,
1427     correctness,
1428     "a comparison with a maximum or minimum value that is always true or false"
1429 }
1430
1431 pub struct AbsurdExtremeComparisons;
1432
1433 impl LintPass for AbsurdExtremeComparisons {
1434     fn get_lints(&self) -> LintArray {
1435         lint_array!(ABSURD_EXTREME_COMPARISONS)
1436     }
1437 }
1438
1439 enum ExtremeType {
1440     Minimum,
1441     Maximum,
1442 }
1443
1444 struct ExtremeExpr<'a> {
1445     which: ExtremeType,
1446     expr: &'a Expr,
1447 }
1448
1449 enum AbsurdComparisonResult {
1450     AlwaysFalse,
1451     AlwaysTrue,
1452     InequalityImpossible,
1453 }
1454
1455 fn is_cast_between_fixed_and_target<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
1456     if let ExprKind::Cast(ref cast_exp, _) = expr.node {
1457         let precast_ty = cx.tables.expr_ty(cast_exp);
1458         let cast_ty = cx.tables.expr_ty(expr);
1459
1460         return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty);
1461     }
1462
1463     false
1464 }
1465
1466 fn detect_absurd_comparison<'a, 'tcx>(
1467     cx: &LateContext<'a, 'tcx>,
1468     op: BinOpKind,
1469     lhs: &'tcx Expr,
1470     rhs: &'tcx Expr,
1471 ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> {
1472     use crate::types::AbsurdComparisonResult::*;
1473     use crate::types::ExtremeType::*;
1474     use crate::utils::comparisons::*;
1475
1476     // absurd comparison only makes sense on primitive types
1477     // primitive types don't implement comparison operators with each other
1478     if cx.tables.expr_ty(lhs) != cx.tables.expr_ty(rhs) {
1479         return None;
1480     }
1481
1482     // comparisons between fix sized types and target sized types are considered unanalyzable
1483     if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) {
1484         return None;
1485     }
1486
1487     let normalized = normalize_comparison(op, lhs, rhs);
1488     let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
1489         val
1490     } else {
1491         return None;
1492     };
1493
1494     let lx = detect_extreme_expr(cx, normalized_lhs);
1495     let rx = detect_extreme_expr(cx, normalized_rhs);
1496
1497     Some(match rel {
1498         Rel::Lt => {
1499             match (lx, rx) {
1500                 (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x
1501                 (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min
1502                 _ => return None,
1503             }
1504         },
1505         Rel::Le => {
1506             match (lx, rx) {
1507                 (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x
1508                 (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x
1509                 (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min
1510                 (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max
1511                 _ => return None,
1512             }
1513         },
1514         Rel::Ne | Rel::Eq => return None,
1515     })
1516 }
1517
1518 fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option<ExtremeExpr<'tcx>> {
1519     use crate::types::ExtremeType::*;
1520
1521     let ty = cx.tables.expr_ty(expr);
1522
1523     let cv = constant(cx, cx.tables, expr)?.0;
1524
1525     let which = match (&ty.sty, cv) {
1526         (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum,
1527         (&ty::Int(ity), Constant::Int(i))
1528             if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) =>
1529         {
1530             Minimum
1531         },
1532
1533         (&ty::Bool, Constant::Bool(true)) => Maximum,
1534         (&ty::Int(ity), Constant::Int(i))
1535             if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) =>
1536         {
1537             Maximum
1538         },
1539         (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum,
1540
1541         _ => return None,
1542     };
1543     Some(ExtremeExpr { which, expr })
1544 }
1545
1546 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons {
1547     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
1548         use crate::types::AbsurdComparisonResult::*;
1549         use crate::types::ExtremeType::*;
1550
1551         if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.node {
1552             if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) {
1553                 if !in_macro(expr.span) {
1554                     let msg = "this comparison involving the minimum or maximum element for this \
1555                                type contains a case that is always true or always false";
1556
1557                     let conclusion = match result {
1558                         AlwaysFalse => "this comparison is always false".to_owned(),
1559                         AlwaysTrue => "this comparison is always true".to_owned(),
1560                         InequalityImpossible => format!(
1561                             "the case where the two sides are not equal never occurs, consider using {} == {} \
1562                              instead",
1563                             snippet(cx, lhs.span, "lhs"),
1564                             snippet(cx, rhs.span, "rhs")
1565                         ),
1566                     };
1567
1568                     let help = format!(
1569                         "because {} is the {} value for this type, {}",
1570                         snippet(cx, culprit.expr.span, "x"),
1571                         match culprit.which {
1572                             Minimum => "minimum",
1573                             Maximum => "maximum",
1574                         },
1575                         conclusion
1576                     );
1577
1578                     span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help);
1579                 }
1580             }
1581         }
1582     }
1583 }
1584
1585 /// **What it does:** Checks for comparisons where the relation is always either
1586 /// true or false, but where one side has been upcast so that the comparison is
1587 /// necessary. Only integer types are checked.
1588 ///
1589 /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300`
1590 /// will mistakenly imply that it is possible for `x` to be outside the range of
1591 /// `u8`.
1592 ///
1593 /// **Known problems:**
1594 /// https://github.com/rust-lang/rust-clippy/issues/886
1595 ///
1596 /// **Example:**
1597 /// ```rust
1598 /// let x : u8 = ...; (x as u32) > 300
1599 /// ```
1600 declare_clippy_lint! {
1601     pub INVALID_UPCAST_COMPARISONS,
1602     pedantic,
1603     "a comparison involving an upcast which is always true or false"
1604 }
1605
1606 pub struct InvalidUpcastComparisons;
1607
1608 impl LintPass for InvalidUpcastComparisons {
1609     fn get_lints(&self) -> LintArray {
1610         lint_array!(INVALID_UPCAST_COMPARISONS)
1611     }
1612 }
1613
1614 #[derive(Copy, Clone, Debug, Eq)]
1615 enum FullInt {
1616     S(i128),
1617     U(u128),
1618 }
1619
1620 impl FullInt {
1621     #[allow(clippy::cast_sign_loss)]
1622     fn cmp_s_u(s: i128, u: u128) -> Ordering {
1623         if s < 0 {
1624             Ordering::Less
1625         } else if u > (i128::max_value() as u128) {
1626             Ordering::Greater
1627         } else {
1628             (s as u128).cmp(&u)
1629         }
1630     }
1631 }
1632
1633 impl PartialEq for FullInt {
1634     fn eq(&self, other: &Self) -> bool {
1635         self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal
1636     }
1637 }
1638
1639 impl PartialOrd for FullInt {
1640     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1641         Some(match (self, other) {
1642             (&FullInt::S(s), &FullInt::S(o)) => s.cmp(&o),
1643             (&FullInt::U(s), &FullInt::U(o)) => s.cmp(&o),
1644             (&FullInt::S(s), &FullInt::U(o)) => Self::cmp_s_u(s, o),
1645             (&FullInt::U(s), &FullInt::S(o)) => Self::cmp_s_u(o, s).reverse(),
1646         })
1647     }
1648 }
1649 impl Ord for FullInt {
1650     fn cmp(&self, other: &Self) -> Ordering {
1651         self.partial_cmp(other)
1652             .expect("partial_cmp for FullInt can never return None")
1653     }
1654 }
1655
1656 fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> {
1657     use crate::syntax::ast::{IntTy, UintTy};
1658     use std::*;
1659
1660     if let ExprKind::Cast(ref cast_exp, _) = expr.node {
1661         let pre_cast_ty = cx.tables.expr_ty(cast_exp);
1662         let cast_ty = cx.tables.expr_ty(expr);
1663         // if it's a cast from i32 to u32 wrapping will invalidate all these checks
1664         if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) {
1665             return None;
1666         }
1667         match pre_cast_ty.sty {
1668             ty::Int(int_ty) => Some(match int_ty {
1669                 IntTy::I8 => (
1670                     FullInt::S(i128::from(i8::min_value())),
1671                     FullInt::S(i128::from(i8::max_value())),
1672                 ),
1673                 IntTy::I16 => (
1674                     FullInt::S(i128::from(i16::min_value())),
1675                     FullInt::S(i128::from(i16::max_value())),
1676                 ),
1677                 IntTy::I32 => (
1678                     FullInt::S(i128::from(i32::min_value())),
1679                     FullInt::S(i128::from(i32::max_value())),
1680                 ),
1681                 IntTy::I64 => (
1682                     FullInt::S(i128::from(i64::min_value())),
1683                     FullInt::S(i128::from(i64::max_value())),
1684                 ),
1685                 IntTy::I128 => (FullInt::S(i128::min_value()), FullInt::S(i128::max_value())),
1686                 IntTy::Isize => (
1687                     FullInt::S(isize::min_value() as i128),
1688                     FullInt::S(isize::max_value() as i128),
1689                 ),
1690             }),
1691             ty::Uint(uint_ty) => Some(match uint_ty {
1692                 UintTy::U8 => (
1693                     FullInt::U(u128::from(u8::min_value())),
1694                     FullInt::U(u128::from(u8::max_value())),
1695                 ),
1696                 UintTy::U16 => (
1697                     FullInt::U(u128::from(u16::min_value())),
1698                     FullInt::U(u128::from(u16::max_value())),
1699                 ),
1700                 UintTy::U32 => (
1701                     FullInt::U(u128::from(u32::min_value())),
1702                     FullInt::U(u128::from(u32::max_value())),
1703                 ),
1704                 UintTy::U64 => (
1705                     FullInt::U(u128::from(u64::min_value())),
1706                     FullInt::U(u128::from(u64::max_value())),
1707                 ),
1708                 UintTy::U128 => (FullInt::U(u128::min_value()), FullInt::U(u128::max_value())),
1709                 UintTy::Usize => (
1710                     FullInt::U(usize::min_value() as u128),
1711                     FullInt::U(usize::max_value() as u128),
1712                 ),
1713             }),
1714             _ => None,
1715         }
1716     } else {
1717         None
1718     }
1719 }
1720
1721 fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option<FullInt> {
1722     let val = constant(cx, cx.tables, expr)?.0;
1723     if let Constant::Int(const_int) = val {
1724         match cx.tables.expr_ty(expr).sty {
1725             ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
1726             ty::Uint(_) => Some(FullInt::U(const_int)),
1727             _ => None,
1728         }
1729     } else {
1730         None
1731     }
1732 }
1733
1734 fn err_upcast_comparison(cx: &LateContext<'_, '_>, span: Span, expr: &Expr, always: bool) {
1735     if let ExprKind::Cast(ref cast_val, _) = expr.node {
1736         span_lint(
1737             cx,
1738             INVALID_UPCAST_COMPARISONS,
1739             span,
1740             &format!(
1741                 "because of the numeric bounds on `{}` prior to casting, this expression is always {}",
1742                 snippet(cx, cast_val.span, "the expression"),
1743                 if always { "true" } else { "false" },
1744             ),
1745         );
1746     }
1747 }
1748
1749 fn upcast_comparison_bounds_err<'a, 'tcx>(
1750     cx: &LateContext<'a, 'tcx>,
1751     span: Span,
1752     rel: comparisons::Rel,
1753     lhs_bounds: Option<(FullInt, FullInt)>,
1754     lhs: &'tcx Expr,
1755     rhs: &'tcx Expr,
1756     invert: bool,
1757 ) {
1758     use crate::utils::comparisons::*;
1759
1760     if let Some((lb, ub)) = lhs_bounds {
1761         if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
1762             if rel == Rel::Eq || rel == Rel::Ne {
1763                 if norm_rhs_val < lb || norm_rhs_val > ub {
1764                     err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
1765                 }
1766             } else if match rel {
1767                 Rel::Lt => {
1768                     if invert {
1769                         norm_rhs_val < lb
1770                     } else {
1771                         ub < norm_rhs_val
1772                     }
1773                 },
1774                 Rel::Le => {
1775                     if invert {
1776                         norm_rhs_val <= lb
1777                     } else {
1778                         ub <= norm_rhs_val
1779                     }
1780                 },
1781                 Rel::Eq | Rel::Ne => unreachable!(),
1782             } {
1783                 err_upcast_comparison(cx, span, lhs, true)
1784             } else if match rel {
1785                 Rel::Lt => {
1786                     if invert {
1787                         norm_rhs_val >= ub
1788                     } else {
1789                         lb >= norm_rhs_val
1790                     }
1791                 },
1792                 Rel::Le => {
1793                     if invert {
1794                         norm_rhs_val > ub
1795                     } else {
1796                         lb > norm_rhs_val
1797                     }
1798                 },
1799                 Rel::Eq | Rel::Ne => unreachable!(),
1800             } {
1801                 err_upcast_comparison(cx, span, lhs, false)
1802             }
1803         }
1804     }
1805 }
1806
1807 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons {
1808     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
1809         if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.node {
1810             let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
1811             let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
1812                 val
1813             } else {
1814                 return;
1815             };
1816
1817             let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs);
1818             let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs);
1819
1820             upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false);
1821             upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true);
1822         }
1823     }
1824 }
1825
1826 /// **What it does:** Checks for public `impl` or `fn` missing generalization
1827 /// over different hashers and implicitly defaulting to the default hashing
1828 /// algorithm (SipHash).
1829 ///
1830 /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be
1831 /// used with them.
1832 ///
1833 /// **Known problems:** Suggestions for replacing constructors can contain
1834 /// false-positives. Also applying suggestions can require modification of other
1835 /// pieces of code, possibly including external crates.
1836 ///
1837 /// **Example:**
1838 /// ```rust
1839 /// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { ... }
1840 ///
1841 /// pub foo(map: &mut HashMap<i32, i32>) { .. }
1842 /// ```
1843 declare_clippy_lint! {
1844     pub IMPLICIT_HASHER,
1845     style,
1846     "missing generalization over different hashers"
1847 }
1848
1849 pub struct ImplicitHasher;
1850
1851 impl LintPass for ImplicitHasher {
1852     fn get_lints(&self) -> LintArray {
1853         lint_array!(IMPLICIT_HASHER)
1854     }
1855 }
1856
1857 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher {
1858     #[allow(clippy::cast_possible_truncation)]
1859     fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
1860         use crate::syntax_pos::BytePos;
1861
1862         fn suggestion<'a, 'tcx>(
1863             cx: &LateContext<'a, 'tcx>,
1864             db: &mut DiagnosticBuilder<'_>,
1865             generics_span: Span,
1866             generics_suggestion_span: Span,
1867             target: &ImplicitHasherType<'_>,
1868             vis: ImplicitHasherConstructorVisitor<'_, '_, '_>,
1869         ) {
1870             let generics_snip = snippet(cx, generics_span, "");
1871             // trim `<` `>`
1872             let generics_snip = if generics_snip.is_empty() {
1873                 ""
1874             } else {
1875                 &generics_snip[1..generics_snip.len() - 1]
1876             };
1877
1878             multispan_sugg(
1879                 db,
1880                 "consider adding a type parameter".to_string(),
1881                 vec![
1882                     (
1883                         generics_suggestion_span,
1884                         format!(
1885                             "<{}{}S: ::std::hash::BuildHasher{}>",
1886                             generics_snip,
1887                             if generics_snip.is_empty() { "" } else { ", " },
1888                             if vis.suggestions.is_empty() {
1889                                 ""
1890                             } else {
1891                                 // request users to add `Default` bound so that generic constructors can be used
1892                                 " + Default"
1893                             },
1894                         ),
1895                     ),
1896                     (
1897                         target.span(),
1898                         format!("{}<{}, S>", target.type_name(), target.type_arguments(),),
1899                     ),
1900                 ],
1901             );
1902
1903             if !vis.suggestions.is_empty() {
1904                 multispan_sugg(db, "...and use generic constructor".into(), vis.suggestions);
1905             }
1906         }
1907
1908         if !cx.access_levels.is_exported(item.id) {
1909             return;
1910         }
1911
1912         match item.node {
1913             ItemKind::Impl(_, _, _, ref generics, _, ref ty, ref items) => {
1914                 let mut vis = ImplicitHasherTypeVisitor::new(cx);
1915                 vis.visit_ty(ty);
1916
1917                 for target in &vis.found {
1918                     if differing_macro_contexts(item.span, target.span()) {
1919                         return;
1920                     }
1921
1922                     let generics_suggestion_span = generics.span.substitute_dummy({
1923                         let pos = snippet_opt(cx, item.span.until(target.span()))
1924                             .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
1925                         if let Some(pos) = pos {
1926                             Span::new(pos, pos, item.span.data().ctxt)
1927                         } else {
1928                             return;
1929                         }
1930                     });
1931
1932                     let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
1933                     for item in items.iter().map(|item| cx.tcx.hir.impl_item(item.id)) {
1934                         ctr_vis.visit_impl_item(item);
1935                     }
1936
1937                     span_lint_and_then(
1938                         cx,
1939                         IMPLICIT_HASHER,
1940                         target.span(),
1941                         &format!(
1942                             "impl for `{}` should be generalized over different hashers",
1943                             target.type_name()
1944                         ),
1945                         move |db| {
1946                             suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis);
1947                         },
1948                     );
1949                 }
1950             },
1951             ItemKind::Fn(ref decl, .., ref generics, body_id) => {
1952                 let body = cx.tcx.hir.body(body_id);
1953
1954                 for ty in &decl.inputs {
1955                     let mut vis = ImplicitHasherTypeVisitor::new(cx);
1956                     vis.visit_ty(ty);
1957
1958                     for target in &vis.found {
1959                         let generics_suggestion_span = generics.span.substitute_dummy({
1960                             let pos = snippet_opt(cx, item.span.until(body.arguments[0].pat.span))
1961                                 .and_then(|snip| {
1962                                     let i = snip.find("fn")?;
1963                                     Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
1964                                 })
1965                                 .expect("failed to create span for type parameters");
1966                             Span::new(pos, pos, item.span.data().ctxt)
1967                         });
1968
1969                         let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
1970                         ctr_vis.visit_body(body);
1971
1972                         span_lint_and_then(
1973                             cx,
1974                             IMPLICIT_HASHER,
1975                             target.span(),
1976                             &format!(
1977                                 "parameter of type `{}` should be generalized over different hashers",
1978                                 target.type_name()
1979                             ),
1980                             move |db| {
1981                                 suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis);
1982                             },
1983                         );
1984                     }
1985                 }
1986             },
1987             _ => {},
1988         }
1989     }
1990 }
1991
1992 enum ImplicitHasherType<'tcx> {
1993     HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>),
1994     HashSet(Span, Ty<'tcx>, Cow<'static, str>),
1995 }
1996
1997 impl<'tcx> ImplicitHasherType<'tcx> {
1998     /// Checks that `ty` is a target type without a BuildHasher.
1999     fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option<Self> {
2000         if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node {
2001             let params: Vec<_> = path
2002                 .segments
2003                 .last()
2004                 .as_ref()?
2005                 .args
2006                 .as_ref()?
2007                 .args
2008                 .iter()
2009                 .filter_map(|arg| match arg {
2010                     GenericArg::Type(ty) => Some(ty),
2011                     GenericArg::Lifetime(_) => None,
2012                 })
2013                 .collect();
2014             let params_len = params.len();
2015
2016             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
2017
2018             if match_path(path, &paths::HASHMAP) && params_len == 2 {
2019                 Some(ImplicitHasherType::HashMap(
2020                     hir_ty.span,
2021                     ty,
2022                     snippet(cx, params[0].span, "K"),
2023                     snippet(cx, params[1].span, "V"),
2024                 ))
2025             } else if match_path(path, &paths::HASHSET) && params_len == 1 {
2026                 Some(ImplicitHasherType::HashSet(
2027                     hir_ty.span,
2028                     ty,
2029                     snippet(cx, params[0].span, "T"),
2030                 ))
2031             } else {
2032                 None
2033             }
2034         } else {
2035             None
2036         }
2037     }
2038
2039     fn type_name(&self) -> &'static str {
2040         match *self {
2041             ImplicitHasherType::HashMap(..) => "HashMap",
2042             ImplicitHasherType::HashSet(..) => "HashSet",
2043         }
2044     }
2045
2046     fn type_arguments(&self) -> String {
2047         match *self {
2048             ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v),
2049             ImplicitHasherType::HashSet(.., ref t) => format!("{}", t),
2050         }
2051     }
2052
2053     fn ty(&self) -> Ty<'tcx> {
2054         match *self {
2055             ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty,
2056         }
2057     }
2058
2059     fn span(&self) -> Span {
2060         match *self {
2061             ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span,
2062         }
2063     }
2064 }
2065
2066 struct ImplicitHasherTypeVisitor<'a, 'tcx: 'a> {
2067     cx: &'a LateContext<'a, 'tcx>,
2068     found: Vec<ImplicitHasherType<'tcx>>,
2069 }
2070
2071 impl<'a, 'tcx: 'a> ImplicitHasherTypeVisitor<'a, 'tcx> {
2072     fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
2073         Self { cx, found: vec![] }
2074     }
2075 }
2076
2077 impl<'a, 'tcx: 'a> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
2078     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
2079         if let Some(target) = ImplicitHasherType::new(self.cx, t) {
2080             self.found.push(target);
2081         }
2082
2083         walk_ty(self, t);
2084     }
2085
2086     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
2087         NestedVisitorMap::None
2088     }
2089 }
2090
2091 /// Looks for default-hasher-dependent constructors like `HashMap::new`.
2092 struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx: 'a + 'b> {
2093     cx: &'a LateContext<'a, 'tcx>,
2094     body: &'a TypeckTables<'tcx>,
2095     target: &'b ImplicitHasherType<'tcx>,
2096     suggestions: BTreeMap<Span, String>,
2097 }
2098
2099 impl<'a, 'b, 'tcx: 'a + 'b> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
2100     fn new(cx: &'a LateContext<'a, 'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self {
2101         Self {
2102             cx,
2103             body: cx.tables,
2104             target,
2105             suggestions: BTreeMap::new(),
2106         }
2107     }
2108 }
2109
2110 impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
2111     fn visit_body(&mut self, body: &'tcx Body) {
2112         self.body = self.cx.tcx.body_tables(body.id());
2113         walk_body(self, body);
2114     }
2115
2116     fn visit_expr(&mut self, e: &'tcx Expr) {
2117         if_chain! {
2118             if let ExprKind::Call(ref fun, ref args) = e.node;
2119             if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.node;
2120             if let TyKind::Path(QPath::Resolved(None, ref ty_path)) = ty.node;
2121             then {
2122                 if !same_tys(self.cx, self.target.ty(), self.body.expr_ty(e)) {
2123                     return;
2124                 }
2125
2126                 if match_path(ty_path, &paths::HASHMAP) {
2127                     if method.ident.name == "new" {
2128                         self.suggestions
2129                             .insert(e.span, "HashMap::default()".to_string());
2130                     } else if method.ident.name == "with_capacity" {
2131                         self.suggestions.insert(
2132                             e.span,
2133                             format!(
2134                                 "HashMap::with_capacity_and_hasher({}, Default::default())",
2135                                 snippet(self.cx, args[0].span, "capacity"),
2136                             ),
2137                         );
2138                     }
2139                 } else if match_path(ty_path, &paths::HASHSET) {
2140                     if method.ident.name == "new" {
2141                         self.suggestions
2142                             .insert(e.span, "HashSet::default()".to_string());
2143                     } else if method.ident.name == "with_capacity" {
2144                         self.suggestions.insert(
2145                             e.span,
2146                             format!(
2147                                 "HashSet::with_capacity_and_hasher({}, Default::default())",
2148                                 snippet(self.cx, args[0].span, "capacity"),
2149                             ),
2150                         );
2151                     }
2152                 }
2153             }
2154         }
2155
2156         walk_expr(self, e);
2157     }
2158
2159     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
2160         NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir)
2161     }
2162 }