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