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