]> git.lizzy.rs Git - rust.git/blob - clippy_utils/src/lib.rs
Auto merge of #7573 - Jarcho:option_if_let_else, r=giraffate
[rust.git] / clippy_utils / src / lib.rs
1 #![feature(box_patterns)]
2 #![feature(in_band_lifetimes)]
3 #![feature(iter_zip)]
4 #![feature(rustc_private)]
5 #![feature(control_flow_enum)]
6 #![recursion_limit = "512"]
7 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
8 #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
9 // warn on the same lints as `clippy_lints`
10 #![warn(trivial_casts, trivial_numeric_casts)]
11 // warn on lints, that are included in `rust-lang/rust`s bootstrap
12 #![warn(rust_2018_idioms, unused_lifetimes)]
13 // warn on rustc internal lints
14 #![warn(rustc::internal)]
15
16 // FIXME: switch to something more ergonomic here, once available.
17 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
18 extern crate rustc_ast;
19 extern crate rustc_ast_pretty;
20 extern crate rustc_attr;
21 extern crate rustc_data_structures;
22 extern crate rustc_errors;
23 extern crate rustc_hir;
24 extern crate rustc_infer;
25 extern crate rustc_lexer;
26 extern crate rustc_lint;
27 extern crate rustc_middle;
28 extern crate rustc_mir;
29 extern crate rustc_session;
30 extern crate rustc_span;
31 extern crate rustc_target;
32 extern crate rustc_trait_selection;
33 extern crate rustc_typeck;
34
35 #[macro_use]
36 pub mod sym_helper;
37
38 #[allow(clippy::module_name_repetitions)]
39 pub mod ast_utils;
40 pub mod attrs;
41 pub mod camel_case;
42 pub mod comparisons;
43 pub mod consts;
44 pub mod diagnostics;
45 pub mod eager_or_lazy;
46 pub mod higher;
47 mod hir_utils;
48 pub mod msrvs;
49 pub mod numeric_literal;
50 pub mod paths;
51 pub mod ptr;
52 pub mod qualify_min_const_fn;
53 pub mod source;
54 pub mod sugg;
55 pub mod ty;
56 pub mod usage;
57 pub mod visitors;
58
59 pub use self::attrs::*;
60 pub use self::hir_utils::{both, count_eq, eq_expr_value, over, SpanlessEq, SpanlessHash};
61
62 use std::collections::hash_map::Entry;
63 use std::hash::BuildHasherDefault;
64
65 use if_chain::if_chain;
66 use rustc_ast::ast::{self, Attribute, LitKind};
67 use rustc_data_structures::unhash::UnhashMap;
68 use rustc_hir as hir;
69 use rustc_hir::def::{DefKind, Res};
70 use rustc_hir::def_id::DefId;
71 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
72 use rustc_hir::intravisit::{self, walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visitor};
73 use rustc_hir::LangItem::{ResultErr, ResultOk};
74 use rustc_hir::{
75     def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl,
76     ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, Param, Pat,
77     PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
78 };
79 use rustc_lint::{LateContext, Level, Lint, LintContext};
80 use rustc_middle::hir::exports::Export;
81 use rustc_middle::hir::map::Map;
82 use rustc_middle::hir::place::PlaceBase;
83 use rustc_middle::ty as rustc_ty;
84 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
85 use rustc_middle::ty::binding::BindingMode;
86 use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture};
87 use rustc_semver::RustcVersion;
88 use rustc_session::Session;
89 use rustc_span::hygiene::{ExpnKind, MacroKind};
90 use rustc_span::source_map::original_sp;
91 use rustc_span::sym;
92 use rustc_span::symbol::{kw, Symbol};
93 use rustc_span::{Span, DUMMY_SP};
94 use rustc_target::abi::Integer;
95
96 use crate::consts::{constant, Constant};
97 use crate::ty::{can_partially_move_ty, is_copy, is_recursively_primitive_type};
98
99 pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
100     if let Ok(version) = RustcVersion::parse(msrv) {
101         return Some(version);
102     } else if let Some(sess) = sess {
103         if let Some(span) = span {
104             sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
105         }
106     }
107     None
108 }
109
110 pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool {
111     msrv.map_or(true, |msrv| msrv.meets(*lint_msrv))
112 }
113
114 #[macro_export]
115 macro_rules! extract_msrv_attr {
116     (LateContext) => {
117         extract_msrv_attr!(@LateContext, ());
118     };
119     (EarlyContext) => {
120         extract_msrv_attr!(@EarlyContext);
121     };
122     (@$context:ident$(, $call:tt)?) => {
123         fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'tcx>, attrs: &'tcx [rustc_ast::ast::Attribute]) {
124             use $crate::get_unique_inner_attr;
125             match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") {
126                 Some(msrv_attr) => {
127                     if let Some(msrv) = msrv_attr.value_str() {
128                         self.msrv = $crate::parse_msrv(
129                             &msrv.to_string(),
130                             Some(cx.sess$($call)?),
131                             Some(msrv_attr.span),
132                         );
133                     } else {
134                         cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute");
135                     }
136                 },
137                 _ => (),
138             }
139         }
140     };
141 }
142
143 /// Returns `true` if the two spans come from differing expansions (i.e., one is
144 /// from a macro and one isn't).
145 #[must_use]
146 pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
147     rhs.ctxt() != lhs.ctxt()
148 }
149
150 /// If the given expression is a local binding, find the initializer expression.
151 /// If that initializer expression is another local binding, find its initializer again.
152 /// This process repeats as long as possible (but usually no more than once). Initializer
153 /// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
154 /// instead.
155 ///
156 /// Examples:
157 /// ```ignore
158 /// let abc = 1;
159 /// //        ^ output
160 /// let def = abc;
161 /// dbg!(def)
162 /// //   ^^^ input
163 ///
164 /// // or...
165 /// let abc = 1;
166 /// let def = abc + 2;
167 /// //        ^^^^^^^ output
168 /// dbg!(def)
169 /// //   ^^^ input
170 /// ```
171 pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
172     while let Some(init) = path_to_local(expr)
173         .and_then(|id| find_binding_init(cx, id))
174         .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
175     {
176         expr = init;
177     }
178     expr
179 }
180
181 /// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
182 /// By only considering immutable bindings, we guarantee that the returned expression represents the
183 /// value of the binding wherever it is referenced.
184 ///
185 /// Example: For `let x = 1`, if the `HirId` of `x` is provided, the `Expr` `1` is returned.
186 /// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the
187 /// canonical binding `HirId`.
188 pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
189     let hir = cx.tcx.hir();
190     if_chain! {
191         if let Some(Node::Binding(pat)) = hir.find(hir_id);
192         if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..));
193         let parent = hir.get_parent_node(hir_id);
194         if let Some(Node::Local(local)) = hir.find(parent);
195         then {
196             return local.init;
197         }
198     }
199     None
200 }
201
202 /// Returns `true` if the given `NodeId` is inside a constant context
203 ///
204 /// # Example
205 ///
206 /// ```rust,ignore
207 /// if in_constant(cx, expr.hir_id) {
208 ///     // Do something
209 /// }
210 /// ```
211 pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
212     let parent_id = cx.tcx.hir().get_parent_item(id);
213     match cx.tcx.hir().get(parent_id) {
214         Node::Item(&Item {
215             kind: ItemKind::Const(..) | ItemKind::Static(..),
216             ..
217         })
218         | Node::TraitItem(&TraitItem {
219             kind: TraitItemKind::Const(..),
220             ..
221         })
222         | Node::ImplItem(&ImplItem {
223             kind: ImplItemKind::Const(..),
224             ..
225         })
226         | Node::AnonConst(_) => true,
227         Node::Item(&Item {
228             kind: ItemKind::Fn(ref sig, ..),
229             ..
230         })
231         | Node::ImplItem(&ImplItem {
232             kind: ImplItemKind::Fn(ref sig, _),
233             ..
234         }) => sig.header.constness == Constness::Const,
235         _ => false,
236     }
237 }
238
239 /// Checks if a `QPath` resolves to a constructor of a `LangItem`.
240 /// For example, use this to check whether a function call or a pattern is `Some(..)`.
241 pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem) -> bool {
242     if let QPath::Resolved(_, path) = qpath {
243         if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
244             if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) {
245                 return cx.tcx.parent(ctor_id) == Some(item_id);
246             }
247         }
248     }
249     false
250 }
251
252 /// Returns `true` if this `span` was expanded by any macro.
253 #[must_use]
254 pub fn in_macro(span: Span) -> bool {
255     if span.from_expansion() {
256         !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
257     } else {
258         false
259     }
260 }
261
262 /// Checks if given pattern is a wildcard (`_`)
263 pub fn is_wild(pat: &Pat<'_>) -> bool {
264     matches!(pat.kind, PatKind::Wild)
265 }
266
267 /// Checks if the first type parameter is a lang item.
268 pub fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> {
269     let ty = get_qpath_generic_tys(qpath).next()?;
270
271     if let TyKind::Path(qpath) = &ty.kind {
272         cx.qpath_res(qpath, ty.hir_id)
273             .opt_def_id()
274             .map_or(false, |id| {
275                 cx.tcx.lang_items().require(item).map_or(false, |lang_id| id == lang_id)
276             })
277             .then(|| ty)
278     } else {
279         None
280     }
281 }
282
283 /// Checks if the first type parameter is a diagnostic item.
284 pub fn is_ty_param_diagnostic_item(
285     cx: &LateContext<'_>,
286     qpath: &QPath<'tcx>,
287     item: Symbol,
288 ) -> Option<&'tcx hir::Ty<'tcx>> {
289     let ty = get_qpath_generic_tys(qpath).next()?;
290
291     if let TyKind::Path(qpath) = &ty.kind {
292         cx.qpath_res(qpath, ty.hir_id)
293             .opt_def_id()
294             .map_or(false, |id| cx.tcx.is_diagnostic_item(item, id))
295             .then(|| ty)
296     } else {
297         None
298     }
299 }
300
301 /// Checks if the method call given in `expr` belongs to the given trait.
302 /// This is a deprecated function, consider using [`is_trait_method`].
303 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
304     let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
305     let trt_id = cx.tcx.trait_of_item(def_id);
306     trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path))
307 }
308
309 /// Checks if a method is defined in an impl of a diagnostic item
310 pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
311     if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
312         if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
313             return cx.tcx.is_diagnostic_item(diag_item, adt.did);
314         }
315     }
316     false
317 }
318
319 /// Checks if a method is in a diagnostic item trait
320 pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
321     if let Some(trait_did) = cx.tcx.trait_of_item(def_id) {
322         return cx.tcx.is_diagnostic_item(diag_item, trait_did);
323     }
324     false
325 }
326
327 /// Checks if the method call given in `expr` belongs to the given trait.
328 pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
329     cx.typeck_results()
330         .type_dependent_def_id(expr.hir_id)
331         .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
332 }
333
334 /// Checks if the given expression is a path referring an item on the trait
335 /// that is marked with the given diagnostic item.
336 ///
337 /// For checking method call expressions instead of path expressions, use
338 /// [`is_trait_method`].
339 ///
340 /// For example, this can be used to find if an expression like `u64::default`
341 /// refers to an item of the trait `Default`, which is associated with the
342 /// `diag_item` of `sym::Default`.
343 pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
344     if let hir::ExprKind::Path(ref qpath) = expr.kind {
345         cx.qpath_res(qpath, expr.hir_id)
346             .opt_def_id()
347             .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
348     } else {
349         false
350     }
351 }
352
353 pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
354     match *path {
355         QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
356         QPath::TypeRelative(_, seg) => seg,
357         QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
358     }
359 }
360
361 pub fn get_qpath_generics(path: &QPath<'tcx>) -> Option<&'tcx GenericArgs<'tcx>> {
362     match path {
363         QPath::Resolved(_, p) => p.segments.last().and_then(|s| s.args),
364         QPath::TypeRelative(_, s) => s.args,
365         QPath::LangItem(..) => None,
366     }
367 }
368
369 pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
370     get_qpath_generics(path)
371         .map_or([].as_ref(), |a| a.args)
372         .iter()
373         .filter_map(|a| {
374             if let hir::GenericArg::Type(ty) = a {
375                 Some(ty)
376             } else {
377                 None
378             }
379         })
380 }
381
382 pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
383     match *path {
384         QPath::Resolved(_, path) => path.segments.get(0),
385         QPath::TypeRelative(_, seg) => Some(seg),
386         QPath::LangItem(..) => None,
387     }
388 }
389
390 /// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
391 /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
392 /// `QPath::Resolved.1.res.opt_def_id()`.
393 ///
394 /// Matches a `QPath` against a slice of segment string literals.
395 ///
396 /// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a
397 /// `rustc_hir::QPath`.
398 ///
399 /// # Examples
400 /// ```rust,ignore
401 /// match_qpath(path, &["std", "rt", "begin_unwind"])
402 /// ```
403 pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
404     match *path {
405         QPath::Resolved(_, path) => match_path(path, segments),
406         QPath::TypeRelative(ty, segment) => match ty.kind {
407             TyKind::Path(ref inner_path) => {
408                 if let [prefix @ .., end] = segments {
409                     if match_qpath(inner_path, prefix) {
410                         return segment.ident.name.as_str() == *end;
411                     }
412                 }
413                 false
414             },
415             _ => false,
416         },
417         QPath::LangItem(..) => false,
418     }
419 }
420
421 /// If the expression is a path, resolve it. Otherwise, return `Res::Err`.
422 pub fn expr_path_res(cx: &LateContext<'_>, expr: &Expr<'_>) -> Res {
423     if let ExprKind::Path(p) = &expr.kind {
424         cx.qpath_res(p, expr.hir_id)
425     } else {
426         Res::Err
427     }
428 }
429
430 /// Resolves the path to a `DefId` and checks if it matches the given path.
431 pub fn is_qpath_def_path(cx: &LateContext<'_>, path: &QPath<'_>, hir_id: HirId, segments: &[&str]) -> bool {
432     cx.qpath_res(path, hir_id)
433         .opt_def_id()
434         .map_or(false, |id| match_def_path(cx, id, segments))
435 }
436
437 /// If the expression is a path, resolves it to a `DefId` and checks if it matches the given path.
438 ///
439 /// Please use `is_expr_diagnostic_item` if the target is a diagnostic item.
440 pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool {
441     expr_path_res(cx, expr)
442         .opt_def_id()
443         .map_or(false, |id| match_def_path(cx, id, segments))
444 }
445
446 /// If the expression is a path, resolves it to a `DefId` and checks if it matches the given
447 /// diagnostic item.
448 pub fn is_expr_diagnostic_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
449     expr_path_res(cx, expr)
450         .opt_def_id()
451         .map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id))
452 }
453
454 /// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
455 /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
456 /// `QPath::Resolved.1.res.opt_def_id()`.
457 ///
458 /// Matches a `Path` against a slice of segment string literals.
459 ///
460 /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a
461 /// `rustc_hir::Path`.
462 ///
463 /// # Examples
464 ///
465 /// ```rust,ignore
466 /// if match_path(&trait_ref.path, &paths::HASH) {
467 ///     // This is the `std::hash::Hash` trait.
468 /// }
469 ///
470 /// if match_path(ty_path, &["rustc", "lint", "Lint"]) {
471 ///     // This is a `rustc_middle::lint::Lint`.
472 /// }
473 /// ```
474 pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
475     path.segments
476         .iter()
477         .rev()
478         .zip(segments.iter().rev())
479         .all(|(a, b)| a.ident.name.as_str() == *b)
480 }
481
482 /// If the expression is a path to a local, returns the canonical `HirId` of the local.
483 pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
484     if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
485         if let Res::Local(id) = path.res {
486             return Some(id);
487         }
488     }
489     None
490 }
491
492 /// Returns true if the expression is a path to a local with the specified `HirId`.
493 /// Use this function to see if an expression matches a function argument or a match binding.
494 pub fn path_to_local_id(expr: &Expr<'_>, id: HirId) -> bool {
495     path_to_local(expr) == Some(id)
496 }
497
498 /// Gets the definition associated to a path.
499 #[allow(clippy::shadow_unrelated)] // false positive #6563
500 pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
501     macro_rules! try_res {
502         ($e:expr) => {
503             match $e {
504                 Some(e) => e,
505                 None => return Res::Err,
506             }
507         };
508     }
509     fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
510         tcx.item_children(def_id)
511             .iter()
512             .find(|item| item.ident.name.as_str() == name)
513     }
514
515     let (krate, first, path) = match *path {
516         [krate, first, ref path @ ..] => (krate, first, path),
517         [primitive] => {
518             return PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy);
519         },
520         _ => return Res::Err,
521     };
522     let tcx = cx.tcx;
523     let crates = tcx.crates(());
524     let krate = try_res!(crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate));
525     let first = try_res!(item_child_by_name(tcx, krate.as_def_id(), first));
526     let last = path
527         .iter()
528         .copied()
529         // `get_def_path` seems to generate these empty segments for extern blocks.
530         // We can just ignore them.
531         .filter(|segment| !segment.is_empty())
532         // for each segment, find the child item
533         .try_fold(first, |item, segment| {
534             let def_id = item.res.def_id();
535             if let Some(item) = item_child_by_name(tcx, def_id, segment) {
536                 Some(item)
537             } else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
538                 // it is not a child item so check inherent impl items
539                 tcx.inherent_impls(def_id)
540                     .iter()
541                     .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
542             } else {
543                 None
544             }
545         });
546     try_res!(last).res
547 }
548
549 /// Convenience function to get the `DefId` of a trait by path.
550 /// It could be a trait or trait alias.
551 pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
552     match path_to_res(cx, path) {
553         Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
554         _ => None,
555     }
556 }
557
558 /// Gets the `hir::TraitRef` of the trait the given method is implemented for.
559 ///
560 /// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
561 ///
562 /// ```rust
563 /// struct Point(isize, isize);
564 ///
565 /// impl std::ops::Add for Point {
566 ///     type Output = Self;
567 ///
568 ///     fn add(self, other: Self) -> Self {
569 ///         Point(0, 0)
570 ///     }
571 /// }
572 /// ```
573 pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> {
574     // Get the implemented trait for the current function
575     let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
576     if_chain! {
577         if parent_impl != hir::CRATE_HIR_ID;
578         if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
579         if let hir::ItemKind::Impl(impl_) = &item.kind;
580         then { return impl_.of_trait.as_ref(); }
581     }
582     None
583 }
584
585 /// This method will return tuple of projection stack and root of the expression,
586 /// used in `can_mut_borrow_both`.
587 ///
588 /// For example, if `e` represents the `v[0].a.b[x]`
589 /// this method will return a tuple, composed of a `Vec`
590 /// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
591 /// and a `Expr` for root of them, `v`
592 fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
593     let mut result = vec![];
594     let root = loop {
595         match e.kind {
596             ExprKind::Index(ep, _) | ExprKind::Field(ep, _) => {
597                 result.push(e);
598                 e = ep;
599             },
600             _ => break e,
601         };
602     };
603     result.reverse();
604     (result, root)
605 }
606
607 /// Checks if two expressions can be mutably borrowed simultaneously
608 /// and they aren't dependent on borrowing same thing twice
609 pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool {
610     let (s1, r1) = projection_stack(e1);
611     let (s2, r2) = projection_stack(e2);
612     if !eq_expr_value(cx, r1, r2) {
613         return true;
614     }
615     for (x1, x2) in s1.iter().zip(s2.iter()) {
616         match (&x1.kind, &x2.kind) {
617             (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => {
618                 if i1 != i2 {
619                     return true;
620                 }
621             },
622             (ExprKind::Index(_, i1), ExprKind::Index(_, i2)) => {
623                 if !eq_expr_value(cx, i1, i2) {
624                     return false;
625                 }
626             },
627             _ => return false,
628         }
629     }
630     false
631 }
632
633 /// Checks if the top level expression can be moved into a closure as is.
634 /// Currently checks for:
635 /// * Break/Continue outside the given loop HIR ids.
636 /// * Yield/Return statments.
637 /// * Inline assembly.
638 /// * Usages of a field of a local where the type of the local can be partially moved.
639 ///
640 /// For example, given the following function:
641 ///
642 /// ```
643 /// fn f<'a>(iter: &mut impl Iterator<Item = (usize, &'a mut String)>) {
644 ///     for item in iter {
645 ///         let s = item.1;
646 ///         if item.0 > 10 {
647 ///             continue;
648 ///         } else {
649 ///             s.clear();
650 ///         }
651 ///     }
652 /// }
653 /// ```
654 ///
655 /// When called on the expression `item.0` this will return false unless the local `item` is in the
656 /// `ignore_locals` set. The type `(usize, &mut String)` can have the second element moved, so it
657 /// isn't always safe to move into a closure when only a single field is needed.
658 ///
659 /// When called on the `continue` expression this will return false unless the outer loop expression
660 /// is in the `loop_ids` set.
661 ///
662 /// Note that this check is not recursive, so passing the `if` expression will always return true
663 /// even though sub-expressions might return false.
664 pub fn can_move_expr_to_closure_no_visit(
665     cx: &LateContext<'tcx>,
666     expr: &'tcx Expr<'_>,
667     loop_ids: &[HirId],
668     ignore_locals: &HirIdSet,
669 ) -> bool {
670     match expr.kind {
671         ExprKind::Break(Destination { target_id: Ok(id), .. }, _)
672         | ExprKind::Continue(Destination { target_id: Ok(id), .. })
673             if loop_ids.contains(&id) =>
674         {
675             true
676         },
677         ExprKind::Break(..)
678         | ExprKind::Continue(_)
679         | ExprKind::Ret(_)
680         | ExprKind::Yield(..)
681         | ExprKind::InlineAsm(_)
682         | ExprKind::LlvmInlineAsm(_) => false,
683         // Accessing a field of a local value can only be done if the type isn't
684         // partially moved.
685         ExprKind::Field(
686             &Expr {
687                 hir_id,
688                 kind:
689                     ExprKind::Path(QPath::Resolved(
690                         _,
691                         Path {
692                             res: Res::Local(local_id),
693                             ..
694                         },
695                     )),
696                 ..
697             },
698             _,
699         ) if !ignore_locals.contains(local_id) && can_partially_move_ty(cx, cx.typeck_results().node_type(hir_id)) => {
700             // TODO: check if the local has been partially moved. Assume it has for now.
701             false
702         },
703         _ => true,
704     }
705 }
706
707 /// How a local is captured by a closure
708 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
709 pub enum CaptureKind {
710     Value,
711     Ref(Mutability),
712 }
713 impl CaptureKind {
714     pub fn is_imm_ref(self) -> bool {
715         self == Self::Ref(Mutability::Not)
716     }
717 }
718 impl std::ops::BitOr for CaptureKind {
719     type Output = Self;
720     fn bitor(self, rhs: Self) -> Self::Output {
721         match (self, rhs) {
722             (CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
723             (CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
724             | (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
725             (CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
726         }
727     }
728 }
729 impl std::ops::BitOrAssign for CaptureKind {
730     fn bitor_assign(&mut self, rhs: Self) {
731         *self = *self | rhs;
732     }
733 }
734
735 /// Given an expression referencing a local, determines how it would be captured in a closure.
736 /// Note as this will walk up to parent expressions until the capture can be determined it should
737 /// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
738 /// function argument (other than a receiver).
739 pub fn capture_local_usage(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind {
740     fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
741         let mut capture = CaptureKind::Ref(Mutability::Not);
742         pat.each_binding_or_first(&mut |_, id, span, _| match cx
743             .typeck_results()
744             .extract_binding_mode(cx.sess(), id, span)
745             .unwrap()
746         {
747             BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => {
748                 capture = CaptureKind::Value;
749             },
750             BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => {
751                 capture = CaptureKind::Ref(Mutability::Mut);
752             },
753             _ => (),
754         });
755         capture
756     }
757
758     debug_assert!(matches!(
759         e.kind,
760         ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
761     ));
762
763     let map = cx.tcx.hir();
764     let mut child_id = e.hir_id;
765     let mut capture = CaptureKind::Value;
766     let mut capture_expr_ty = e;
767
768     for (parent_id, parent) in map.parent_iter(e.hir_id) {
769         if let [Adjustment {
770             kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
771             target,
772         }, ref adjust @ ..] = *cx
773             .typeck_results()
774             .adjustments()
775             .get(child_id)
776             .map_or(&[][..], |x| &**x)
777         {
778             if let rustc_ty::RawPtr(TypeAndMut { mutbl: mutability, .. }) | rustc_ty::Ref(_, _, mutability) =
779                 *adjust.last().map_or(target, |a| a.target).kind()
780             {
781                 return CaptureKind::Ref(mutability);
782             }
783         }
784
785         match parent {
786             Node::Expr(e) => match e.kind {
787                 ExprKind::AddrOf(_, mutability, _) => return CaptureKind::Ref(mutability),
788                 ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, _) => capture = CaptureKind::Ref(Mutability::Not),
789                 ExprKind::Assign(lhs, ..) | ExprKind::Assign(_, lhs, _) if lhs.hir_id == child_id => {
790                     return CaptureKind::Ref(Mutability::Mut);
791                 },
792                 ExprKind::Field(..) => {
793                     if capture == CaptureKind::Value {
794                         capture_expr_ty = e;
795                     }
796                 },
797                 ExprKind::Match(_, arms, _) => {
798                     let mut mutability = Mutability::Not;
799                     for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
800                         match capture {
801                             CaptureKind::Value => break,
802                             CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
803                             CaptureKind::Ref(Mutability::Not) => (),
804                         }
805                     }
806                     return CaptureKind::Ref(mutability);
807                 },
808                 _ => break,
809             },
810             Node::Local(l) => match pat_capture_kind(cx, l.pat) {
811                 CaptureKind::Value => break,
812                 capture @ CaptureKind::Ref(_) => return capture,
813             },
814             _ => break,
815         }
816
817         child_id = parent_id;
818     }
819
820     if capture == CaptureKind::Value && is_copy(cx, cx.typeck_results().expr_ty(capture_expr_ty)) {
821         // Copy types are never automatically captured by value.
822         CaptureKind::Ref(Mutability::Not)
823     } else {
824         capture
825     }
826 }
827
828 /// Checks if the expression can be moved into a closure as is. This will return a list of captures
829 /// if so, otherwise, `None`.
830 pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<HirIdMap<CaptureKind>> {
831     struct V<'cx, 'tcx> {
832         cx: &'cx LateContext<'tcx>,
833         // Stack of potential break targets contained in the expression.
834         loops: Vec<HirId>,
835         /// Local variables created in the expression. These don't need to be captured.
836         locals: HirIdSet,
837         /// Whether this expression can be turned into a closure.
838         allow_closure: bool,
839         /// Locals which need to be captured, and whether they need to be by value, reference, or
840         /// mutable reference.
841         captures: HirIdMap<CaptureKind>,
842     }
843     impl Visitor<'tcx> for V<'_, 'tcx> {
844         type Map = ErasedMap<'tcx>;
845         fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
846             NestedVisitorMap::None
847         }
848
849         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
850             if !self.allow_closure {
851                 return;
852             }
853
854             match e.kind {
855                 ExprKind::Path(QPath::Resolved(None, &Path { res: Res::Local(l), .. })) => {
856                     if !self.locals.contains(&l) {
857                         let cap = capture_local_usage(self.cx, e);
858                         self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
859                     }
860                 },
861                 ExprKind::Closure(..) => {
862                     let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id();
863                     for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
864                         let local_id = match capture.place.base {
865                             PlaceBase::Local(id) => id,
866                             PlaceBase::Upvar(var) => var.var_path.hir_id,
867                             _ => continue,
868                         };
869                         if !self.locals.contains(&local_id) {
870                             let capture = match capture.info.capture_kind {
871                                 UpvarCapture::ByValue(_) => CaptureKind::Value,
872                                 UpvarCapture::ByRef(borrow) => match borrow.kind {
873                                     BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
874                                     BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
875                                         CaptureKind::Ref(Mutability::Mut)
876                                     },
877                                 },
878                             };
879                             self.captures
880                                 .entry(local_id)
881                                 .and_modify(|e| *e |= capture)
882                                 .or_insert(capture);
883                         }
884                     }
885                 },
886                 ExprKind::Loop(b, ..) => {
887                     self.loops.push(e.hir_id);
888                     self.visit_block(b);
889                     self.loops.pop();
890                 },
891                 _ => {
892                     self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops, &self.locals);
893                     walk_expr(self, e);
894                 },
895             }
896         }
897
898         fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
899             p.each_binding_or_first(&mut |_, id, _, _| {
900                 self.locals.insert(id);
901             });
902         }
903     }
904
905     let mut v = V {
906         cx,
907         allow_closure: true,
908         loops: Vec::new(),
909         locals: HirIdSet::default(),
910         captures: HirIdMap::default(),
911     };
912     v.visit_expr(expr);
913     v.allow_closure.then(|| v.captures)
914 }
915
916 /// Returns the method names and argument list of nested method call expressions that make up
917 /// `expr`. method/span lists are sorted with the most recent call first.
918 pub fn method_calls<'tcx>(
919     expr: &'tcx Expr<'tcx>,
920     max_depth: usize,
921 ) -> (Vec<Symbol>, Vec<&'tcx [Expr<'tcx>]>, Vec<Span>) {
922     let mut method_names = Vec::with_capacity(max_depth);
923     let mut arg_lists = Vec::with_capacity(max_depth);
924     let mut spans = Vec::with_capacity(max_depth);
925
926     let mut current = expr;
927     for _ in 0..max_depth {
928         if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
929             if args.iter().any(|e| e.span.from_expansion()) {
930                 break;
931             }
932             method_names.push(path.ident.name);
933             arg_lists.push(&**args);
934             spans.push(*span);
935             current = &args[0];
936         } else {
937             break;
938         }
939     }
940
941     (method_names, arg_lists, spans)
942 }
943
944 /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
945 ///
946 /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
947 /// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
948 /// containing the `Expr`s for
949 /// `.bar()` and `.baz()`
950 pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
951     let mut current = expr;
952     let mut matched = Vec::with_capacity(methods.len());
953     for method_name in methods.iter().rev() {
954         // method chains are stored last -> first
955         if let ExprKind::MethodCall(path, _, args, _) = current.kind {
956             if path.ident.name.as_str() == *method_name {
957                 if args.iter().any(|e| e.span.from_expansion()) {
958                     return None;
959                 }
960                 matched.push(args); // build up `matched` backwards
961                 current = &args[0]; // go to parent expression
962             } else {
963                 return None;
964             }
965         } else {
966             return None;
967         }
968     }
969     // Reverse `matched` so that it is in the same order as `methods`.
970     matched.reverse();
971     Some(matched)
972 }
973
974 /// Returns `true` if the provided `def_id` is an entrypoint to a program.
975 pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
976     cx.tcx
977         .entry_fn(())
978         .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id)
979 }
980
981 /// Returns `true` if the expression is in the program's `#[panic_handler]`.
982 pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
983     let parent = cx.tcx.hir().get_parent_item(e.hir_id);
984     let def_id = cx.tcx.hir().local_def_id(parent).to_def_id();
985     Some(def_id) == cx.tcx.lang_items().panic_impl()
986 }
987
988 /// Gets the name of the item the expression is in, if available.
989 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
990     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
991     match cx.tcx.hir().find(parent_id) {
992         Some(
993             Node::Item(Item { ident, .. })
994             | Node::TraitItem(TraitItem { ident, .. })
995             | Node::ImplItem(ImplItem { ident, .. }),
996         ) => Some(ident.name),
997         _ => None,
998     }
999 }
1000
1001 pub struct ContainsName {
1002     pub name: Symbol,
1003     pub result: bool,
1004 }
1005
1006 impl<'tcx> Visitor<'tcx> for ContainsName {
1007     type Map = Map<'tcx>;
1008
1009     fn visit_name(&mut self, _: Span, name: Symbol) {
1010         if self.name == name {
1011             self.result = true;
1012         }
1013     }
1014     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
1015         NestedVisitorMap::None
1016     }
1017 }
1018
1019 /// Checks if an `Expr` contains a certain name.
1020 pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
1021     let mut cn = ContainsName { name, result: false };
1022     cn.visit_expr(expr);
1023     cn.result
1024 }
1025
1026 /// Returns `true` if `expr` contains a return expression
1027 pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
1028     struct RetCallFinder {
1029         found: bool,
1030     }
1031
1032     impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder {
1033         type Map = Map<'tcx>;
1034
1035         fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
1036             if self.found {
1037                 return;
1038             }
1039             if let hir::ExprKind::Ret(..) = &expr.kind {
1040                 self.found = true;
1041             } else {
1042                 hir::intravisit::walk_expr(self, expr);
1043             }
1044         }
1045
1046         fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
1047             hir::intravisit::NestedVisitorMap::None
1048         }
1049     }
1050
1051     let mut visitor = RetCallFinder { found: false };
1052     visitor.visit_expr(expr);
1053     visitor.found
1054 }
1055
1056 struct FindMacroCalls<'a, 'b> {
1057     names: &'a [&'b str],
1058     result: Vec<Span>,
1059 }
1060
1061 impl<'a, 'b, 'tcx> Visitor<'tcx> for FindMacroCalls<'a, 'b> {
1062     type Map = Map<'tcx>;
1063
1064     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
1065         if self.names.iter().any(|fun| is_expn_of(expr.span, fun).is_some()) {
1066             self.result.push(expr.span);
1067         }
1068         // and check sub-expressions
1069         intravisit::walk_expr(self, expr);
1070     }
1071
1072     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
1073         NestedVisitorMap::None
1074     }
1075 }
1076
1077 /// Finds calls of the specified macros in a function body.
1078 pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> {
1079     let mut fmc = FindMacroCalls {
1080         names,
1081         result: Vec::new(),
1082     };
1083     fmc.visit_expr(&body.value);
1084     fmc.result
1085 }
1086
1087 /// Extends the span to the beginning of the spans line, incl. whitespaces.
1088 ///
1089 /// ```rust,ignore
1090 ///        let x = ();
1091 /// //             ^^
1092 /// // will be converted to
1093 ///        let x = ();
1094 /// // ^^^^^^^^^^^^^^
1095 /// ```
1096 fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
1097     let span = original_sp(span, DUMMY_SP);
1098     let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
1099     let line_no = source_map_and_line.line;
1100     let line_start = source_map_and_line.sf.lines[line_no];
1101     Span::new(line_start, span.hi(), span.ctxt())
1102 }
1103
1104 /// Gets the parent node, if any.
1105 pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
1106     tcx.hir().parent_iter(id).next().map(|(_, node)| node)
1107 }
1108
1109 /// Gets the parent expression, if any â€“- this is useful to constrain a lint.
1110 pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1111     get_parent_expr_for_hir(cx, e.hir_id)
1112 }
1113
1114 /// This retrieves the parent for the given `HirId` if it's an expression. This is useful for
1115 /// constraint lints
1116 pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> {
1117     match get_parent_node(cx.tcx, hir_id) {
1118         Some(Node::Expr(parent)) => Some(parent),
1119         _ => None,
1120     }
1121 }
1122
1123 pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
1124     let map = &cx.tcx.hir();
1125     let enclosing_node = map
1126         .get_enclosing_scope(hir_id)
1127         .and_then(|enclosing_id| map.find(enclosing_id));
1128     enclosing_node.and_then(|node| match node {
1129         Node::Block(block) => Some(block),
1130         Node::Item(&Item {
1131             kind: ItemKind::Fn(_, _, eid),
1132             ..
1133         })
1134         | Node::ImplItem(&ImplItem {
1135             kind: ImplItemKind::Fn(_, eid),
1136             ..
1137         }) => match cx.tcx.hir().body(eid).value.kind {
1138             ExprKind::Block(block, _) => Some(block),
1139             _ => None,
1140         },
1141         _ => None,
1142     })
1143 }
1144
1145 /// Gets the loop or closure enclosing the given expression, if any.
1146 pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1147     let map = tcx.hir();
1148     for (_, node) in map.parent_iter(expr.hir_id) {
1149         match node {
1150             Node::Expr(
1151                 e
1152                 @
1153                 Expr {
1154                     kind: ExprKind::Loop(..) | ExprKind::Closure(..),
1155                     ..
1156                 },
1157             ) => return Some(e),
1158             Node::Expr(_) | Node::Stmt(_) | Node::Block(_) | Node::Local(_) | Node::Arm(_) => (),
1159             _ => break,
1160         }
1161     }
1162     None
1163 }
1164
1165 /// Gets the parent node if it's an impl block.
1166 pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
1167     let map = tcx.hir();
1168     match map.parent_iter(id).next() {
1169         Some((
1170             _,
1171             Node::Item(Item {
1172                 kind: ItemKind::Impl(imp),
1173                 ..
1174             }),
1175         )) => Some(imp),
1176         _ => None,
1177     }
1178 }
1179
1180 /// Checks if the given expression is the else clause of either an `if` or `if let` expression.
1181 pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1182     let map = tcx.hir();
1183     let mut iter = map.parent_iter(expr.hir_id);
1184     match iter.next() {
1185         Some((arm_id, Node::Arm(..))) => matches!(
1186             iter.next(),
1187             Some((
1188                 _,
1189                 Node::Expr(Expr {
1190                     kind: ExprKind::Match(_, [_, else_arm], MatchSource::IfLetDesugar { .. }),
1191                     ..
1192                 })
1193             ))
1194             if else_arm.hir_id == arm_id
1195         ),
1196         Some((
1197             _,
1198             Node::Expr(Expr {
1199                 kind: ExprKind::If(_, _, Some(else_expr)),
1200                 ..
1201             }),
1202         )) => else_expr.hir_id == expr.hir_id,
1203         _ => false,
1204     }
1205 }
1206
1207 /// Checks whether the given expression is a constant integer of the given value.
1208 /// unlike `is_integer_literal`, this version does const folding
1209 pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
1210     if is_integer_literal(e, value) {
1211         return true;
1212     }
1213     let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id));
1214     if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
1215         value == v
1216     } else {
1217         false
1218     }
1219 }
1220
1221 /// Checks whether the given expression is a constant literal of the given value.
1222 pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
1223     // FIXME: use constant folding
1224     if let ExprKind::Lit(ref spanned) = expr.kind {
1225         if let LitKind::Int(v, _) = spanned.node {
1226             return v == value;
1227         }
1228     }
1229     false
1230 }
1231
1232 /// Returns `true` if the given `Expr` has been coerced before.
1233 ///
1234 /// Examples of coercions can be found in the Nomicon at
1235 /// <https://doc.rust-lang.org/nomicon/coercions.html>.
1236 ///
1237 /// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
1238 /// information on adjustments and coercions.
1239 pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
1240     cx.typeck_results().adjustments().get(e.hir_id).is_some()
1241 }
1242
1243 /// Returns the pre-expansion span if is this comes from an expansion of the
1244 /// macro `name`.
1245 /// See also `is_direct_expn_of`.
1246 #[must_use]
1247 pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
1248     loop {
1249         if span.from_expansion() {
1250             let data = span.ctxt().outer_expn_data();
1251             let new_span = data.call_site;
1252
1253             if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1254                 if mac_name.as_str() == name {
1255                     return Some(new_span);
1256                 }
1257             }
1258
1259             span = new_span;
1260         } else {
1261             return None;
1262         }
1263     }
1264 }
1265
1266 /// Returns the pre-expansion span if the span directly comes from an expansion
1267 /// of the macro `name`.
1268 /// The difference with `is_expn_of` is that in
1269 /// ```rust,ignore
1270 /// foo!(bar!(42));
1271 /// ```
1272 /// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
1273 /// `bar!` by
1274 /// `is_direct_expn_of`.
1275 #[must_use]
1276 pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
1277     if span.from_expansion() {
1278         let data = span.ctxt().outer_expn_data();
1279         let new_span = data.call_site;
1280
1281         if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1282             if mac_name.as_str() == name {
1283                 return Some(new_span);
1284             }
1285         }
1286     }
1287
1288     None
1289 }
1290
1291 /// Convenience function to get the return type of a function.
1292 pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
1293     let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
1294     let ret_ty = cx.tcx.fn_sig(fn_def_id).output();
1295     cx.tcx.erase_late_bound_regions(ret_ty)
1296 }
1297
1298 /// Checks if an expression is constructing a tuple-like enum variant or struct
1299 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1300     if let ExprKind::Call(fun, _) = expr.kind {
1301         if let ExprKind::Path(ref qp) = fun.kind {
1302             let res = cx.qpath_res(qp, fun.hir_id);
1303             return match res {
1304                 def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
1305                 def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
1306                 _ => false,
1307             };
1308         }
1309     }
1310     false
1311 }
1312
1313 /// Returns `true` if a pattern is refutable.
1314 // TODO: should be implemented using rustc/mir_build/thir machinery
1315 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
1316     fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
1317         matches!(
1318             cx.qpath_res(qpath, id),
1319             def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
1320         )
1321     }
1322
1323     fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
1324         i.into_iter().any(|pat| is_refutable(cx, pat))
1325     }
1326
1327     match pat.kind {
1328         PatKind::Wild => false,
1329         PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
1330         PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
1331         PatKind::Lit(..) | PatKind::Range(..) => true,
1332         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
1333         PatKind::Or(pats) => {
1334             // TODO: should be the honest check, that pats is exhaustive set
1335             are_refutable(cx, pats)
1336         },
1337         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
1338         PatKind::Struct(ref qpath, fields, _) => {
1339             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
1340         },
1341         PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
1342         PatKind::Slice(head, middle, tail) => {
1343             match &cx.typeck_results().node_type(pat.hir_id).kind() {
1344                 rustc_ty::Slice(..) => {
1345                     // [..] is the only irrefutable slice pattern.
1346                     !head.is_empty() || middle.is_none() || !tail.is_empty()
1347                 },
1348                 rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
1349                 _ => {
1350                     // unreachable!()
1351                     true
1352                 },
1353             }
1354         },
1355     }
1356 }
1357
1358 /// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call
1359 /// the function once on the given pattern.
1360 pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
1361     if let PatKind::Or(pats) = pat.kind {
1362         pats.iter().for_each(f);
1363     } else {
1364         f(pat);
1365     }
1366 }
1367
1368 /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
1369 /// implementations have.
1370 pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
1371     attrs.iter().any(|attr| attr.has_name(sym::automatically_derived))
1372 }
1373
1374 /// Remove blocks around an expression.
1375 ///
1376 /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return
1377 /// themselves.
1378 pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
1379     while let ExprKind::Block(block, ..) = expr.kind {
1380         match (block.stmts.is_empty(), block.expr.as_ref()) {
1381             (true, Some(e)) => expr = e,
1382             _ => break,
1383         }
1384     }
1385     expr
1386 }
1387
1388 pub fn is_self(slf: &Param<'_>) -> bool {
1389     if let PatKind::Binding(.., name, _) = slf.pat.kind {
1390         name.name == kw::SelfLower
1391     } else {
1392         false
1393     }
1394 }
1395
1396 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
1397     if_chain! {
1398         if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind;
1399         if let Res::SelfTy(..) = path.res;
1400         then {
1401             return true
1402         }
1403     }
1404     false
1405 }
1406
1407 pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator<Item = &'tcx Param<'tcx>> {
1408     (0..decl.inputs.len()).map(move |i| &body.params[i])
1409 }
1410
1411 /// Checks if a given expression is a match expression expanded from the `?`
1412 /// operator or the `try` macro.
1413 pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
1414     fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1415         if_chain! {
1416             if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind;
1417             if is_lang_ctor(cx, path, ResultOk);
1418             if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
1419             if path_to_local_id(arm.body, hir_id);
1420             then {
1421                 return true;
1422             }
1423         }
1424         false
1425     }
1426
1427     fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1428         if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
1429             is_lang_ctor(cx, path, ResultErr)
1430         } else {
1431             false
1432         }
1433     }
1434
1435     if let ExprKind::Match(_, arms, ref source) = expr.kind {
1436         // desugared from a `?` operator
1437         if let MatchSource::TryDesugar = *source {
1438             return Some(expr);
1439         }
1440
1441         if_chain! {
1442             if arms.len() == 2;
1443             if arms[0].guard.is_none();
1444             if arms[1].guard.is_none();
1445             if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) ||
1446                 (is_ok(cx, &arms[1]) && is_err(cx, &arms[0]));
1447             then {
1448                 return Some(expr);
1449             }
1450         }
1451     }
1452
1453     None
1454 }
1455
1456 /// Returns `true` if the lint is allowed in the current context
1457 ///
1458 /// Useful for skipping long running code when it's unnecessary
1459 pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
1460     cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
1461 }
1462
1463 pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
1464     while let PatKind::Ref(subpat, _) = pat.kind {
1465         pat = subpat;
1466     }
1467     pat
1468 }
1469
1470 pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 {
1471     Integer::from_int_ty(&tcx, ity).size().bits()
1472 }
1473
1474 #[allow(clippy::cast_possible_wrap)]
1475 /// Turn a constant int byte representation into an i128
1476 pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 {
1477     let amt = 128 - int_bits(tcx, ity);
1478     ((u as i128) << amt) >> amt
1479 }
1480
1481 #[allow(clippy::cast_sign_loss)]
1482 /// clip unused bytes
1483 pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 {
1484     let amt = 128 - int_bits(tcx, ity);
1485     ((u as u128) << amt) >> amt
1486 }
1487
1488 /// clip unused bytes
1489 pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 {
1490     let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
1491     let amt = 128 - bits;
1492     (u << amt) >> amt
1493 }
1494
1495 pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
1496     let map = &tcx.hir();
1497     let mut prev_enclosing_node = None;
1498     let mut enclosing_node = node;
1499     while Some(enclosing_node) != prev_enclosing_node {
1500         if is_automatically_derived(map.attrs(enclosing_node)) {
1501             return true;
1502         }
1503         prev_enclosing_node = Some(enclosing_node);
1504         enclosing_node = map.get_parent_item(enclosing_node);
1505     }
1506     false
1507 }
1508
1509 /// Matches a function call with the given path and returns the arguments.
1510 ///
1511 /// Usage:
1512 ///
1513 /// ```rust,ignore
1514 /// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
1515 /// ```
1516 pub fn match_function_call<'tcx>(
1517     cx: &LateContext<'tcx>,
1518     expr: &'tcx Expr<'_>,
1519     path: &[&str],
1520 ) -> Option<&'tcx [Expr<'tcx>]> {
1521     if_chain! {
1522         if let ExprKind::Call(fun, args) = expr.kind;
1523         if let ExprKind::Path(ref qpath) = fun.kind;
1524         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
1525         if match_def_path(cx, fun_def_id, path);
1526         then {
1527             return Some(args)
1528         }
1529     };
1530     None
1531 }
1532
1533 /// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
1534 /// any.
1535 ///
1536 /// Please use `match_any_diagnostic_items` if the targets are all diagnostic items.
1537 pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]]) -> Option<usize> {
1538     let search_path = cx.get_def_path(did);
1539     paths
1540         .iter()
1541         .position(|p| p.iter().map(|x| Symbol::intern(x)).eq(search_path.iter().copied()))
1542 }
1543
1544 /// Checks if the given `DefId` matches any of provided diagnostic items. Returns the index of
1545 /// matching path, if any.
1546 pub fn match_any_diagnostic_items(cx: &LateContext<'_>, def_id: DefId, diag_items: &[Symbol]) -> Option<usize> {
1547     diag_items
1548         .iter()
1549         .position(|item| cx.tcx.is_diagnostic_item(*item, def_id))
1550 }
1551
1552 /// Checks if the given `DefId` matches the path.
1553 pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool {
1554     // We should probably move to Symbols in Clippy as well rather than interning every time.
1555     let path = cx.get_def_path(did);
1556     syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied())
1557 }
1558
1559 pub fn match_panic_call(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1560     if let ExprKind::Call(func, [arg]) = expr.kind {
1561         expr_path_res(cx, func)
1562             .opt_def_id()
1563             .map_or(false, |id| match_panic_def_id(cx, id))
1564             .then(|| arg)
1565     } else {
1566         None
1567     }
1568 }
1569
1570 pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool {
1571     match_any_def_paths(
1572         cx,
1573         did,
1574         &[
1575             &paths::BEGIN_PANIC,
1576             &paths::BEGIN_PANIC_FMT,
1577             &paths::PANIC_ANY,
1578             &paths::PANICKING_PANIC,
1579             &paths::PANICKING_PANIC_FMT,
1580             &paths::PANICKING_PANIC_STR,
1581         ],
1582     )
1583     .is_some()
1584 }
1585
1586 /// Returns the list of condition expressions and the list of blocks in a
1587 /// sequence of `if/else`.
1588 /// E.g., this returns `([a, b], [c, d, e])` for the expression
1589 /// `if a { c } else if b { d } else { e }`.
1590 pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) {
1591     let mut conds = Vec::new();
1592     let mut blocks: Vec<&Block<'_>> = Vec::new();
1593
1594     while let ExprKind::If(cond, then_expr, ref else_expr) = expr.kind {
1595         conds.push(cond);
1596         if let ExprKind::Block(block, _) = then_expr.kind {
1597             blocks.push(block);
1598         } else {
1599             panic!("ExprKind::If node is not an ExprKind::Block");
1600         }
1601
1602         if let Some(else_expr) = *else_expr {
1603             expr = else_expr;
1604         } else {
1605             break;
1606         }
1607     }
1608
1609     // final `else {..}`
1610     if !blocks.is_empty() {
1611         if let ExprKind::Block(block, _) = expr.kind {
1612             blocks.push(block);
1613         }
1614     }
1615
1616     (conds, blocks)
1617 }
1618
1619 /// Checks if the given function kind is an async function.
1620 pub fn is_async_fn(kind: FnKind<'_>) -> bool {
1621     matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
1622 }
1623
1624 /// Peels away all the compiler generated code surrounding the body of an async function,
1625 pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
1626     if let ExprKind::Call(
1627         _,
1628         &[Expr {
1629             kind: ExprKind::Closure(_, _, body, _, _),
1630             ..
1631         }],
1632     ) = body.value.kind
1633     {
1634         if let ExprKind::Block(
1635             Block {
1636                 stmts: [],
1637                 expr:
1638                     Some(Expr {
1639                         kind: ExprKind::DropTemps(expr),
1640                         ..
1641                     }),
1642                 ..
1643             },
1644             _,
1645         ) = tcx.hir().body(body).value.kind
1646         {
1647             return Some(expr);
1648         }
1649     };
1650     None
1651 }
1652
1653 // Finds the `#[must_use]` attribute, if any
1654 pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
1655     attrs.iter().find(|a| a.has_name(sym::must_use))
1656 }
1657
1658 // check if expr is calling method or function with #[must_use] attribute
1659 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1660     let did = match expr.kind {
1661         ExprKind::Call(path, _) => if_chain! {
1662             if let ExprKind::Path(ref qpath) = path.kind;
1663             if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
1664             then {
1665                 Some(did)
1666             } else {
1667                 None
1668             }
1669         },
1670         ExprKind::MethodCall(_, _, _, _) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1671         _ => None,
1672     };
1673
1674     did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some())
1675 }
1676
1677 /// Checks if an expression represents the identity function
1678 /// Only examines closures and `std::convert::identity`
1679 pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1680     /// Checks if a function's body represents the identity function. Looks for bodies of the form:
1681     /// * `|x| x`
1682     /// * `|x| return x`
1683     /// * `|x| { return x }`
1684     /// * `|x| { return x; }`
1685     fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
1686         let id = if_chain! {
1687             if let [param] = func.params;
1688             if let PatKind::Binding(_, id, _, _) = param.pat.kind;
1689             then {
1690                 id
1691             } else {
1692                 return false;
1693             }
1694         };
1695
1696         let mut expr = &func.value;
1697         loop {
1698             match expr.kind {
1699                 #[rustfmt::skip]
1700                 ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, )
1701                 | ExprKind::Ret(Some(e)) => expr = e,
1702                 #[rustfmt::skip]
1703                 ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => {
1704                     if_chain! {
1705                         if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
1706                         if let ExprKind::Ret(Some(ret_val)) = e.kind;
1707                         then {
1708                             expr = ret_val;
1709                         } else {
1710                             return false;
1711                         }
1712                     }
1713                 },
1714                 _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
1715             }
1716         }
1717     }
1718
1719     match expr.kind {
1720         ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
1721         ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY),
1722         _ => false,
1723     }
1724 }
1725
1726 /// Gets the node where an expression is either used, or it's type is unified with another branch.
1727 pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
1728     let map = tcx.hir();
1729     let mut child_id = expr.hir_id;
1730     let mut iter = map.parent_iter(child_id);
1731     loop {
1732         match iter.next() {
1733             None => break None,
1734             Some((id, Node::Block(_))) => child_id = id,
1735             Some((id, Node::Arm(arm))) if arm.body.hir_id == child_id => child_id = id,
1736             Some((_, Node::Expr(expr))) => match expr.kind {
1737                 ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id,
1738                 ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id,
1739                 ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None,
1740                 _ => break Some(Node::Expr(expr)),
1741             },
1742             Some((_, node)) => break Some(node),
1743         }
1744     }
1745 }
1746
1747 /// Checks if the result of an expression is used, or it's type is unified with another branch.
1748 pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1749     !matches!(
1750         get_expr_use_or_unification_node(tcx, expr),
1751         None | Some(Node::Stmt(Stmt {
1752             kind: StmtKind::Expr(_)
1753                 | StmtKind::Semi(_)
1754                 | StmtKind::Local(Local {
1755                     pat: Pat {
1756                         kind: PatKind::Wild,
1757                         ..
1758                     },
1759                     ..
1760                 }),
1761             ..
1762         }))
1763     )
1764 }
1765
1766 /// Checks if the expression is the final expression returned from a block.
1767 pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1768     matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..)))
1769 }
1770
1771 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
1772     cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
1773         if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
1774             attr.path == sym::no_std
1775         } else {
1776             false
1777         }
1778     })
1779 }
1780
1781 /// Check if parent of a hir node is a trait implementation block.
1782 /// For example, `f` in
1783 /// ```rust,ignore
1784 /// impl Trait for S {
1785 ///     fn f() {}
1786 /// }
1787 /// ```
1788 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
1789     if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
1790         matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
1791     } else {
1792         false
1793     }
1794 }
1795
1796 /// Check if it's even possible to satisfy the `where` clause for the item.
1797 ///
1798 /// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example:
1799 ///
1800 /// ```ignore
1801 /// fn foo() where i32: Iterator {
1802 ///     for _ in 2i32 {}
1803 /// }
1804 /// ```
1805 pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
1806     use rustc_trait_selection::traits;
1807     let predicates = cx
1808         .tcx
1809         .predicates_of(did)
1810         .predicates
1811         .iter()
1812         .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
1813     traits::impossible_predicates(
1814         cx.tcx,
1815         traits::elaborate_predicates(cx.tcx, predicates)
1816             .map(|o| o.predicate)
1817             .collect::<Vec<_>>(),
1818     )
1819 }
1820
1821 /// Returns the `DefId` of the callee if the given expression is a function or method call.
1822 pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
1823     match &expr.kind {
1824         ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1825         ExprKind::Call(
1826             Expr {
1827                 kind: ExprKind::Path(qpath),
1828                 hir_id: path_hir_id,
1829                 ..
1830             },
1831             ..,
1832         ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
1833         _ => None,
1834     }
1835 }
1836
1837 /// Returns Option<String> where String is a textual representation of the type encapsulated in the
1838 /// slice iff the given expression is a slice of primitives (as defined in the
1839 /// `is_recursively_primitive_type` function) and None otherwise.
1840 pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
1841     let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
1842     let expr_kind = expr_type.kind();
1843     let is_primitive = match expr_kind {
1844         rustc_ty::Slice(element_type) => is_recursively_primitive_type(element_type),
1845         rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => {
1846             if let rustc_ty::Slice(element_type) = inner_ty.kind() {
1847                 is_recursively_primitive_type(element_type)
1848             } else {
1849                 unreachable!()
1850             }
1851         },
1852         _ => false,
1853     };
1854
1855     if is_primitive {
1856         // if we have wrappers like Array, Slice or Tuple, print these
1857         // and get the type enclosed in the slice ref
1858         match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
1859             rustc_ty::Slice(..) => return Some("slice".into()),
1860             rustc_ty::Array(..) => return Some("array".into()),
1861             rustc_ty::Tuple(..) => return Some("tuple".into()),
1862             _ => {
1863                 // is_recursively_primitive_type() should have taken care
1864                 // of the rest and we can rely on the type that is found
1865                 let refs_peeled = expr_type.peel_refs();
1866                 return Some(refs_peeled.walk().last().unwrap().to_string());
1867             },
1868         }
1869     }
1870     None
1871 }
1872
1873 /// returns list of all pairs (a, b) from `exprs` such that `eq(a, b)`
1874 /// `hash` must be comformed with `eq`
1875 pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
1876 where
1877     Hash: Fn(&T) -> u64,
1878     Eq: Fn(&T, &T) -> bool,
1879 {
1880     match exprs {
1881         [a, b] if eq(a, b) => return vec![(a, b)],
1882         _ if exprs.len() <= 2 => return vec![],
1883         _ => {},
1884     }
1885
1886     let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
1887
1888     let mut map: UnhashMap<u64, Vec<&_>> =
1889         UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
1890
1891     for expr in exprs {
1892         match map.entry(hash(expr)) {
1893             Entry::Occupied(mut o) => {
1894                 for o in o.get() {
1895                     if eq(o, expr) {
1896                         match_expr_list.push((o, expr));
1897                     }
1898                 }
1899                 o.get_mut().push(expr);
1900             },
1901             Entry::Vacant(v) => {
1902                 v.insert(vec![expr]);
1903             },
1904         }
1905     }
1906
1907     match_expr_list
1908 }
1909
1910 /// Peels off all references on the pattern. Returns the underlying pattern and the number of
1911 /// references removed.
1912 pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
1913     fn peel(pat: &'a Pat<'a>, count: usize) -> (&'a Pat<'a>, usize) {
1914         if let PatKind::Ref(pat, _) = pat.kind {
1915             peel(pat, count + 1)
1916         } else {
1917             (pat, count)
1918         }
1919     }
1920     peel(pat, 0)
1921 }
1922
1923 /// Peels of expressions while the given closure returns `Some`.
1924 pub fn peel_hir_expr_while<'tcx>(
1925     mut expr: &'tcx Expr<'tcx>,
1926     mut f: impl FnMut(&'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>>,
1927 ) -> &'tcx Expr<'tcx> {
1928     while let Some(e) = f(expr) {
1929         expr = e;
1930     }
1931     expr
1932 }
1933
1934 /// Peels off up to the given number of references on the expression. Returns the underlying
1935 /// expression and the number of references removed.
1936 pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
1937     let mut remaining = count;
1938     let e = peel_hir_expr_while(expr, |e| match e.kind {
1939         ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) if remaining != 0 => {
1940             remaining -= 1;
1941             Some(e)
1942         },
1943         _ => None,
1944     });
1945     (e, count - remaining)
1946 }
1947
1948 /// Peels off all references on the expression. Returns the underlying expression and the number of
1949 /// references removed.
1950 pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
1951     let mut count = 0;
1952     let e = peel_hir_expr_while(expr, |e| match e.kind {
1953         ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) => {
1954             count += 1;
1955             Some(e)
1956         },
1957         _ => None,
1958     });
1959     (e, count)
1960 }
1961
1962 /// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
1963 /// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
1964 pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
1965     loop {
1966         match expr.kind {
1967             ExprKind::AddrOf(_, _, e) => expr = e,
1968             ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
1969             _ => break,
1970         }
1971     }
1972     expr
1973 }
1974
1975 #[macro_export]
1976 macro_rules! unwrap_cargo_metadata {
1977     ($cx: ident, $lint: ident, $deps: expr) => {{
1978         let mut command = cargo_metadata::MetadataCommand::new();
1979         if !$deps {
1980             command.no_deps();
1981         }
1982
1983         match command.exec() {
1984             Ok(metadata) => metadata,
1985             Err(err) => {
1986                 span_lint($cx, $lint, DUMMY_SP, &format!("could not read cargo metadata: {}", err));
1987                 return;
1988             },
1989         }
1990     }};
1991 }
1992
1993 pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
1994     if_chain! {
1995         if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
1996         if let Res::Def(_, def_id) = path.res;
1997         then {
1998             cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr)
1999         } else {
2000             false
2001         }
2002     }
2003 }
2004
2005 /// Checks whether item either has `test` attribute applied, or
2006 /// is a module with `test` in its name.
2007 pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
2008     if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) {
2009         if tcx.has_attr(def_id.to_def_id(), sym::test) {
2010             return true;
2011         }
2012     }
2013
2014     matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
2015 }
2016
2017 macro_rules! op_utils {
2018     ($($name:ident $assign:ident)*) => {
2019         /// Binary operation traits like `LangItem::Add`
2020         pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
2021
2022         /// Operator-Assign traits like `LangItem::AddAssign`
2023         pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
2024
2025         /// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
2026         pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
2027             match kind {
2028                 $(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
2029                 _ => None,
2030             }
2031         }
2032     };
2033 }
2034
2035 op_utils! {
2036     Add    AddAssign
2037     Sub    SubAssign
2038     Mul    MulAssign
2039     Div    DivAssign
2040     Rem    RemAssign
2041     BitXor BitXorAssign
2042     BitAnd BitAndAssign
2043     BitOr  BitOrAssign
2044     Shl    ShlAssign
2045     Shr    ShrAssign
2046 }