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