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