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