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