]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/types.rs
f4bb648d15a48d30e7077bf66243ce5b986b7dab
[rust.git] / clippy_lints / src / types.rs
1 #![allow(rustc::default_hash_types)]
2
3 use std::borrow::Cow;
4 use std::cmp::Ordering;
5 use std::collections::BTreeMap;
6
7 use if_chain::if_chain;
8 use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy};
9 use rustc_errors::{Applicability, DiagnosticBuilder};
10 use rustc_hir as hir;
11 use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
12 use rustc_hir::{
13     BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem,
14     ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt, StmtKind,
15     TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
16 };
17 use rustc_lint::{LateContext, LateLintPass, LintContext};
18 use rustc_middle::hir::map::Map;
19 use rustc_middle::lint::in_external_macro;
20 use rustc_middle::ty::TypeFoldable;
21 use rustc_middle::ty::{self, InferTy, Ty, TyCtxt, TyS, TypeckResults};
22 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
23 use rustc_span::hygiene::{ExpnKind, MacroKind};
24 use rustc_span::source_map::Span;
25 use rustc_span::symbol::sym;
26 use rustc_target::abi::LayoutOf;
27 use rustc_target::spec::abi::Abi;
28 use rustc_typeck::hir_ty_to_ty;
29
30 use crate::consts::{constant, Constant};
31 use crate::utils::paths;
32 use crate::utils::{
33     clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_type_diagnostic_item,
34     last_path_segment, match_def_path, match_path, method_chain_args, multispan_sugg, numeric_literal::NumericLiteral,
35     qpath_res, reindent_multiline, sext, snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite,
36     span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext,
37 };
38
39 declare_clippy_lint! {
40     /// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
41     /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
42     ///
43     /// **Why is this bad?** `Vec` already keeps its contents in a separate area on
44     /// the heap. So if you `Box` it, you just add another level of indirection
45     /// without any benefit whatsoever.
46     ///
47     /// **Known problems:** None.
48     ///
49     /// **Example:**
50     /// ```rust,ignore
51     /// struct X {
52     ///     values: Box<Vec<Foo>>,
53     /// }
54     /// ```
55     ///
56     /// Better:
57     ///
58     /// ```rust,ignore
59     /// struct X {
60     ///     values: Vec<Foo>,
61     /// }
62     /// ```
63     pub BOX_VEC,
64     perf,
65     "usage of `Box<Vec<T>>`, vector elements are already on the heap"
66 }
67
68 declare_clippy_lint! {
69     /// **What it does:** Checks for use of `Vec<Box<T>>` where T: Sized anywhere in the code.
70     /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
71     ///
72     /// **Why is this bad?** `Vec` already keeps its contents in a separate area on
73     /// the heap. So if you `Box` its contents, you just add another level of indirection.
74     ///
75     /// **Known problems:** Vec<Box<T: Sized>> makes sense if T is a large type (see #3530,
76     /// 1st comment).
77     ///
78     /// **Example:**
79     /// ```rust
80     /// struct X {
81     ///     values: Vec<Box<i32>>,
82     /// }
83     /// ```
84     ///
85     /// Better:
86     ///
87     /// ```rust
88     /// struct X {
89     ///     values: Vec<i32>,
90     /// }
91     /// ```
92     pub VEC_BOX,
93     complexity,
94     "usage of `Vec<Box<T>>` where T: Sized, vector elements are already on the heap"
95 }
96
97 declare_clippy_lint! {
98     /// **What it does:** Checks for use of `Option<Option<_>>` in function signatures and type
99     /// definitions
100     ///
101     /// **Why is this bad?** `Option<_>` represents an optional value. `Option<Option<_>>`
102     /// represents an optional optional value which is logically the same thing as an optional
103     /// value but has an unneeded extra level of wrapping.
104     ///
105     /// If you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases,
106     /// consider a custom `enum` instead, with clear names for each case.
107     ///
108     /// **Known problems:** None.
109     ///
110     /// **Example**
111     /// ```rust
112     /// fn get_data() -> Option<Option<u32>> {
113     ///     None
114     /// }
115     /// ```
116     ///
117     /// Better:
118     ///
119     /// ```rust
120     /// pub enum Contents {
121     ///     Data(Vec<u8>), // Was Some(Some(Vec<u8>))
122     ///     NotYetFetched, // Was Some(None)
123     ///     None,          // Was None
124     /// }
125     ///
126     /// fn get_data() -> Contents {
127     ///     Contents::None
128     /// }
129     /// ```
130     pub OPTION_OPTION,
131     pedantic,
132     "usage of `Option<Option<T>>`"
133 }
134
135 declare_clippy_lint! {
136     /// **What it does:** Checks for usage of any `LinkedList`, suggesting to use a
137     /// `Vec` or a `VecDeque` (formerly called `RingBuf`).
138     ///
139     /// **Why is this bad?** Gankro says:
140     ///
141     /// > The TL;DR of `LinkedList` is that it's built on a massive amount of
142     /// pointers and indirection.
143     /// > It wastes memory, it has terrible cache locality, and is all-around slow.
144     /// `RingBuf`, while
145     /// > "only" amortized for push/pop, should be faster in the general case for
146     /// almost every possible
147     /// > workload, and isn't even amortized at all if you can predict the capacity
148     /// you need.
149     /// >
150     /// > `LinkedList`s are only really good if you're doing a lot of merging or
151     /// splitting of lists.
152     /// > This is because they can just mangle some pointers instead of actually
153     /// copying the data. Even
154     /// > if you're doing a lot of insertion in the middle of the list, `RingBuf`
155     /// can still be better
156     /// > because of how expensive it is to seek to the middle of a `LinkedList`.
157     ///
158     /// **Known problems:** False positives – the instances where using a
159     /// `LinkedList` makes sense are few and far between, but they can still happen.
160     ///
161     /// **Example:**
162     /// ```rust
163     /// # use std::collections::LinkedList;
164     /// let x: LinkedList<usize> = LinkedList::new();
165     /// ```
166     pub LINKEDLIST,
167     pedantic,
168     "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a `VecDeque`"
169 }
170
171 declare_clippy_lint! {
172     /// **What it does:** Checks for use of `&Box<T>` anywhere in the code.
173     /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
174     ///
175     /// **Why is this bad?** Any `&Box<T>` can also be a `&T`, which is more
176     /// general.
177     ///
178     /// **Known problems:** None.
179     ///
180     /// **Example:**
181     /// ```rust,ignore
182     /// fn foo(bar: &Box<T>) { ... }
183     /// ```
184     ///
185     /// Better:
186     ///
187     /// ```rust,ignore
188     /// fn foo(bar: &T) { ... }
189     /// ```
190     pub BORROWED_BOX,
191     complexity,
192     "a borrow of a boxed type"
193 }
194
195 declare_clippy_lint! {
196     /// **What it does:** Checks for use of redundant allocations anywhere in the code.
197     ///
198     /// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Box<T>>`, `Box<&T>`
199     /// add an unnecessary level of indirection.
200     ///
201     /// **Known problems:** None.
202     ///
203     /// **Example:**
204     /// ```rust
205     /// # use std::rc::Rc;
206     /// fn foo(bar: Rc<&usize>) {}
207     /// ```
208     ///
209     /// Better:
210     ///
211     /// ```rust
212     /// fn foo(bar: &usize) {}
213     /// ```
214     pub REDUNDANT_ALLOCATION,
215     perf,
216     "redundant allocation"
217 }
218
219 declare_clippy_lint! {
220     /// **What it does:** Checks for `Rc<T>` and `Arc<T>` when `T` is a mutable buffer type such as `String` or `Vec`.
221     ///
222     /// **Why is this bad?** Expressions such as `Rc<String>` usually have no advantage over `Rc<str>`, since
223     /// it is larger and involves an extra level of indirection, and doesn't implement `Borrow<str>`.
224     ///
225     /// While mutating a buffer type would still be possible with `Rc::get_mut()`, it only
226     /// works if there are no additional references yet, which usually defeats the purpose of
227     /// enclosing it in a shared ownership type. Instead, additionally wrapping the inner
228     /// type with an interior mutable container (such as `RefCell` or `Mutex`) would normally
229     /// be used.
230     ///
231     /// **Known problems:** This pattern can be desirable to avoid the overhead of a `RefCell` or `Mutex` for
232     /// cases where mutation only happens before there are any additional references.
233     ///
234     /// **Example:**
235     /// ```rust,ignore
236     /// # use std::rc::Rc;
237     /// fn foo(interned: Rc<String>) { ... }
238     /// ```
239     ///
240     /// Better:
241     ///
242     /// ```rust,ignore
243     /// fn foo(interned: Rc<str>) { ... }
244     /// ```
245     pub RC_BUFFER,
246     restriction,
247     "shared ownership of a buffer type"
248 }
249
250 pub struct Types {
251     vec_box_size_threshold: u64,
252 }
253
254 impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER]);
255
256 impl<'tcx> LateLintPass<'tcx> for Types {
257     fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
258         // Skip trait implementations; see issue #605.
259         if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) {
260             if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
261                 return;
262             }
263         }
264
265         self.check_fn_decl(cx, decl);
266     }
267
268     fn check_struct_field(&mut self, cx: &LateContext<'_>, field: &hir::StructField<'_>) {
269         self.check_ty(cx, &field.ty, false);
270     }
271
272     fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
273         match item.kind {
274             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_ty(cx, ty, false),
275             TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, &sig.decl),
276             _ => (),
277         }
278     }
279
280     fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
281         if let Some(ref ty) = local.ty {
282             self.check_ty(cx, ty, true);
283         }
284     }
285 }
286
287 /// Checks if `qpath` has last segment with type parameter matching `path`
288 fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> {
289     let last = last_path_segment(qpath);
290     if_chain! {
291         if let Some(ref params) = last.args;
292         if !params.parenthesized;
293         if let Some(ty) = params.args.iter().find_map(|arg| match arg {
294             GenericArg::Type(ty) => Some(ty),
295             _ => None,
296         });
297         if let TyKind::Path(ref qpath) = ty.kind;
298         if let Some(did) = qpath_res(cx, qpath, ty.hir_id).opt_def_id();
299         if match_def_path(cx, did, path);
300         then {
301             return Some(ty.span);
302         }
303     }
304     None
305 }
306
307 fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
308     if match_type_parameter(cx, qpath, &paths::STRING).is_some() {
309         return Some("str");
310     }
311     if match_type_parameter(cx, qpath, &paths::OS_STRING).is_some() {
312         return Some("std::ffi::OsStr");
313     }
314     if match_type_parameter(cx, qpath, &paths::PATH_BUF).is_some() {
315         return Some("std::path::Path");
316     }
317     None
318 }
319
320 fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
321     let last = last_path_segment(qpath);
322     if_chain! {
323         if let Some(ref params) = last.args;
324         if !params.parenthesized;
325         if let Some(ty) = params.args.iter().find_map(|arg| match arg {
326             GenericArg::Type(ty) => Some(ty),
327             _ => None,
328         });
329         if let TyKind::Rptr(..) = ty.kind;
330         then {
331             return Some(ty.span);
332         }
333     }
334     None
335 }
336
337 impl Types {
338     pub fn new(vec_box_size_threshold: u64) -> Self {
339         Self { vec_box_size_threshold }
340     }
341
342     fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>) {
343         for input in decl.inputs {
344             self.check_ty(cx, input, false);
345         }
346
347         if let FnRetTy::Return(ref ty) = decl.output {
348             self.check_ty(cx, ty, false);
349         }
350     }
351
352     /// Recursively check for `TypePass` lints in the given type. Stop at the first
353     /// lint found.
354     ///
355     /// The parameter `is_local` distinguishes the context of the type; types from
356     /// local bindings should only be checked for the `BORROWED_BOX` lint.
357     #[allow(clippy::too_many_lines)]
358     fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, is_local: bool) {
359         if hir_ty.span.from_expansion() {
360             return;
361         }
362         match hir_ty.kind {
363             TyKind::Path(ref qpath) if !is_local => {
364                 let hir_id = hir_ty.hir_id;
365                 let res = qpath_res(cx, qpath, hir_id);
366                 if let Some(def_id) = res.opt_def_id() {
367                     if Some(def_id) == cx.tcx.lang_items().owned_box() {
368                         if let Some(span) = match_borrows_parameter(cx, qpath) {
369                             let mut applicability = Applicability::MachineApplicable;
370                             span_lint_and_sugg(
371                                 cx,
372                                 REDUNDANT_ALLOCATION,
373                                 hir_ty.span,
374                                 "usage of `Box<&T>`",
375                                 "try",
376                                 snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
377                                 applicability,
378                             );
379                             return; // don't recurse into the type
380                         }
381                         if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
382                             span_lint_and_help(
383                                 cx,
384                                 BOX_VEC,
385                                 hir_ty.span,
386                                 "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`",
387                                 None,
388                                 "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation.",
389                             );
390                             return; // don't recurse into the type
391                         }
392                     } else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
393                         if let Some(span) = match_type_parameter(cx, qpath, &paths::RC) {
394                             let mut applicability = Applicability::MachineApplicable;
395                             span_lint_and_sugg(
396                                 cx,
397                                 REDUNDANT_ALLOCATION,
398                                 hir_ty.span,
399                                 "usage of `Rc<Rc<T>>`",
400                                 "try",
401                                 snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
402                                 applicability,
403                             );
404                             return; // don't recurse into the type
405                         }
406                         if match_type_parameter(cx, qpath, &paths::BOX).is_some() {
407                             let box_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
408                                 GenericArg::Type(ty) => match &ty.kind {
409                                     TyKind::Path(qpath) => qpath,
410                                     _ => return,
411                                 },
412                                 _ => return,
413                             };
414                             let inner_span = match &last_path_segment(&box_ty).args.unwrap().args[0] {
415                                 GenericArg::Type(ty) => ty.span,
416                                 _ => return,
417                             };
418                             let mut applicability = Applicability::MachineApplicable;
419                             span_lint_and_sugg(
420                                 cx,
421                                 REDUNDANT_ALLOCATION,
422                                 hir_ty.span,
423                                 "usage of `Rc<Box<T>>`",
424                                 "try",
425                                 format!(
426                                     "Rc<{}>",
427                                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
428                                 ),
429                                 applicability,
430                             );
431                             return; // don't recurse into the type
432                         }
433                         if let Some(alternate) = match_buffer_type(cx, qpath) {
434                             span_lint_and_sugg(
435                                 cx,
436                                 RC_BUFFER,
437                                 hir_ty.span,
438                                 "usage of `Rc<T>` when T is a buffer type",
439                                 "try",
440                                 format!("Rc<{}>", alternate),
441                                 Applicability::MachineApplicable,
442                             );
443                             return; // don't recurse into the type
444                         }
445                         if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
446                             let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
447                                 GenericArg::Type(ty) => match &ty.kind {
448                                     TyKind::Path(qpath) => qpath,
449                                     _ => return,
450                                 },
451                                 _ => return,
452                             };
453                             let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
454                                 GenericArg::Type(ty) => ty.span,
455                                 _ => return,
456                             };
457                             let mut applicability = Applicability::MachineApplicable;
458                             span_lint_and_sugg(
459                                 cx,
460                                 RC_BUFFER,
461                                 hir_ty.span,
462                                 "usage of `Rc<T>` when T is a buffer type",
463                                 "try",
464                                 format!(
465                                     "Rc<[{}]>",
466                                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
467                                 ),
468                                 Applicability::MachineApplicable,
469                             );
470                             return; // don't recurse into the type
471                         }
472                         if let Some(span) = match_borrows_parameter(cx, qpath) {
473                             let mut applicability = Applicability::MachineApplicable;
474                             span_lint_and_sugg(
475                                 cx,
476                                 REDUNDANT_ALLOCATION,
477                                 hir_ty.span,
478                                 "usage of `Rc<&T>`",
479                                 "try",
480                                 snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
481                                 applicability,
482                             );
483                             return; // don't recurse into the type
484                         }
485                     } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
486                         if let Some(alternate) = match_buffer_type(cx, qpath) {
487                             span_lint_and_sugg(
488                                 cx,
489                                 RC_BUFFER,
490                                 hir_ty.span,
491                                 "usage of `Arc<T>` when T is a buffer type",
492                                 "try",
493                                 format!("Arc<{}>", alternate),
494                                 Applicability::MachineApplicable,
495                             );
496                             return; // don't recurse into the type
497                         }
498                         if match_type_parameter(cx, qpath, &paths::VEC).is_some() {
499                             let vec_ty = match &last_path_segment(qpath).args.unwrap().args[0] {
500                                 GenericArg::Type(ty) => match &ty.kind {
501                                     TyKind::Path(qpath) => qpath,
502                                     _ => return,
503                                 },
504                                 _ => return,
505                             };
506                             let inner_span = match &last_path_segment(&vec_ty).args.unwrap().args[0] {
507                                 GenericArg::Type(ty) => ty.span,
508                                 _ => return,
509                             };
510                             let mut applicability = Applicability::MachineApplicable;
511                             span_lint_and_sugg(
512                                 cx,
513                                 RC_BUFFER,
514                                 hir_ty.span,
515                                 "usage of `Arc<T>` when T is a buffer type",
516                                 "try",
517                                 format!(
518                                     "Arc<[{}]>",
519                                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
520                                 ),
521                                 Applicability::MachineApplicable,
522                             );
523                             return; // don't recurse into the type
524                         }
525                     } else if cx.tcx.is_diagnostic_item(sym!(vec_type), def_id) {
526                         if_chain! {
527                             // Get the _ part of Vec<_>
528                             if let Some(ref last) = last_path_segment(qpath).args;
529                             if let Some(ty) = last.args.iter().find_map(|arg| match arg {
530                                 GenericArg::Type(ty) => Some(ty),
531                                 _ => None,
532                             });
533                             // ty is now _ at this point
534                             if let TyKind::Path(ref ty_qpath) = ty.kind;
535                             let res = qpath_res(cx, ty_qpath, ty.hir_id);
536                             if let Some(def_id) = res.opt_def_id();
537                             if Some(def_id) == cx.tcx.lang_items().owned_box();
538                             // At this point, we know ty is Box<T>, now get T
539                             if let Some(ref last) = last_path_segment(ty_qpath).args;
540                             if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg {
541                                 GenericArg::Type(ty) => Some(ty),
542                                 _ => None,
543                             });
544                             let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
545                             if !ty_ty.has_escaping_bound_vars();
546                             if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env);
547                             if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
548                             if ty_ty_size <= self.vec_box_size_threshold;
549                             then {
550                                 span_lint_and_sugg(
551                                     cx,
552                                     VEC_BOX,
553                                     hir_ty.span,
554                                     "`Vec<T>` is already on the heap, the boxing is unnecessary.",
555                                     "try",
556                                     format!("Vec<{}>", ty_ty),
557                                     Applicability::MachineApplicable,
558                                 );
559                                 return; // don't recurse into the type
560                             }
561                         }
562                     } else if cx.tcx.is_diagnostic_item(sym!(option_type), def_id) {
563                         if match_type_parameter(cx, qpath, &paths::OPTION).is_some() {
564                             span_lint(
565                                 cx,
566                                 OPTION_OPTION,
567                                 hir_ty.span,
568                                 "consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
569                                  enum if you need to distinguish all 3 cases",
570                             );
571                             return; // don't recurse into the type
572                         }
573                     } else if match_def_path(cx, def_id, &paths::LINKED_LIST) {
574                         span_lint_and_help(
575                             cx,
576                             LINKEDLIST,
577                             hir_ty.span,
578                             "I see you're using a LinkedList! Perhaps you meant some other data structure?",
579                             None,
580                             "a `VecDeque` might work",
581                         );
582                         return; // don't recurse into the type
583                     }
584                 }
585                 match *qpath {
586                     QPath::Resolved(Some(ref ty), ref p) => {
587                         self.check_ty(cx, ty, is_local);
588                         for ty in p.segments.iter().flat_map(|seg| {
589                             seg.args
590                                 .as_ref()
591                                 .map_or_else(|| [].iter(), |params| params.args.iter())
592                                 .filter_map(|arg| match arg {
593                                     GenericArg::Type(ty) => Some(ty),
594                                     _ => None,
595                                 })
596                         }) {
597                             self.check_ty(cx, ty, is_local);
598                         }
599                     },
600                     QPath::Resolved(None, ref p) => {
601                         for ty in p.segments.iter().flat_map(|seg| {
602                             seg.args
603                                 .as_ref()
604                                 .map_or_else(|| [].iter(), |params| params.args.iter())
605                                 .filter_map(|arg| match arg {
606                                     GenericArg::Type(ty) => Some(ty),
607                                     _ => None,
608                                 })
609                         }) {
610                             self.check_ty(cx, ty, is_local);
611                         }
612                     },
613                     QPath::TypeRelative(ref ty, ref seg) => {
614                         self.check_ty(cx, ty, is_local);
615                         if let Some(ref params) = seg.args {
616                             for ty in params.args.iter().filter_map(|arg| match arg {
617                                 GenericArg::Type(ty) => Some(ty),
618                                 _ => None,
619                             }) {
620                                 self.check_ty(cx, ty, is_local);
621                             }
622                         }
623                     },
624                     QPath::LangItem(..) => {},
625                 }
626             },
627             TyKind::Rptr(ref lt, ref mut_ty) => self.check_ty_rptr(cx, hir_ty, is_local, lt, mut_ty),
628             // recurse
629             TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => {
630                 self.check_ty(cx, ty, is_local)
631             },
632             TyKind::Tup(tys) => {
633                 for ty in tys {
634                     self.check_ty(cx, ty, is_local);
635                 }
636             },
637             _ => {},
638         }
639     }
640
641     fn check_ty_rptr(
642         &mut self,
643         cx: &LateContext<'_>,
644         hir_ty: &hir::Ty<'_>,
645         is_local: bool,
646         lt: &Lifetime,
647         mut_ty: &MutTy<'_>,
648     ) {
649         match mut_ty.ty.kind {
650             TyKind::Path(ref qpath) => {
651                 let hir_id = mut_ty.ty.hir_id;
652                 let def = qpath_res(cx, qpath, hir_id);
653                 if_chain! {
654                     if let Some(def_id) = def.opt_def_id();
655                     if Some(def_id) == cx.tcx.lang_items().owned_box();
656                     if let QPath::Resolved(None, ref path) = *qpath;
657                     if let [ref bx] = *path.segments;
658                     if let Some(ref params) = bx.args;
659                     if !params.parenthesized;
660                     if let Some(inner) = params.args.iter().find_map(|arg| match arg {
661                         GenericArg::Type(ty) => Some(ty),
662                         _ => None,
663                     });
664                     then {
665                         if is_any_trait(inner) {
666                             // Ignore `Box<Any>` types; see issue #1884 for details.
667                             return;
668                         }
669
670                         let ltopt = if lt.is_elided() {
671                             String::new()
672                         } else {
673                             format!("{} ", lt.name.ident().as_str())
674                         };
675
676                         if mut_ty.mutbl == Mutability::Mut {
677                             // Ignore `&mut Box<T>` types; see issue #2907 for
678                             // details.
679                             return;
680                         }
681                         span_lint_and_sugg(
682                             cx,
683                             BORROWED_BOX,
684                             hir_ty.span,
685                             "you seem to be trying to use `&Box<T>`. Consider using just `&T`",
686                             "try",
687                             format!(
688                                 "&{}{}",
689                                 ltopt,
690                                 &snippet(cx, inner.span, "..")
691                             ),
692                             // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
693                             // because the trait impls of it will break otherwise;
694                             // and there may be other cases that result in invalid code.
695                             // For example, type coercion doesn't work nicely.
696                             Applicability::Unspecified,
697                         );
698                         return; // don't recurse into the type
699                     }
700                 };
701                 self.check_ty(cx, &mut_ty.ty, is_local);
702             },
703             _ => self.check_ty(cx, &mut_ty.ty, is_local),
704         }
705     }
706 }
707
708 // Returns true if given type is `Any` trait.
709 fn is_any_trait(t: &hir::Ty<'_>) -> bool {
710     if_chain! {
711         if let TyKind::TraitObject(ref traits, _) = t.kind;
712         if !traits.is_empty();
713         // Only Send/Sync can be used as additional traits, so it is enough to
714         // check only the first trait.
715         if match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT);
716         then {
717             return true;
718         }
719     }
720
721     false
722 }
723
724 declare_clippy_lint! {
725     /// **What it does:** Checks for binding a unit value.
726     ///
727     /// **Why is this bad?** A unit value cannot usefully be used anywhere. So
728     /// binding one is kind of pointless.
729     ///
730     /// **Known problems:** None.
731     ///
732     /// **Example:**
733     /// ```rust
734     /// let x = {
735     ///     1;
736     /// };
737     /// ```
738     pub LET_UNIT_VALUE,
739     pedantic,
740     "creating a `let` binding to a value of unit type, which usually can't be used afterwards"
741 }
742
743 declare_lint_pass!(LetUnitValue => [LET_UNIT_VALUE]);
744
745 impl<'tcx> LateLintPass<'tcx> for LetUnitValue {
746     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
747         if let StmtKind::Local(ref local) = stmt.kind {
748             if is_unit(cx.typeck_results().pat_ty(&local.pat)) {
749                 if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() {
750                     return;
751                 }
752                 if higher::is_from_for_desugar(local) {
753                     return;
754                 }
755                 span_lint_and_then(
756                     cx,
757                     LET_UNIT_VALUE,
758                     stmt.span,
759                     "this let-binding has unit value",
760                     |diag| {
761                         if let Some(expr) = &local.init {
762                             let snip = snippet_with_macro_callsite(cx, expr.span, "()");
763                             diag.span_suggestion(
764                                 stmt.span,
765                                 "omit the `let` binding",
766                                 format!("{};", snip),
767                                 Applicability::MachineApplicable, // snippet
768                             );
769                         }
770                     },
771                 );
772             }
773         }
774     }
775 }
776
777 declare_clippy_lint! {
778     /// **What it does:** Checks for comparisons to unit. This includes all binary
779     /// comparisons (like `==` and `<`) and asserts.
780     ///
781     /// **Why is this bad?** Unit is always equal to itself, and thus is just a
782     /// clumsily written constant. Mostly this happens when someone accidentally
783     /// adds semicolons at the end of the operands.
784     ///
785     /// **Known problems:** None.
786     ///
787     /// **Example:**
788     /// ```rust
789     /// # fn foo() {};
790     /// # fn bar() {};
791     /// # fn baz() {};
792     /// if {
793     ///     foo();
794     /// } == {
795     ///     bar();
796     /// } {
797     ///     baz();
798     /// }
799     /// ```
800     /// is equal to
801     /// ```rust
802     /// # fn foo() {};
803     /// # fn bar() {};
804     /// # fn baz() {};
805     /// {
806     ///     foo();
807     ///     bar();
808     ///     baz();
809     /// }
810     /// ```
811     ///
812     /// For asserts:
813     /// ```rust
814     /// # fn foo() {};
815     /// # fn bar() {};
816     /// assert_eq!({ foo(); }, { bar(); });
817     /// ```
818     /// will always succeed
819     pub UNIT_CMP,
820     correctness,
821     "comparing unit values"
822 }
823
824 declare_lint_pass!(UnitCmp => [UNIT_CMP]);
825
826 impl<'tcx> LateLintPass<'tcx> for UnitCmp {
827     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
828         if expr.span.from_expansion() {
829             if let Some(callee) = expr.span.source_callee() {
830                 if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
831                     if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
832                         let op = cmp.node;
833                         if op.is_comparison() && is_unit(cx.typeck_results().expr_ty(left)) {
834                             let result = match &*symbol.as_str() {
835                                 "assert_eq" | "debug_assert_eq" => "succeed",
836                                 "assert_ne" | "debug_assert_ne" => "fail",
837                                 _ => return,
838                             };
839                             span_lint(
840                                 cx,
841                                 UNIT_CMP,
842                                 expr.span,
843                                 &format!(
844                                     "`{}` of unit values detected. This will always {}",
845                                     symbol.as_str(),
846                                     result
847                                 ),
848                             );
849                         }
850                     }
851                 }
852             }
853             return;
854         }
855         if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
856             let op = cmp.node;
857             if op.is_comparison() && is_unit(cx.typeck_results().expr_ty(left)) {
858                 let result = match op {
859                     BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true",
860                     _ => "false",
861                 };
862                 span_lint(
863                     cx,
864                     UNIT_CMP,
865                     expr.span,
866                     &format!(
867                         "{}-comparison of unit values detected. This will always be {}",
868                         op.as_str(),
869                         result
870                     ),
871                 );
872             }
873         }
874     }
875 }
876
877 declare_clippy_lint! {
878     /// **What it does:** Checks for passing a unit value as an argument to a function without using a
879     /// unit literal (`()`).
880     ///
881     /// **Why is this bad?** This is likely the result of an accidental semicolon.
882     ///
883     /// **Known problems:** None.
884     ///
885     /// **Example:**
886     /// ```rust,ignore
887     /// foo({
888     ///     let a = bar();
889     ///     baz(a);
890     /// })
891     /// ```
892     pub UNIT_ARG,
893     complexity,
894     "passing unit to a function"
895 }
896
897 declare_lint_pass!(UnitArg => [UNIT_ARG]);
898
899 impl<'tcx> LateLintPass<'tcx> for UnitArg {
900     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
901         if expr.span.from_expansion() {
902             return;
903         }
904
905         // apparently stuff in the desugaring of `?` can trigger this
906         // so check for that here
907         // only the calls to `Try::from_error` is marked as desugared,
908         // so we need to check both the current Expr and its parent.
909         if is_questionmark_desugar_marked_call(expr) {
910             return;
911         }
912         if_chain! {
913             let map = &cx.tcx.hir();
914             let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
915             if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
916             if is_questionmark_desugar_marked_call(parent_expr);
917             then {
918                 return;
919             }
920         }
921
922         match expr.kind {
923             ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
924                 let args_to_recover = args
925                     .iter()
926                     .filter(|arg| {
927                         if is_unit(cx.typeck_results().expr_ty(arg)) && !is_unit_literal(arg) {
928                             !matches!(&arg.kind, ExprKind::Match(.., MatchSource::TryDesugar))
929                         } else {
930                             false
931                         }
932                     })
933                     .collect::<Vec<_>>();
934                 if !args_to_recover.is_empty() {
935                     lint_unit_args(cx, expr, &args_to_recover);
936                 }
937             },
938             _ => (),
939         }
940     }
941 }
942
943 fn fmt_stmts_and_call(
944     cx: &LateContext<'_>,
945     call_expr: &Expr<'_>,
946     call_snippet: &str,
947     args_snippets: &[impl AsRef<str>],
948     non_empty_block_args_snippets: &[impl AsRef<str>],
949 ) -> String {
950     let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0);
951     let call_snippet_with_replacements = args_snippets
952         .iter()
953         .fold(call_snippet.to_owned(), |acc, arg| acc.replacen(arg.as_ref(), "()", 1));
954
955     let mut stmts_and_call = non_empty_block_args_snippets
956         .iter()
957         .map(|it| it.as_ref().to_owned())
958         .collect::<Vec<_>>();
959     stmts_and_call.push(call_snippet_with_replacements);
960     stmts_and_call = stmts_and_call
961         .into_iter()
962         .map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned())
963         .collect();
964
965     let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
966     // expr is not in a block statement or result expression position, wrap in a block
967     let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id));
968     if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
969         let block_indent = call_expr_indent + 4;
970         stmts_and_call_snippet =
971             reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned();
972         stmts_and_call_snippet = format!(
973             "{{\n{}{}\n{}}}",
974             " ".repeat(block_indent),
975             &stmts_and_call_snippet,
976             " ".repeat(call_expr_indent)
977         );
978     }
979     stmts_and_call_snippet
980 }
981
982 fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) {
983     let mut applicability = Applicability::MachineApplicable;
984     let (singular, plural) = if args_to_recover.len() > 1 {
985         ("", "s")
986     } else {
987         ("a ", "")
988     };
989     span_lint_and_then(
990         cx,
991         UNIT_ARG,
992         expr.span,
993         &format!("passing {}unit value{} to a function", singular, plural),
994         |db| {
995             let mut or = "";
996             args_to_recover
997                 .iter()
998                 .filter_map(|arg| {
999                     if_chain! {
1000                         if let ExprKind::Block(block, _) = arg.kind;
1001                         if block.expr.is_none();
1002                         if let Some(last_stmt) = block.stmts.iter().last();
1003                         if let StmtKind::Semi(last_expr) = last_stmt.kind;
1004                         if let Some(snip) = snippet_opt(cx, last_expr.span);
1005                         then {
1006                             Some((
1007                                 last_stmt.span,
1008                                 snip,
1009                             ))
1010                         }
1011                         else {
1012                             None
1013                         }
1014                     }
1015                 })
1016                 .for_each(|(span, sugg)| {
1017                     db.span_suggestion(
1018                         span,
1019                         "remove the semicolon from the last statement in the block",
1020                         sugg,
1021                         Applicability::MaybeIncorrect,
1022                     );
1023                     or = "or ";
1024                     applicability = Applicability::MaybeIncorrect;
1025                 });
1026
1027             let arg_snippets: Vec<String> = args_to_recover
1028                 .iter()
1029                 .filter_map(|arg| snippet_opt(cx, arg.span))
1030                 .collect();
1031             let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover
1032                 .iter()
1033                 .filter(|arg| !is_empty_block(arg))
1034                 .filter_map(|arg| snippet_opt(cx, arg.span))
1035                 .collect();
1036
1037             if let Some(call_snippet) = snippet_opt(cx, expr.span) {
1038                 let sugg = fmt_stmts_and_call(
1039                     cx,
1040                     expr,
1041                     &call_snippet,
1042                     &arg_snippets,
1043                     &arg_snippets_without_empty_blocks,
1044                 );
1045
1046                 if arg_snippets_without_empty_blocks.is_empty() {
1047                     db.multipart_suggestion(
1048                         &format!("use {}unit literal{} instead", singular, plural),
1049                         args_to_recover
1050                             .iter()
1051                             .map(|arg| (arg.span, "()".to_string()))
1052                             .collect::<Vec<_>>(),
1053                         applicability,
1054                     );
1055                 } else {
1056                     let plural = arg_snippets_without_empty_blocks.len() > 1;
1057                     let empty_or_s = if plural { "s" } else { "" };
1058                     let it_or_them = if plural { "them" } else { "it" };
1059                     db.span_suggestion(
1060                         expr.span,
1061                         &format!(
1062                             "{}move the expression{} in front of the call and replace {} with the unit literal `()`",
1063                             or, empty_or_s, it_or_them
1064                         ),
1065                         sugg,
1066                         applicability,
1067                     );
1068                 }
1069             }
1070         },
1071     );
1072 }
1073
1074 fn is_empty_block(expr: &Expr<'_>) -> bool {
1075     matches!(
1076         expr.kind,
1077         ExprKind::Block(
1078             Block {
1079                 stmts: &[], expr: None, ..
1080             },
1081             _,
1082         )
1083     )
1084 }
1085
1086 fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool {
1087     use rustc_span::hygiene::DesugaringKind;
1088     if let ExprKind::Call(ref callee, _) = expr.kind {
1089         callee.span.is_desugaring(DesugaringKind::QuestionMark)
1090     } else {
1091         false
1092     }
1093 }
1094
1095 fn is_unit(ty: Ty<'_>) -> bool {
1096     matches!(ty.kind(), ty::Tuple(slice) if slice.is_empty())
1097 }
1098
1099 fn is_unit_literal(expr: &Expr<'_>) -> bool {
1100     matches!(expr.kind, ExprKind::Tup(ref slice) if slice.is_empty())
1101 }
1102
1103 declare_clippy_lint! {
1104     /// **What it does:** Checks for casts from any numerical to a float type where
1105     /// the receiving type cannot store all values from the original type without
1106     /// rounding errors. This possible rounding is to be expected, so this lint is
1107     /// `Allow` by default.
1108     ///
1109     /// Basically, this warns on casting any integer with 32 or more bits to `f32`
1110     /// or any 64-bit integer to `f64`.
1111     ///
1112     /// **Why is this bad?** It's not bad at all. But in some applications it can be
1113     /// helpful to know where precision loss can take place. This lint can help find
1114     /// those places in the code.
1115     ///
1116     /// **Known problems:** None.
1117     ///
1118     /// **Example:**
1119     /// ```rust
1120     /// let x = u64::MAX;
1121     /// x as f64;
1122     /// ```
1123     pub CAST_PRECISION_LOSS,
1124     pedantic,
1125     "casts that cause loss of precision, e.g., `x as f32` where `x: u64`"
1126 }
1127
1128 declare_clippy_lint! {
1129     /// **What it does:** Checks for casts from a signed to an unsigned numerical
1130     /// type. In this case, negative values wrap around to large positive values,
1131     /// which can be quite surprising in practice. However, as the cast works as
1132     /// defined, this lint is `Allow` by default.
1133     ///
1134     /// **Why is this bad?** Possibly surprising results. You can activate this lint
1135     /// as a one-time check to see where numerical wrapping can arise.
1136     ///
1137     /// **Known problems:** None.
1138     ///
1139     /// **Example:**
1140     /// ```rust
1141     /// let y: i8 = -1;
1142     /// y as u128; // will return 18446744073709551615
1143     /// ```
1144     pub CAST_SIGN_LOSS,
1145     pedantic,
1146     "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`"
1147 }
1148
1149 declare_clippy_lint! {
1150     /// **What it does:** Checks for casts between numerical types that may
1151     /// truncate large values. This is expected behavior, so the cast is `Allow` by
1152     /// default.
1153     ///
1154     /// **Why is this bad?** In some problem domains, it is good practice to avoid
1155     /// truncation. This lint can be activated to help assess where additional
1156     /// checks could be beneficial.
1157     ///
1158     /// **Known problems:** None.
1159     ///
1160     /// **Example:**
1161     /// ```rust
1162     /// fn as_u8(x: u64) -> u8 {
1163     ///     x as u8
1164     /// }
1165     /// ```
1166     pub CAST_POSSIBLE_TRUNCATION,
1167     pedantic,
1168     "casts that may cause truncation of the value, e.g., `x as u8` where `x: u32`, or `x as i32` where `x: f32`"
1169 }
1170
1171 declare_clippy_lint! {
1172     /// **What it does:** Checks for casts from an unsigned type to a signed type of
1173     /// the same size. Performing such a cast is a 'no-op' for the compiler,
1174     /// i.e., nothing is changed at the bit level, and the binary representation of
1175     /// the value is reinterpreted. This can cause wrapping if the value is too big
1176     /// for the target signed type. However, the cast works as defined, so this lint
1177     /// is `Allow` by default.
1178     ///
1179     /// **Why is this bad?** While such a cast is not bad in itself, the results can
1180     /// be surprising when this is not the intended behavior, as demonstrated by the
1181     /// example below.
1182     ///
1183     /// **Known problems:** None.
1184     ///
1185     /// **Example:**
1186     /// ```rust
1187     /// u32::MAX as i32; // will yield a value of `-1`
1188     /// ```
1189     pub CAST_POSSIBLE_WRAP,
1190     pedantic,
1191     "casts that may cause wrapping around the value, e.g., `x as i32` where `x: u32` and `x > i32::MAX`"
1192 }
1193
1194 declare_clippy_lint! {
1195     /// **What it does:** Checks for casts between numerical types that may
1196     /// be replaced by safe conversion functions.
1197     ///
1198     /// **Why is this bad?** Rust's `as` keyword will perform many kinds of
1199     /// conversions, including silently lossy conversions. Conversion functions such
1200     /// as `i32::from` will only perform lossless conversions. Using the conversion
1201     /// functions prevents conversions from turning into silent lossy conversions if
1202     /// the types of the input expressions ever change, and make it easier for
1203     /// people reading the code to know that the conversion is lossless.
1204     ///
1205     /// **Known problems:** None.
1206     ///
1207     /// **Example:**
1208     /// ```rust
1209     /// fn as_u64(x: u8) -> u64 {
1210     ///     x as u64
1211     /// }
1212     /// ```
1213     ///
1214     /// Using `::from` would look like this:
1215     ///
1216     /// ```rust
1217     /// fn as_u64(x: u8) -> u64 {
1218     ///     u64::from(x)
1219     /// }
1220     /// ```
1221     pub CAST_LOSSLESS,
1222     pedantic,
1223     "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`"
1224 }
1225
1226 declare_clippy_lint! {
1227     /// **What it does:** Checks for casts to the same type, casts of int literals to integer types
1228     /// and casts of float literals to float types.
1229     ///
1230     /// **Why is this bad?** It's just unnecessary.
1231     ///
1232     /// **Known problems:** None.
1233     ///
1234     /// **Example:**
1235     /// ```rust
1236     /// let _ = 2i32 as i32;
1237     /// let _ = 0.5 as f32;
1238     /// ```
1239     pub UNNECESSARY_CAST,
1240     complexity,
1241     "cast to the same type, e.g., `x as i32` where `x: i32`"
1242 }
1243
1244 declare_clippy_lint! {
1245     /// **What it does:** Checks for casts from a less-strictly-aligned pointer to a
1246     /// more-strictly-aligned pointer
1247     ///
1248     /// **Why is this bad?** Dereferencing the resulting pointer may be undefined
1249     /// behavior.
1250     ///
1251     /// **Known problems:** Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar
1252     /// on the resulting pointer is fine. Is over-zealous: Casts with manual alignment checks or casts like
1253     /// u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis.
1254     ///
1255     /// **Example:**
1256     /// ```rust
1257     /// let _ = (&1u8 as *const u8) as *const u16;
1258     /// let _ = (&mut 1u8 as *mut u8) as *mut u16;
1259     /// ```
1260     pub CAST_PTR_ALIGNMENT,
1261     pedantic,
1262     "cast from a pointer to a more-strictly-aligned pointer"
1263 }
1264
1265 declare_clippy_lint! {
1266     /// **What it does:** Checks for casts of function pointers to something other than usize
1267     ///
1268     /// **Why is this bad?**
1269     /// Casting a function pointer to anything other than usize/isize is not portable across
1270     /// architectures, because you end up losing bits if the target type is too small or end up with a
1271     /// bunch of extra bits that waste space and add more instructions to the final binary than
1272     /// strictly necessary for the problem
1273     ///
1274     /// Casting to isize also doesn't make sense since there are no signed addresses.
1275     ///
1276     /// **Example**
1277     ///
1278     /// ```rust
1279     /// // Bad
1280     /// fn fun() -> i32 { 1 }
1281     /// let a = fun as i64;
1282     ///
1283     /// // Good
1284     /// fn fun2() -> i32 { 1 }
1285     /// let a = fun2 as usize;
1286     /// ```
1287     pub FN_TO_NUMERIC_CAST,
1288     style,
1289     "casting a function pointer to a numeric type other than usize"
1290 }
1291
1292 declare_clippy_lint! {
1293     /// **What it does:** Checks for casts of a function pointer to a numeric type not wide enough to
1294     /// store address.
1295     ///
1296     /// **Why is this bad?**
1297     /// Such a cast discards some bits of the function's address. If this is intended, it would be more
1298     /// clearly expressed by casting to usize first, then casting the usize to the intended type (with
1299     /// a comment) to perform the truncation.
1300     ///
1301     /// **Example**
1302     ///
1303     /// ```rust
1304     /// // Bad
1305     /// fn fn1() -> i16 {
1306     ///     1
1307     /// };
1308     /// let _ = fn1 as i32;
1309     ///
1310     /// // Better: Cast to usize first, then comment with the reason for the truncation
1311     /// fn fn2() -> i16 {
1312     ///     1
1313     /// };
1314     /// let fn_ptr = fn2 as usize;
1315     /// let fn_ptr_truncated = fn_ptr as i32;
1316     /// ```
1317     pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
1318     style,
1319     "casting a function pointer to a numeric type not wide enough to store the address"
1320 }
1321
1322 /// Returns the size in bits of an integral type.
1323 /// Will return 0 if the type is not an int or uint variant
1324 fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 {
1325     match typ.kind() {
1326         ty::Int(i) => match i {
1327             IntTy::Isize => tcx.data_layout.pointer_size.bits(),
1328             IntTy::I8 => 8,
1329             IntTy::I16 => 16,
1330             IntTy::I32 => 32,
1331             IntTy::I64 => 64,
1332             IntTy::I128 => 128,
1333         },
1334         ty::Uint(i) => match i {
1335             UintTy::Usize => tcx.data_layout.pointer_size.bits(),
1336             UintTy::U8 => 8,
1337             UintTy::U16 => 16,
1338             UintTy::U32 => 32,
1339             UintTy::U64 => 64,
1340             UintTy::U128 => 128,
1341         },
1342         _ => 0,
1343     }
1344 }
1345
1346 fn is_isize_or_usize(typ: Ty<'_>) -> bool {
1347     matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize))
1348 }
1349
1350 fn span_precision_loss_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to_f64: bool) {
1351     let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
1352     let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
1353     let arch_dependent_str = "on targets with 64-bit wide pointers ";
1354     let from_nbits_str = if arch_dependent {
1355         "64".to_owned()
1356     } else if is_isize_or_usize(cast_from) {
1357         "32 or 64".to_owned()
1358     } else {
1359         int_ty_to_nbits(cast_from, cx.tcx).to_string()
1360     };
1361     span_lint(
1362         cx,
1363         CAST_PRECISION_LOSS,
1364         expr.span,
1365         &format!(
1366             "casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
1367              but `{1}`'s mantissa is only {4} bits wide)",
1368             cast_from,
1369             if cast_to_f64 { "f64" } else { "f32" },
1370             if arch_dependent { arch_dependent_str } else { "" },
1371             from_nbits_str,
1372             mantissa_nbits
1373         ),
1374     );
1375 }
1376
1377 fn should_strip_parens(op: &Expr<'_>, snip: &str) -> bool {
1378     if let ExprKind::Binary(_, _, _) = op.kind {
1379         if snip.starts_with('(') && snip.ends_with(')') {
1380             return true;
1381         }
1382     }
1383     false
1384 }
1385
1386 fn span_lossless_lint(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1387     // Do not suggest using From in consts/statics until it is valid to do so (see #2267).
1388     if in_constant(cx, expr.hir_id) {
1389         return;
1390     }
1391     // The suggestion is to use a function call, so if the original expression
1392     // has parens on the outside, they are no longer needed.
1393     let mut applicability = Applicability::MachineApplicable;
1394     let opt = snippet_opt(cx, op.span);
1395     let sugg = opt.as_ref().map_or_else(
1396         || {
1397             applicability = Applicability::HasPlaceholders;
1398             ".."
1399         },
1400         |snip| {
1401             if should_strip_parens(op, snip) {
1402                 &snip[1..snip.len() - 1]
1403             } else {
1404                 snip.as_str()
1405             }
1406         },
1407     );
1408
1409     span_lint_and_sugg(
1410         cx,
1411         CAST_LOSSLESS,
1412         expr.span,
1413         &format!(
1414             "casting `{}` to `{}` may become silently lossy if you later change the type",
1415             cast_from, cast_to
1416         ),
1417         "try",
1418         format!("{}::from({})", cast_to, sugg),
1419         applicability,
1420     );
1421 }
1422
1423 enum ArchSuffix {
1424     _32,
1425     _64,
1426     None,
1427 }
1428
1429 fn check_loss_of_sign(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1430     if !cast_from.is_signed() || cast_to.is_signed() {
1431         return;
1432     }
1433
1434     // don't lint for positive constants
1435     let const_val = constant(cx, &cx.typeck_results(), op);
1436     if_chain! {
1437         if let Some((const_val, _)) = const_val;
1438         if let Constant::Int(n) = const_val;
1439         if let ty::Int(ity) = *cast_from.kind();
1440         if sext(cx.tcx, n, ity) >= 0;
1441         then {
1442             return
1443         }
1444     }
1445
1446     // don't lint for the result of methods that always return non-negative values
1447     if let ExprKind::MethodCall(ref path, _, _, _) = op.kind {
1448         let mut method_name = path.ident.name.as_str();
1449         let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
1450
1451         if_chain! {
1452             if method_name == "unwrap";
1453             if let Some(arglist) = method_chain_args(op, &["unwrap"]);
1454             if let ExprKind::MethodCall(ref inner_path, _, _, _) = &arglist[0][0].kind;
1455             then {
1456                 method_name = inner_path.ident.name.as_str();
1457             }
1458         }
1459
1460         if allowed_methods.iter().any(|&name| method_name == name) {
1461             return;
1462         }
1463     }
1464
1465     span_lint(
1466         cx,
1467         CAST_SIGN_LOSS,
1468         expr.span,
1469         &format!(
1470             "casting `{}` to `{}` may lose the sign of the value",
1471             cast_from, cast_to
1472         ),
1473     );
1474 }
1475
1476 fn check_truncation_and_wrapping(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1477     let arch_64_suffix = " on targets with 64-bit wide pointers";
1478     let arch_32_suffix = " on targets with 32-bit wide pointers";
1479     let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed();
1480     let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
1481     let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
1482     let (span_truncation, suffix_truncation, span_wrap, suffix_wrap) =
1483         match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
1484             (true, true) | (false, false) => (
1485                 to_nbits < from_nbits,
1486                 ArchSuffix::None,
1487                 to_nbits == from_nbits && cast_unsigned_to_signed,
1488                 ArchSuffix::None,
1489             ),
1490             (true, false) => (
1491                 to_nbits <= 32,
1492                 if to_nbits == 32 {
1493                     ArchSuffix::_64
1494                 } else {
1495                     ArchSuffix::None
1496                 },
1497                 to_nbits <= 32 && cast_unsigned_to_signed,
1498                 ArchSuffix::_32,
1499             ),
1500             (false, true) => (
1501                 from_nbits == 64,
1502                 ArchSuffix::_32,
1503                 cast_unsigned_to_signed,
1504                 if from_nbits == 64 {
1505                     ArchSuffix::_64
1506                 } else {
1507                     ArchSuffix::_32
1508                 },
1509             ),
1510         };
1511     if span_truncation {
1512         span_lint(
1513             cx,
1514             CAST_POSSIBLE_TRUNCATION,
1515             expr.span,
1516             &format!(
1517                 "casting `{}` to `{}` may truncate the value{}",
1518                 cast_from,
1519                 cast_to,
1520                 match suffix_truncation {
1521                     ArchSuffix::_32 => arch_32_suffix,
1522                     ArchSuffix::_64 => arch_64_suffix,
1523                     ArchSuffix::None => "",
1524                 }
1525             ),
1526         );
1527     }
1528     if span_wrap {
1529         span_lint(
1530             cx,
1531             CAST_POSSIBLE_WRAP,
1532             expr.span,
1533             &format!(
1534                 "casting `{}` to `{}` may wrap around the value{}",
1535                 cast_from,
1536                 cast_to,
1537                 match suffix_wrap {
1538                     ArchSuffix::_32 => arch_32_suffix,
1539                     ArchSuffix::_64 => arch_64_suffix,
1540                     ArchSuffix::None => "",
1541                 }
1542             ),
1543         );
1544     }
1545 }
1546
1547 fn check_lossless(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1548     let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed();
1549     let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
1550     let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
1551     if !is_isize_or_usize(cast_from) && !is_isize_or_usize(cast_to) && from_nbits < to_nbits && !cast_signed_to_unsigned
1552     {
1553         span_lossless_lint(cx, expr, op, cast_from, cast_to);
1554     }
1555 }
1556
1557 declare_lint_pass!(Casts => [
1558     CAST_PRECISION_LOSS,
1559     CAST_SIGN_LOSS,
1560     CAST_POSSIBLE_TRUNCATION,
1561     CAST_POSSIBLE_WRAP,
1562     CAST_LOSSLESS,
1563     UNNECESSARY_CAST,
1564     CAST_PTR_ALIGNMENT,
1565     FN_TO_NUMERIC_CAST,
1566     FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
1567 ]);
1568
1569 // Check if the given type is either `core::ffi::c_void` or
1570 // one of the platform specific `libc::<platform>::c_void` of libc.
1571 fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
1572     if let ty::Adt(adt, _) = ty.kind() {
1573         let names = cx.get_def_path(adt.did);
1574
1575         if names.is_empty() {
1576             return false;
1577         }
1578         if names[0] == sym!(libc) || names[0] == sym::core && *names.last().unwrap() == sym!(c_void) {
1579             return true;
1580         }
1581     }
1582     false
1583 }
1584
1585 /// Returns the mantissa bits wide of a fp type.
1586 /// Will return 0 if the type is not a fp
1587 fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
1588     match typ.kind() {
1589         ty::Float(FloatTy::F32) => 23,
1590         ty::Float(FloatTy::F64) | ty::Infer(InferTy::FloatVar(_)) => 52,
1591         _ => 0,
1592     }
1593 }
1594
1595 impl<'tcx> LateLintPass<'tcx> for Casts {
1596     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
1597         if expr.span.from_expansion() {
1598             return;
1599         }
1600         if let ExprKind::Cast(ref ex, _) = expr.kind {
1601             let (cast_from, cast_to) = (cx.typeck_results().expr_ty(ex), cx.typeck_results().expr_ty(expr));
1602             lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
1603             if let Some(lit) = get_numeric_literal(ex) {
1604                 let literal_str = snippet_opt(cx, lit.span).unwrap_or_default();
1605
1606                 if_chain! {
1607                     if let LitKind::Int(n, _) = lit.node;
1608                     if let Some(src) = snippet_opt(cx, lit.span);
1609                     if cast_to.is_floating_point();
1610                     if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node);
1611                     let from_nbits = 128 - n.leading_zeros();
1612                     let to_nbits = fp_ty_mantissa_nbits(cast_to);
1613                     if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal();
1614                     then {
1615                         show_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
1616                         return;
1617                     }
1618                 }
1619
1620                 match lit.node {
1621                     LitKind::Int(_, LitIntType::Unsuffixed) if cast_to.is_integral() => {
1622                         show_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
1623                     },
1624                     LitKind::Float(_, LitFloatType::Unsuffixed) if cast_to.is_floating_point() => {
1625                         show_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
1626                     },
1627                     LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => (),
1628                     _ => {
1629                         if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
1630                             span_lint(
1631                                 cx,
1632                                 UNNECESSARY_CAST,
1633                                 expr.span,
1634                                 &format!(
1635                                     "casting to the same type is unnecessary (`{}` -> `{}`)",
1636                                     cast_from, cast_to
1637                                 ),
1638                             );
1639                         }
1640                     },
1641                 }
1642             }
1643             if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
1644                 lint_numeric_casts(cx, expr, ex, cast_from, cast_to);
1645             }
1646
1647             lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
1648         }
1649     }
1650 }
1651
1652 fn get_numeric_literal<'e>(expr: &'e Expr<'e>) -> Option<&'e Lit> {
1653     match expr.kind {
1654         ExprKind::Lit(ref lit) => Some(lit),
1655         ExprKind::Unary(UnOp::UnNeg, e) => {
1656             if let ExprKind::Lit(ref lit) = e.kind {
1657                 Some(lit)
1658             } else {
1659                 None
1660             }
1661         },
1662         _ => None,
1663     }
1664 }
1665
1666 fn show_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &str, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1667     let literal_kind_name = if cast_from.is_integral() { "integer" } else { "float" };
1668     span_lint_and_sugg(
1669         cx,
1670         UNNECESSARY_CAST,
1671         expr.span,
1672         &format!("casting {} literal to `{}` is unnecessary", literal_kind_name, cast_to),
1673         "try",
1674         format!("{}_{}", literal_str, cast_to),
1675         Applicability::MachineApplicable,
1676     );
1677 }
1678
1679 fn lint_numeric_casts<'tcx>(
1680     cx: &LateContext<'tcx>,
1681     expr: &Expr<'tcx>,
1682     cast_expr: &Expr<'_>,
1683     cast_from: Ty<'tcx>,
1684     cast_to: Ty<'tcx>,
1685 ) {
1686     match (cast_from.is_integral(), cast_to.is_integral()) {
1687         (true, false) => {
1688             let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
1689             let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() {
1690                 32
1691             } else {
1692                 64
1693             };
1694             if is_isize_or_usize(cast_from) || from_nbits >= to_nbits {
1695                 span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64);
1696             }
1697             if from_nbits < to_nbits {
1698                 span_lossless_lint(cx, expr, cast_expr, cast_from, cast_to);
1699             }
1700         },
1701         (false, true) => {
1702             span_lint(
1703                 cx,
1704                 CAST_POSSIBLE_TRUNCATION,
1705                 expr.span,
1706                 &format!("casting `{}` to `{}` may truncate the value", cast_from, cast_to),
1707             );
1708             if !cast_to.is_signed() {
1709                 span_lint(
1710                     cx,
1711                     CAST_SIGN_LOSS,
1712                     expr.span,
1713                     &format!(
1714                         "casting `{}` to `{}` may lose the sign of the value",
1715                         cast_from, cast_to
1716                     ),
1717                 );
1718             }
1719         },
1720         (true, true) => {
1721             check_loss_of_sign(cx, expr, cast_expr, cast_from, cast_to);
1722             check_truncation_and_wrapping(cx, expr, cast_from, cast_to);
1723             check_lossless(cx, expr, cast_expr, cast_from, cast_to);
1724         },
1725         (false, false) => {
1726             if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.kind(), &cast_to.kind()) {
1727                 span_lint(
1728                     cx,
1729                     CAST_POSSIBLE_TRUNCATION,
1730                     expr.span,
1731                     "casting `f64` to `f32` may truncate the value",
1732                 );
1733             }
1734             if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.kind(), &cast_to.kind()) {
1735                 span_lossless_lint(cx, expr, cast_expr, cast_from, cast_to);
1736             }
1737         },
1738     }
1739 }
1740
1741 fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) {
1742     if_chain! {
1743         if let ty::RawPtr(from_ptr_ty) = &cast_from.kind();
1744         if let ty::RawPtr(to_ptr_ty) = &cast_to.kind();
1745         if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty);
1746         if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty);
1747         if from_layout.align.abi < to_layout.align.abi;
1748         // with c_void, we inherently need to trust the user
1749         if !is_c_void(cx, from_ptr_ty.ty);
1750         // when casting from a ZST, we don't know enough to properly lint
1751         if !from_layout.is_zst();
1752         then {
1753             span_lint(
1754                 cx,
1755                 CAST_PTR_ALIGNMENT,
1756                 expr.span,
1757                 &format!(
1758                     "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
1759                     cast_from,
1760                     cast_to,
1761                     from_layout.align.abi.bytes(),
1762                     to_layout.align.abi.bytes(),
1763                 ),
1764             );
1765         }
1766     }
1767 }
1768
1769 fn lint_fn_to_numeric_cast(
1770     cx: &LateContext<'_>,
1771     expr: &Expr<'_>,
1772     cast_expr: &Expr<'_>,
1773     cast_from: Ty<'_>,
1774     cast_to: Ty<'_>,
1775 ) {
1776     // We only want to check casts to `ty::Uint` or `ty::Int`
1777     match cast_to.kind() {
1778         ty::Uint(_) | ty::Int(..) => { /* continue on */ },
1779         _ => return,
1780     }
1781     match cast_from.kind() {
1782         ty::FnDef(..) | ty::FnPtr(_) => {
1783             let mut applicability = Applicability::MaybeIncorrect;
1784             let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
1785
1786             let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
1787             if to_nbits < cx.tcx.data_layout.pointer_size.bits() {
1788                 span_lint_and_sugg(
1789                     cx,
1790                     FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
1791                     expr.span,
1792                     &format!(
1793                         "casting function pointer `{}` to `{}`, which truncates the value",
1794                         from_snippet, cast_to
1795                     ),
1796                     "try",
1797                     format!("{} as usize", from_snippet),
1798                     applicability,
1799                 );
1800             } else if *cast_to.kind() != ty::Uint(UintTy::Usize) {
1801                 span_lint_and_sugg(
1802                     cx,
1803                     FN_TO_NUMERIC_CAST,
1804                     expr.span,
1805                     &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
1806                     "try",
1807                     format!("{} as usize", from_snippet),
1808                     applicability,
1809                 );
1810             }
1811         },
1812         _ => {},
1813     }
1814 }
1815
1816 declare_clippy_lint! {
1817     /// **What it does:** Checks for types used in structs, parameters and `let`
1818     /// declarations above a certain complexity threshold.
1819     ///
1820     /// **Why is this bad?** Too complex types make the code less readable. Consider
1821     /// using a `type` definition to simplify them.
1822     ///
1823     /// **Known problems:** None.
1824     ///
1825     /// **Example:**
1826     /// ```rust
1827     /// # use std::rc::Rc;
1828     /// struct Foo {
1829     ///     inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
1830     /// }
1831     /// ```
1832     pub TYPE_COMPLEXITY,
1833     complexity,
1834     "usage of very complex types that might be better factored into `type` definitions"
1835 }
1836
1837 pub struct TypeComplexity {
1838     threshold: u64,
1839 }
1840
1841 impl TypeComplexity {
1842     #[must_use]
1843     pub fn new(threshold: u64) -> Self {
1844         Self { threshold }
1845     }
1846 }
1847
1848 impl_lint_pass!(TypeComplexity => [TYPE_COMPLEXITY]);
1849
1850 impl<'tcx> LateLintPass<'tcx> for TypeComplexity {
1851     fn check_fn(
1852         &mut self,
1853         cx: &LateContext<'tcx>,
1854         _: FnKind<'tcx>,
1855         decl: &'tcx FnDecl<'_>,
1856         _: &'tcx Body<'_>,
1857         _: Span,
1858         _: HirId,
1859     ) {
1860         self.check_fndecl(cx, decl);
1861     }
1862
1863     fn check_struct_field(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::StructField<'_>) {
1864         // enum variants are also struct fields now
1865         self.check_type(cx, &field.ty);
1866     }
1867
1868     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
1869         match item.kind {
1870             ItemKind::Static(ref ty, _, _) | ItemKind::Const(ref ty, _) => self.check_type(cx, ty),
1871             // functions, enums, structs, impls and traits are covered
1872             _ => (),
1873         }
1874     }
1875
1876     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
1877         match item.kind {
1878             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty),
1879             TraitItemKind::Fn(FnSig { ref decl, .. }, TraitFn::Required(_)) => self.check_fndecl(cx, decl),
1880             // methods with default impl are covered by check_fn
1881             _ => (),
1882         }
1883     }
1884
1885     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
1886         match item.kind {
1887             ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty),
1888             // methods are covered by check_fn
1889             _ => (),
1890         }
1891     }
1892
1893     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
1894         if let Some(ref ty) = local.ty {
1895             self.check_type(cx, ty);
1896         }
1897     }
1898 }
1899
1900 impl<'tcx> TypeComplexity {
1901     fn check_fndecl(&self, cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>) {
1902         for arg in decl.inputs {
1903             self.check_type(cx, arg);
1904         }
1905         if let FnRetTy::Return(ref ty) = decl.output {
1906             self.check_type(cx, ty);
1907         }
1908     }
1909
1910     fn check_type(&self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) {
1911         if ty.span.from_expansion() {
1912             return;
1913         }
1914         let score = {
1915             let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
1916             visitor.visit_ty(ty);
1917             visitor.score
1918         };
1919
1920         if score > self.threshold {
1921             span_lint(
1922                 cx,
1923                 TYPE_COMPLEXITY,
1924                 ty.span,
1925                 "very complex type used. Consider factoring parts into `type` definitions",
1926             );
1927         }
1928     }
1929 }
1930
1931 /// Walks a type and assigns a complexity score to it.
1932 struct TypeComplexityVisitor {
1933     /// total complexity score of the type
1934     score: u64,
1935     /// current nesting level
1936     nest: u64,
1937 }
1938
1939 impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
1940     type Map = Map<'tcx>;
1941
1942     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
1943         let (add_score, sub_nest) = match ty.kind {
1944             // _, &x and *x have only small overhead; don't mess with nesting level
1945             TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0),
1946
1947             // the "normal" components of a type: named types, arrays/tuples
1948             TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1),
1949
1950             // function types bring a lot of overhead
1951             TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
1952
1953             TyKind::TraitObject(ref param_bounds, _) => {
1954                 let has_lifetime_parameters = param_bounds.iter().any(|bound| {
1955                     bound
1956                         .bound_generic_params
1957                         .iter()
1958                         .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. }))
1959                 });
1960                 if has_lifetime_parameters {
1961                     // complex trait bounds like A<'a, 'b>
1962                     (50 * self.nest, 1)
1963                 } else {
1964                     // simple trait bounds like A + B
1965                     (20 * self.nest, 0)
1966                 }
1967             },
1968
1969             _ => (0, 0),
1970         };
1971         self.score += add_score;
1972         self.nest += sub_nest;
1973         walk_ty(self, ty);
1974         self.nest -= sub_nest;
1975     }
1976     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
1977         NestedVisitorMap::None
1978     }
1979 }
1980
1981 declare_clippy_lint! {
1982     /// **What it does:** Checks for expressions where a character literal is cast
1983     /// to `u8` and suggests using a byte literal instead.
1984     ///
1985     /// **Why is this bad?** In general, casting values to smaller types is
1986     /// error-prone and should be avoided where possible. In the particular case of
1987     /// converting a character literal to u8, it is easy to avoid by just using a
1988     /// byte literal instead. As an added bonus, `b'a'` is even slightly shorter
1989     /// than `'a' as u8`.
1990     ///
1991     /// **Known problems:** None.
1992     ///
1993     /// **Example:**
1994     /// ```rust,ignore
1995     /// 'x' as u8
1996     /// ```
1997     ///
1998     /// A better version, using the byte literal:
1999     ///
2000     /// ```rust,ignore
2001     /// b'x'
2002     /// ```
2003     pub CHAR_LIT_AS_U8,
2004     complexity,
2005     "casting a character literal to `u8` truncates"
2006 }
2007
2008 declare_lint_pass!(CharLitAsU8 => [CHAR_LIT_AS_U8]);
2009
2010 impl<'tcx> LateLintPass<'tcx> for CharLitAsU8 {
2011     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
2012         if_chain! {
2013             if !expr.span.from_expansion();
2014             if let ExprKind::Cast(e, _) = &expr.kind;
2015             if let ExprKind::Lit(l) = &e.kind;
2016             if let LitKind::Char(c) = l.node;
2017             if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(expr).kind();
2018             then {
2019                 let mut applicability = Applicability::MachineApplicable;
2020                 let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability);
2021
2022                 span_lint_and_then(
2023                     cx,
2024                     CHAR_LIT_AS_U8,
2025                     expr.span,
2026                     "casting a character literal to `u8` truncates",
2027                     |diag| {
2028                         diag.note("`char` is four bytes wide, but `u8` is a single byte");
2029
2030                         if c.is_ascii() {
2031                             diag.span_suggestion(
2032                                 expr.span,
2033                                 "use a byte literal instead",
2034                                 format!("b{}", snippet),
2035                                 applicability,
2036                             );
2037                         }
2038                 });
2039             }
2040         }
2041     }
2042 }
2043
2044 declare_clippy_lint! {
2045     /// **What it does:** Checks for comparisons where one side of the relation is
2046     /// either the minimum or maximum value for its type and warns if it involves a
2047     /// case that is always true or always false. Only integer and boolean types are
2048     /// checked.
2049     ///
2050     /// **Why is this bad?** An expression like `min <= x` may misleadingly imply
2051     /// that it is possible for `x` to be less than the minimum. Expressions like
2052     /// `max < x` are probably mistakes.
2053     ///
2054     /// **Known problems:** For `usize` the size of the current compile target will
2055     /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
2056     /// a comparison to detect target pointer width will trigger this lint. One can
2057     /// use `mem::sizeof` and compare its value or conditional compilation
2058     /// attributes
2059     /// like `#[cfg(target_pointer_width = "64")] ..` instead.
2060     ///
2061     /// **Example:**
2062     ///
2063     /// ```rust
2064     /// let vec: Vec<isize> = Vec::new();
2065     /// if vec.len() <= 0 {}
2066     /// if 100 > i32::MAX {}
2067     /// ```
2068     pub ABSURD_EXTREME_COMPARISONS,
2069     correctness,
2070     "a comparison with a maximum or minimum value that is always true or false"
2071 }
2072
2073 declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]);
2074
2075 enum ExtremeType {
2076     Minimum,
2077     Maximum,
2078 }
2079
2080 struct ExtremeExpr<'a> {
2081     which: ExtremeType,
2082     expr: &'a Expr<'a>,
2083 }
2084
2085 enum AbsurdComparisonResult {
2086     AlwaysFalse,
2087     AlwaysTrue,
2088     InequalityImpossible,
2089 }
2090
2091 fn is_cast_between_fixed_and_target<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
2092     if let ExprKind::Cast(ref cast_exp, _) = expr.kind {
2093         let precast_ty = cx.typeck_results().expr_ty(cast_exp);
2094         let cast_ty = cx.typeck_results().expr_ty(expr);
2095
2096         return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty);
2097     }
2098
2099     false
2100 }
2101
2102 fn detect_absurd_comparison<'tcx>(
2103     cx: &LateContext<'tcx>,
2104     op: BinOpKind,
2105     lhs: &'tcx Expr<'_>,
2106     rhs: &'tcx Expr<'_>,
2107 ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> {
2108     use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible};
2109     use crate::types::ExtremeType::{Maximum, Minimum};
2110     use crate::utils::comparisons::{normalize_comparison, Rel};
2111
2112     // absurd comparison only makes sense on primitive types
2113     // primitive types don't implement comparison operators with each other
2114     if cx.typeck_results().expr_ty(lhs) != cx.typeck_results().expr_ty(rhs) {
2115         return None;
2116     }
2117
2118     // comparisons between fix sized types and target sized types are considered unanalyzable
2119     if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) {
2120         return None;
2121     }
2122
2123     let (rel, normalized_lhs, normalized_rhs) = normalize_comparison(op, lhs, rhs)?;
2124
2125     let lx = detect_extreme_expr(cx, normalized_lhs);
2126     let rx = detect_extreme_expr(cx, normalized_rhs);
2127
2128     Some(match rel {
2129         Rel::Lt => {
2130             match (lx, rx) {
2131                 (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x
2132                 (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min
2133                 _ => return None,
2134             }
2135         },
2136         Rel::Le => {
2137             match (lx, rx) {
2138                 (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x
2139                 (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x
2140                 (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min
2141                 (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max
2142                 _ => return None,
2143             }
2144         },
2145         Rel::Ne | Rel::Eq => return None,
2146     })
2147 }
2148
2149 fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
2150     use crate::types::ExtremeType::{Maximum, Minimum};
2151
2152     let ty = cx.typeck_results().expr_ty(expr);
2153
2154     let cv = constant(cx, cx.typeck_results(), expr)?.0;
2155
2156     let which = match (ty.kind(), cv) {
2157         (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum,
2158         (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => {
2159             Minimum
2160         },
2161
2162         (&ty::Bool, Constant::Bool(true)) => Maximum,
2163         (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => {
2164             Maximum
2165         },
2166         (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => Maximum,
2167
2168         _ => return None,
2169     };
2170     Some(ExtremeExpr { which, expr })
2171 }
2172
2173 impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons {
2174     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
2175         use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible};
2176         use crate::types::ExtremeType::{Maximum, Minimum};
2177
2178         if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind {
2179             if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) {
2180                 if !expr.span.from_expansion() {
2181                     let msg = "this comparison involving the minimum or maximum element for this \
2182                                type contains a case that is always true or always false";
2183
2184                     let conclusion = match result {
2185                         AlwaysFalse => "this comparison is always false".to_owned(),
2186                         AlwaysTrue => "this comparison is always true".to_owned(),
2187                         InequalityImpossible => format!(
2188                             "the case where the two sides are not equal never occurs, consider using `{} == {}` \
2189                              instead",
2190                             snippet(cx, lhs.span, "lhs"),
2191                             snippet(cx, rhs.span, "rhs")
2192                         ),
2193                     };
2194
2195                     let help = format!(
2196                         "because `{}` is the {} value for this type, {}",
2197                         snippet(cx, culprit.expr.span, "x"),
2198                         match culprit.which {
2199                             Minimum => "minimum",
2200                             Maximum => "maximum",
2201                         },
2202                         conclusion
2203                     );
2204
2205                     span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help);
2206                 }
2207             }
2208         }
2209     }
2210 }
2211
2212 declare_clippy_lint! {
2213     /// **What it does:** Checks for comparisons where the relation is always either
2214     /// true or false, but where one side has been upcast so that the comparison is
2215     /// necessary. Only integer types are checked.
2216     ///
2217     /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300`
2218     /// will mistakenly imply that it is possible for `x` to be outside the range of
2219     /// `u8`.
2220     ///
2221     /// **Known problems:**
2222     /// https://github.com/rust-lang/rust-clippy/issues/886
2223     ///
2224     /// **Example:**
2225     /// ```rust
2226     /// let x: u8 = 1;
2227     /// (x as u32) > 300;
2228     /// ```
2229     pub INVALID_UPCAST_COMPARISONS,
2230     pedantic,
2231     "a comparison involving an upcast which is always true or false"
2232 }
2233
2234 declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
2235
2236 #[derive(Copy, Clone, Debug, Eq)]
2237 enum FullInt {
2238     S(i128),
2239     U(u128),
2240 }
2241
2242 impl FullInt {
2243     #[allow(clippy::cast_sign_loss)]
2244     #[must_use]
2245     fn cmp_s_u(s: i128, u: u128) -> Ordering {
2246         if s < 0 {
2247             Ordering::Less
2248         } else if u > (i128::MAX as u128) {
2249             Ordering::Greater
2250         } else {
2251             (s as u128).cmp(&u)
2252         }
2253     }
2254 }
2255
2256 impl PartialEq for FullInt {
2257     #[must_use]
2258     fn eq(&self, other: &Self) -> bool {
2259         self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
2260     }
2261 }
2262
2263 impl PartialOrd for FullInt {
2264     #[must_use]
2265     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2266         Some(match (self, other) {
2267             (&Self::S(s), &Self::S(o)) => s.cmp(&o),
2268             (&Self::U(s), &Self::U(o)) => s.cmp(&o),
2269             (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
2270             (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
2271         })
2272     }
2273 }
2274
2275 impl Ord for FullInt {
2276     #[must_use]
2277     fn cmp(&self, other: &Self) -> Ordering {
2278         self.partial_cmp(other)
2279             .expect("`partial_cmp` for FullInt can never return `None`")
2280     }
2281 }
2282
2283 fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
2284     if let ExprKind::Cast(ref cast_exp, _) = expr.kind {
2285         let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
2286         let cast_ty = cx.typeck_results().expr_ty(expr);
2287         // if it's a cast from i32 to u32 wrapping will invalidate all these checks
2288         if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) {
2289             return None;
2290         }
2291         match pre_cast_ty.kind() {
2292             ty::Int(int_ty) => Some(match int_ty {
2293                 IntTy::I8 => (FullInt::S(i128::from(i8::MIN)), FullInt::S(i128::from(i8::MAX))),
2294                 IntTy::I16 => (FullInt::S(i128::from(i16::MIN)), FullInt::S(i128::from(i16::MAX))),
2295                 IntTy::I32 => (FullInt::S(i128::from(i32::MIN)), FullInt::S(i128::from(i32::MAX))),
2296                 IntTy::I64 => (FullInt::S(i128::from(i64::MIN)), FullInt::S(i128::from(i64::MAX))),
2297                 IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)),
2298                 IntTy::Isize => (FullInt::S(isize::MIN as i128), FullInt::S(isize::MAX as i128)),
2299             }),
2300             ty::Uint(uint_ty) => Some(match uint_ty {
2301                 UintTy::U8 => (FullInt::U(u128::from(u8::MIN)), FullInt::U(u128::from(u8::MAX))),
2302                 UintTy::U16 => (FullInt::U(u128::from(u16::MIN)), FullInt::U(u128::from(u16::MAX))),
2303                 UintTy::U32 => (FullInt::U(u128::from(u32::MIN)), FullInt::U(u128::from(u32::MAX))),
2304                 UintTy::U64 => (FullInt::U(u128::from(u64::MIN)), FullInt::U(u128::from(u64::MAX))),
2305                 UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)),
2306                 UintTy::Usize => (FullInt::U(usize::MIN as u128), FullInt::U(usize::MAX as u128)),
2307             }),
2308             _ => None,
2309         }
2310     } else {
2311         None
2312     }
2313 }
2314
2315 fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
2316     let val = constant(cx, cx.typeck_results(), expr)?.0;
2317     if let Constant::Int(const_int) = val {
2318         match *cx.typeck_results().expr_ty(expr).kind() {
2319             ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
2320             ty::Uint(_) => Some(FullInt::U(const_int)),
2321             _ => None,
2322         }
2323     } else {
2324         None
2325     }
2326 }
2327
2328 fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
2329     if let ExprKind::Cast(ref cast_val, _) = expr.kind {
2330         span_lint(
2331             cx,
2332             INVALID_UPCAST_COMPARISONS,
2333             span,
2334             &format!(
2335                 "because of the numeric bounds on `{}` prior to casting, this expression is always {}",
2336                 snippet(cx, cast_val.span, "the expression"),
2337                 if always { "true" } else { "false" },
2338             ),
2339         );
2340     }
2341 }
2342
2343 fn upcast_comparison_bounds_err<'tcx>(
2344     cx: &LateContext<'tcx>,
2345     span: Span,
2346     rel: comparisons::Rel,
2347     lhs_bounds: Option<(FullInt, FullInt)>,
2348     lhs: &'tcx Expr<'_>,
2349     rhs: &'tcx Expr<'_>,
2350     invert: bool,
2351 ) {
2352     use crate::utils::comparisons::Rel;
2353
2354     if let Some((lb, ub)) = lhs_bounds {
2355         if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
2356             if rel == Rel::Eq || rel == Rel::Ne {
2357                 if norm_rhs_val < lb || norm_rhs_val > ub {
2358                     err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
2359                 }
2360             } else if match rel {
2361                 Rel::Lt => {
2362                     if invert {
2363                         norm_rhs_val < lb
2364                     } else {
2365                         ub < norm_rhs_val
2366                     }
2367                 },
2368                 Rel::Le => {
2369                     if invert {
2370                         norm_rhs_val <= lb
2371                     } else {
2372                         ub <= norm_rhs_val
2373                     }
2374                 },
2375                 Rel::Eq | Rel::Ne => unreachable!(),
2376             } {
2377                 err_upcast_comparison(cx, span, lhs, true)
2378             } else if match rel {
2379                 Rel::Lt => {
2380                     if invert {
2381                         norm_rhs_val >= ub
2382                     } else {
2383                         lb >= norm_rhs_val
2384                     }
2385                 },
2386                 Rel::Le => {
2387                     if invert {
2388                         norm_rhs_val > ub
2389                     } else {
2390                         lb > norm_rhs_val
2391                     }
2392                 },
2393                 Rel::Eq | Rel::Ne => unreachable!(),
2394             } {
2395                 err_upcast_comparison(cx, span, lhs, false)
2396             }
2397         }
2398     }
2399 }
2400
2401 impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons {
2402     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
2403         if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind {
2404             let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
2405             let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
2406                 val
2407             } else {
2408                 return;
2409             };
2410
2411             let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs);
2412             let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs);
2413
2414             upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false);
2415             upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true);
2416         }
2417     }
2418 }
2419
2420 declare_clippy_lint! {
2421     /// **What it does:** Checks for public `impl` or `fn` missing generalization
2422     /// over different hashers and implicitly defaulting to the default hashing
2423     /// algorithm (`SipHash`).
2424     ///
2425     /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be
2426     /// used with them.
2427     ///
2428     /// **Known problems:** Suggestions for replacing constructors can contain
2429     /// false-positives. Also applying suggestions can require modification of other
2430     /// pieces of code, possibly including external crates.
2431     ///
2432     /// **Example:**
2433     /// ```rust
2434     /// # use std::collections::HashMap;
2435     /// # use std::hash::{Hash, BuildHasher};
2436     /// # trait Serialize {};
2437     /// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { }
2438     ///
2439     /// pub fn foo(map: &mut HashMap<i32, i32>) { }
2440     /// ```
2441     /// could be rewritten as
2442     /// ```rust
2443     /// # use std::collections::HashMap;
2444     /// # use std::hash::{Hash, BuildHasher};
2445     /// # trait Serialize {};
2446     /// impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { }
2447     ///
2448     /// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { }
2449     /// ```
2450     pub IMPLICIT_HASHER,
2451     pedantic,
2452     "missing generalization over different hashers"
2453 }
2454
2455 declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]);
2456
2457 impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
2458     #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)]
2459     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
2460         use rustc_span::BytePos;
2461
2462         fn suggestion<'tcx>(
2463             cx: &LateContext<'tcx>,
2464             diag: &mut DiagnosticBuilder<'_>,
2465             generics_span: Span,
2466             generics_suggestion_span: Span,
2467             target: &ImplicitHasherType<'_>,
2468             vis: ImplicitHasherConstructorVisitor<'_, '_, '_>,
2469         ) {
2470             let generics_snip = snippet(cx, generics_span, "");
2471             // trim `<` `>`
2472             let generics_snip = if generics_snip.is_empty() {
2473                 ""
2474             } else {
2475                 &generics_snip[1..generics_snip.len() - 1]
2476             };
2477
2478             multispan_sugg(
2479                 diag,
2480                 "consider adding a type parameter",
2481                 vec![
2482                     (
2483                         generics_suggestion_span,
2484                         format!(
2485                             "<{}{}S: ::std::hash::BuildHasher{}>",
2486                             generics_snip,
2487                             if generics_snip.is_empty() { "" } else { ", " },
2488                             if vis.suggestions.is_empty() {
2489                                 ""
2490                             } else {
2491                                 // request users to add `Default` bound so that generic constructors can be used
2492                                 " + Default"
2493                             },
2494                         ),
2495                     ),
2496                     (
2497                         target.span(),
2498                         format!("{}<{}, S>", target.type_name(), target.type_arguments(),),
2499                     ),
2500                 ],
2501             );
2502
2503             if !vis.suggestions.is_empty() {
2504                 multispan_sugg(diag, "...and use generic constructor", vis.suggestions);
2505             }
2506         }
2507
2508         if !cx.access_levels.is_exported(item.hir_id) {
2509             return;
2510         }
2511
2512         match item.kind {
2513             ItemKind::Impl {
2514                 ref generics,
2515                 self_ty: ref ty,
2516                 ref items,
2517                 ..
2518             } => {
2519                 let mut vis = ImplicitHasherTypeVisitor::new(cx);
2520                 vis.visit_ty(ty);
2521
2522                 for target in &vis.found {
2523                     if differing_macro_contexts(item.span, target.span()) {
2524                         return;
2525                     }
2526
2527                     let generics_suggestion_span = generics.span.substitute_dummy({
2528                         let pos = snippet_opt(cx, item.span.until(target.span()))
2529                             .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
2530                         if let Some(pos) = pos {
2531                             Span::new(pos, pos, item.span.data().ctxt)
2532                         } else {
2533                             return;
2534                         }
2535                     });
2536
2537                     let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
2538                     for item in items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
2539                         ctr_vis.visit_impl_item(item);
2540                     }
2541
2542                     span_lint_and_then(
2543                         cx,
2544                         IMPLICIT_HASHER,
2545                         target.span(),
2546                         &format!(
2547                             "impl for `{}` should be generalized over different hashers",
2548                             target.type_name()
2549                         ),
2550                         move |diag| {
2551                             suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis);
2552                         },
2553                     );
2554                 }
2555             },
2556             ItemKind::Fn(ref sig, ref generics, body_id) => {
2557                 let body = cx.tcx.hir().body(body_id);
2558
2559                 for ty in sig.decl.inputs {
2560                     let mut vis = ImplicitHasherTypeVisitor::new(cx);
2561                     vis.visit_ty(ty);
2562
2563                     for target in &vis.found {
2564                         if in_external_macro(cx.sess(), generics.span) {
2565                             continue;
2566                         }
2567                         let generics_suggestion_span = generics.span.substitute_dummy({
2568                             let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span))
2569                                 .and_then(|snip| {
2570                                     let i = snip.find("fn")?;
2571                                     Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
2572                                 })
2573                                 .expect("failed to create span for type parameters");
2574                             Span::new(pos, pos, item.span.data().ctxt)
2575                         });
2576
2577                         let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
2578                         ctr_vis.visit_body(body);
2579
2580                         span_lint_and_then(
2581                             cx,
2582                             IMPLICIT_HASHER,
2583                             target.span(),
2584                             &format!(
2585                                 "parameter of type `{}` should be generalized over different hashers",
2586                                 target.type_name()
2587                             ),
2588                             move |diag| {
2589                                 suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis);
2590                             },
2591                         );
2592                     }
2593                 }
2594             },
2595             _ => {},
2596         }
2597     }
2598 }
2599
2600 enum ImplicitHasherType<'tcx> {
2601     HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>),
2602     HashSet(Span, Ty<'tcx>, Cow<'static, str>),
2603 }
2604
2605 impl<'tcx> ImplicitHasherType<'tcx> {
2606     /// Checks that `ty` is a target type without a `BuildHasher`.
2607     fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> {
2608         if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.kind {
2609             let params: Vec<_> = path
2610                 .segments
2611                 .last()
2612                 .as_ref()?
2613                 .args
2614                 .as_ref()?
2615                 .args
2616                 .iter()
2617                 .filter_map(|arg| match arg {
2618                     GenericArg::Type(ty) => Some(ty),
2619                     _ => None,
2620                 })
2621                 .collect();
2622             let params_len = params.len();
2623
2624             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
2625
2626             if is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) && params_len == 2 {
2627                 Some(ImplicitHasherType::HashMap(
2628                     hir_ty.span,
2629                     ty,
2630                     snippet(cx, params[0].span, "K"),
2631                     snippet(cx, params[1].span, "V"),
2632                 ))
2633             } else if is_type_diagnostic_item(cx, ty, sym!(hashset_type)) && params_len == 1 {
2634                 Some(ImplicitHasherType::HashSet(
2635                     hir_ty.span,
2636                     ty,
2637                     snippet(cx, params[0].span, "T"),
2638                 ))
2639             } else {
2640                 None
2641             }
2642         } else {
2643             None
2644         }
2645     }
2646
2647     fn type_name(&self) -> &'static str {
2648         match *self {
2649             ImplicitHasherType::HashMap(..) => "HashMap",
2650             ImplicitHasherType::HashSet(..) => "HashSet",
2651         }
2652     }
2653
2654     fn type_arguments(&self) -> String {
2655         match *self {
2656             ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v),
2657             ImplicitHasherType::HashSet(.., ref t) => format!("{}", t),
2658         }
2659     }
2660
2661     fn ty(&self) -> Ty<'tcx> {
2662         match *self {
2663             ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty,
2664         }
2665     }
2666
2667     fn span(&self) -> Span {
2668         match *self {
2669             ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span,
2670         }
2671     }
2672 }
2673
2674 struct ImplicitHasherTypeVisitor<'a, 'tcx> {
2675     cx: &'a LateContext<'tcx>,
2676     found: Vec<ImplicitHasherType<'tcx>>,
2677 }
2678
2679 impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
2680     fn new(cx: &'a LateContext<'tcx>) -> Self {
2681         Self { cx, found: vec![] }
2682     }
2683 }
2684
2685 impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
2686     type Map = Map<'tcx>;
2687
2688     fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) {
2689         if let Some(target) = ImplicitHasherType::new(self.cx, t) {
2690             self.found.push(target);
2691         }
2692
2693         walk_ty(self, t);
2694     }
2695
2696     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
2697         NestedVisitorMap::None
2698     }
2699 }
2700
2701 /// Looks for default-hasher-dependent constructors like `HashMap::new`.
2702 struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
2703     cx: &'a LateContext<'tcx>,
2704     maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>,
2705     target: &'b ImplicitHasherType<'tcx>,
2706     suggestions: BTreeMap<Span, String>,
2707 }
2708
2709 impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
2710     fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self {
2711         Self {
2712             cx,
2713             maybe_typeck_results: cx.maybe_typeck_results(),
2714             target,
2715             suggestions: BTreeMap::new(),
2716         }
2717     }
2718 }
2719
2720 impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
2721     type Map = Map<'tcx>;
2722
2723     fn visit_body(&mut self, body: &'tcx Body<'_>) {
2724         let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id()));
2725         walk_body(self, body);
2726         self.maybe_typeck_results = old_maybe_typeck_results;
2727     }
2728
2729     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
2730         if_chain! {
2731             if let ExprKind::Call(ref fun, ref args) = e.kind;
2732             if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind;
2733             if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind;
2734             then {
2735                 if !TyS::same_type(self.target.ty(), self.maybe_typeck_results.unwrap().expr_ty(e)) {
2736                     return;
2737                 }
2738
2739                 if match_path(ty_path, &paths::HASHMAP) {
2740                     if method.ident.name == sym!(new) {
2741                         self.suggestions
2742                             .insert(e.span, "HashMap::default()".to_string());
2743                     } else if method.ident.name == sym!(with_capacity) {
2744                         self.suggestions.insert(
2745                             e.span,
2746                             format!(
2747                                 "HashMap::with_capacity_and_hasher({}, Default::default())",
2748                                 snippet(self.cx, args[0].span, "capacity"),
2749                             ),
2750                         );
2751                     }
2752                 } else if match_path(ty_path, &paths::HASHSET) {
2753                     if method.ident.name == sym!(new) {
2754                         self.suggestions
2755                             .insert(e.span, "HashSet::default()".to_string());
2756                     } else if method.ident.name == sym!(with_capacity) {
2757                         self.suggestions.insert(
2758                             e.span,
2759                             format!(
2760                                 "HashSet::with_capacity_and_hasher({}, Default::default())",
2761                                 snippet(self.cx, args[0].span, "capacity"),
2762                             ),
2763                         );
2764                     }
2765                 }
2766             }
2767         }
2768
2769         walk_expr(self, e);
2770     }
2771
2772     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
2773         NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
2774     }
2775 }
2776
2777 declare_clippy_lint! {
2778     /// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
2779     ///
2780     /// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
2781     /// `UnsafeCell` is the only way to obtain aliasable data that is considered
2782     /// mutable.
2783     ///
2784     /// **Known problems:** None.
2785     ///
2786     /// **Example:**
2787     /// ```rust,ignore
2788     /// fn x(r: &i32) {
2789     ///     unsafe {
2790     ///         *(r as *const _ as *mut _) += 1;
2791     ///     }
2792     /// }
2793     /// ```
2794     ///
2795     /// Instead consider using interior mutability types.
2796     ///
2797     /// ```rust
2798     /// use std::cell::UnsafeCell;
2799     ///
2800     /// fn x(r: &UnsafeCell<i32>) {
2801     ///     unsafe {
2802     ///         *r.get() += 1;
2803     ///     }
2804     /// }
2805     /// ```
2806     pub CAST_REF_TO_MUT,
2807     correctness,
2808     "a cast of reference to a mutable pointer"
2809 }
2810
2811 declare_lint_pass!(RefToMut => [CAST_REF_TO_MUT]);
2812
2813 impl<'tcx> LateLintPass<'tcx> for RefToMut {
2814     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
2815         if_chain! {
2816             if let ExprKind::Unary(UnOp::UnDeref, e) = &expr.kind;
2817             if let ExprKind::Cast(e, t) = &e.kind;
2818             if let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind;
2819             if let ExprKind::Cast(e, t) = &e.kind;
2820             if let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind;
2821             if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind();
2822             then {
2823                 span_lint(
2824                     cx,
2825                     CAST_REF_TO_MUT,
2826                     expr.span,
2827                     "casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`",
2828                 );
2829             }
2830         }
2831     }
2832 }