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