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