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