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