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