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