]> git.lizzy.rs Git - rust.git/blob - clippy_utils/src/lib.rs
Fix `option_if_let_else`
[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 loop HIR ids.
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 ///
639 /// For example, given the following function:
640 ///
641 /// ```
642 /// fn f<'a>(iter: &mut impl Iterator<Item = (usize, &'a mut String)>) {
643 ///     for item in iter {
644 ///         let s = item.1;
645 ///         if item.0 > 10 {
646 ///             continue;
647 ///         } else {
648 ///             s.clear();
649 ///         }
650 ///     }
651 /// }
652 /// ```
653 ///
654 /// When called on the expression `item.0` this will return false unless the local `item` is in the
655 /// `ignore_locals` set. The type `(usize, &mut String)` can have the second element moved, so it
656 /// isn't always safe to move into a closure when only a single field is needed.
657 ///
658 /// When called on the `continue` expression this will return false unless the outer loop expression
659 /// is in the `loop_ids` set.
660 ///
661 /// Note that this check is not recursive, so passing the `if` expression will always return true
662 /// even though sub-expressions might return false.
663 pub fn can_move_expr_to_closure_no_visit(
664     cx: &LateContext<'tcx>,
665     expr: &'tcx Expr<'_>,
666     loop_ids: &[HirId],
667     ignore_locals: &HirIdSet,
668 ) -> bool {
669     match expr.kind {
670         ExprKind::Break(Destination { target_id: Ok(id), .. }, _)
671         | ExprKind::Continue(Destination { target_id: Ok(id), .. })
672             if loop_ids.contains(&id) =>
673         {
674             true
675         },
676         ExprKind::Break(..)
677         | ExprKind::Continue(_)
678         | ExprKind::Ret(_)
679         | ExprKind::Yield(..)
680         | ExprKind::InlineAsm(_)
681         | ExprKind::LlvmInlineAsm(_) => false,
682         // Accessing a field of a local value can only be done if the type isn't
683         // partially moved.
684         ExprKind::Field(
685             &Expr {
686                 hir_id,
687                 kind:
688                     ExprKind::Path(QPath::Resolved(
689                         _,
690                         Path {
691                             res: Res::Local(local_id),
692                             ..
693                         },
694                     )),
695                 ..
696             },
697             _,
698         ) if !ignore_locals.contains(local_id) && can_partially_move_ty(cx, cx.typeck_results().node_type(hir_id)) => {
699             // TODO: check if the local has been partially moved. Assume it has for now.
700             false
701         },
702         _ => true,
703     }
704 }
705
706 /// How a local is captured by a closure
707 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
708 pub enum CaptureKind {
709     Value,
710     Ref(Mutability),
711 }
712 impl CaptureKind {
713     pub fn is_imm_ref(self) -> bool {
714         self == Self::Ref(Mutability::Not)
715     }
716 }
717 impl std::ops::BitOr for CaptureKind {
718     type Output = Self;
719     fn bitor(self, rhs: Self) -> Self::Output {
720         match (self, rhs) {
721             (CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
722             (CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
723             | (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
724             (CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
725         }
726     }
727 }
728 impl std::ops::BitOrAssign for CaptureKind {
729     fn bitor_assign(&mut self, rhs: Self) {
730         *self = *self | rhs;
731     }
732 }
733
734 /// Given an expression referencing a local, determines how it would be captured in a closure.
735 /// Note as this will walk up to parent expressions until the capture can be determined it should
736 /// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
737 /// function argument (other than a receiver).
738 pub fn capture_local_usage(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind {
739     fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
740         let mut capture = CaptureKind::Ref(Mutability::Not);
741         pat.each_binding_or_first(&mut |_, id, span, _| match cx
742             .typeck_results()
743             .extract_binding_mode(cx.sess(), id, span)
744             .unwrap()
745         {
746             BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => {
747                 capture = CaptureKind::Value;
748             },
749             BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => {
750                 capture = CaptureKind::Ref(Mutability::Mut);
751             },
752             _ => (),
753         });
754         capture
755     }
756
757     debug_assert!(matches!(
758         e.kind,
759         ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
760     ));
761
762     let map = cx.tcx.hir();
763     let mut child_id = e.hir_id;
764     let mut capture = CaptureKind::Value;
765     let mut capture_expr_ty = e;
766
767     for (parent_id, parent) in map.parent_iter(e.hir_id) {
768         if let [Adjustment {
769             kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
770             target,
771         }, ref adjust @ ..] = *cx
772             .typeck_results()
773             .adjustments()
774             .get(child_id)
775             .map_or(&[][..], |x| &**x)
776         {
777             if let rustc_ty::RawPtr(TypeAndMut { mutbl: mutability, .. }) | rustc_ty::Ref(_, _, mutability) =
778                 *adjust.last().map_or(target, |a| a.target).kind()
779             {
780                 return CaptureKind::Ref(mutability);
781             }
782         }
783
784         match parent {
785             Node::Expr(e) => match e.kind {
786                 ExprKind::AddrOf(_, mutability, _) => return CaptureKind::Ref(mutability),
787                 ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, _) => capture = CaptureKind::Ref(Mutability::Not),
788                 ExprKind::Assign(lhs, ..) | ExprKind::Assign(_, lhs, _) if lhs.hir_id == child_id => {
789                     return CaptureKind::Ref(Mutability::Mut);
790                 },
791                 ExprKind::Field(..) => {
792                     if capture == CaptureKind::Value {
793                         capture_expr_ty = e;
794                     }
795                 },
796                 ExprKind::Match(_, arms, _) => {
797                     let mut mutability = Mutability::Not;
798                     for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
799                         match capture {
800                             CaptureKind::Value => break,
801                             CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
802                             CaptureKind::Ref(Mutability::Not) => (),
803                         }
804                     }
805                     return CaptureKind::Ref(mutability);
806                 },
807                 _ => break,
808             },
809             Node::Local(l) => match pat_capture_kind(cx, l.pat) {
810                 CaptureKind::Value => break,
811                 capture @ CaptureKind::Ref(_) => return capture,
812             },
813             _ => break,
814         }
815
816         child_id = parent_id;
817     }
818
819     if capture == CaptureKind::Value && is_copy(cx, cx.typeck_results().expr_ty(capture_expr_ty)) {
820         // Copy types are never automatically captured by value.
821         CaptureKind::Ref(Mutability::Not)
822     } else {
823         capture
824     }
825 }
826
827 /// Checks if the expression can be moved into a closure as is. This will return a list of captures
828 /// if so, otherwise, `None`.
829 pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<HirIdMap<CaptureKind>> {
830     struct V<'cx, 'tcx> {
831         cx: &'cx LateContext<'tcx>,
832         // Stack of potential break targets contained in the expression.
833         loops: Vec<HirId>,
834         /// Local variables created in the expression. These don't need to be captured.
835         locals: HirIdSet,
836         /// Whether this expression can be turned into a closure.
837         allow_closure: bool,
838         /// Locals which need to be captured, and whether they need to be by value, reference, or
839         /// mutable reference.
840         captures: HirIdMap<CaptureKind>,
841     }
842     impl Visitor<'tcx> for V<'_, 'tcx> {
843         type Map = ErasedMap<'tcx>;
844         fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
845             NestedVisitorMap::None
846         }
847
848         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
849             if !self.allow_closure {
850                 return;
851             }
852
853             match e.kind {
854                 ExprKind::Path(QPath::Resolved(None, &Path { res: Res::Local(l), .. })) => {
855                     if !self.locals.contains(&l) {
856                         let cap = capture_local_usage(self.cx, e);
857                         self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
858                     }
859                 },
860                 ExprKind::Closure(..) => {
861                     let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id();
862                     for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
863                         let local_id = match capture.place.base {
864                             PlaceBase::Local(id) => id,
865                             PlaceBase::Upvar(var) => var.var_path.hir_id,
866                             _ => continue,
867                         };
868                         if !self.locals.contains(&local_id) {
869                             let capture = match capture.info.capture_kind {
870                                 UpvarCapture::ByValue(_) => CaptureKind::Value,
871                                 UpvarCapture::ByRef(borrow) => match borrow.kind {
872                                     BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
873                                     BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
874                                         CaptureKind::Ref(Mutability::Mut)
875                                     },
876                                 },
877                             };
878                             self.captures
879                                 .entry(local_id)
880                                 .and_modify(|e| *e |= capture)
881                                 .or_insert(capture);
882                         }
883                     }
884                 },
885                 ExprKind::Loop(b, ..) => {
886                     self.loops.push(e.hir_id);
887                     self.visit_block(b);
888                     self.loops.pop();
889                 },
890                 _ => {
891                     self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops, &self.locals);
892                     walk_expr(self, e);
893                 },
894             }
895         }
896
897         fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
898             p.each_binding_or_first(&mut |_, id, _, _| {
899                 self.locals.insert(id);
900             });
901         }
902     }
903
904     let mut v = V {
905         cx,
906         allow_closure: true,
907         loops: Vec::new(),
908         locals: HirIdSet::default(),
909         captures: HirIdMap::default(),
910     };
911     v.visit_expr(expr);
912     v.allow_closure.then(|| v.captures)
913 }
914
915 /// Returns the method names and argument list of nested method call expressions that make up
916 /// `expr`. method/span lists are sorted with the most recent call first.
917 pub fn method_calls<'tcx>(
918     expr: &'tcx Expr<'tcx>,
919     max_depth: usize,
920 ) -> (Vec<Symbol>, Vec<&'tcx [Expr<'tcx>]>, Vec<Span>) {
921     let mut method_names = Vec::with_capacity(max_depth);
922     let mut arg_lists = Vec::with_capacity(max_depth);
923     let mut spans = Vec::with_capacity(max_depth);
924
925     let mut current = expr;
926     for _ in 0..max_depth {
927         if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
928             if args.iter().any(|e| e.span.from_expansion()) {
929                 break;
930             }
931             method_names.push(path.ident.name);
932             arg_lists.push(&**args);
933             spans.push(*span);
934             current = &args[0];
935         } else {
936             break;
937         }
938     }
939
940     (method_names, arg_lists, spans)
941 }
942
943 /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
944 ///
945 /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
946 /// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
947 /// containing the `Expr`s for
948 /// `.bar()` and `.baz()`
949 pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
950     let mut current = expr;
951     let mut matched = Vec::with_capacity(methods.len());
952     for method_name in methods.iter().rev() {
953         // method chains are stored last -> first
954         if let ExprKind::MethodCall(path, _, args, _) = current.kind {
955             if path.ident.name.as_str() == *method_name {
956                 if args.iter().any(|e| e.span.from_expansion()) {
957                     return None;
958                 }
959                 matched.push(args); // build up `matched` backwards
960                 current = &args[0]; // go to parent expression
961             } else {
962                 return None;
963             }
964         } else {
965             return None;
966         }
967     }
968     // Reverse `matched` so that it is in the same order as `methods`.
969     matched.reverse();
970     Some(matched)
971 }
972
973 /// Returns `true` if the provided `def_id` is an entrypoint to a program.
974 pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
975     cx.tcx
976         .entry_fn(())
977         .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id)
978 }
979
980 /// Returns `true` if the expression is in the program's `#[panic_handler]`.
981 pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
982     let parent = cx.tcx.hir().get_parent_item(e.hir_id);
983     let def_id = cx.tcx.hir().local_def_id(parent).to_def_id();
984     Some(def_id) == cx.tcx.lang_items().panic_impl()
985 }
986
987 /// Gets the name of the item the expression is in, if available.
988 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
989     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
990     match cx.tcx.hir().find(parent_id) {
991         Some(
992             Node::Item(Item { ident, .. })
993             | Node::TraitItem(TraitItem { ident, .. })
994             | Node::ImplItem(ImplItem { ident, .. }),
995         ) => Some(ident.name),
996         _ => None,
997     }
998 }
999
1000 pub struct ContainsName {
1001     pub name: Symbol,
1002     pub result: bool,
1003 }
1004
1005 impl<'tcx> Visitor<'tcx> for ContainsName {
1006     type Map = Map<'tcx>;
1007
1008     fn visit_name(&mut self, _: Span, name: Symbol) {
1009         if self.name == name {
1010             self.result = true;
1011         }
1012     }
1013     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
1014         NestedVisitorMap::None
1015     }
1016 }
1017
1018 /// Checks if an `Expr` contains a certain name.
1019 pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
1020     let mut cn = ContainsName { name, result: false };
1021     cn.visit_expr(expr);
1022     cn.result
1023 }
1024
1025 /// Returns `true` if `expr` contains a return expression
1026 pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
1027     struct RetCallFinder {
1028         found: bool,
1029     }
1030
1031     impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder {
1032         type Map = Map<'tcx>;
1033
1034         fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
1035             if self.found {
1036                 return;
1037             }
1038             if let hir::ExprKind::Ret(..) = &expr.kind {
1039                 self.found = true;
1040             } else {
1041                 hir::intravisit::walk_expr(self, expr);
1042             }
1043         }
1044
1045         fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
1046             hir::intravisit::NestedVisitorMap::None
1047         }
1048     }
1049
1050     let mut visitor = RetCallFinder { found: false };
1051     visitor.visit_expr(expr);
1052     visitor.found
1053 }
1054
1055 struct FindMacroCalls<'a, 'b> {
1056     names: &'a [&'b str],
1057     result: Vec<Span>,
1058 }
1059
1060 impl<'a, 'b, 'tcx> Visitor<'tcx> for FindMacroCalls<'a, 'b> {
1061     type Map = Map<'tcx>;
1062
1063     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
1064         if self.names.iter().any(|fun| is_expn_of(expr.span, fun).is_some()) {
1065             self.result.push(expr.span);
1066         }
1067         // and check sub-expressions
1068         intravisit::walk_expr(self, expr);
1069     }
1070
1071     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
1072         NestedVisitorMap::None
1073     }
1074 }
1075
1076 /// Finds calls of the specified macros in a function body.
1077 pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> {
1078     let mut fmc = FindMacroCalls {
1079         names,
1080         result: Vec::new(),
1081     };
1082     fmc.visit_expr(&body.value);
1083     fmc.result
1084 }
1085
1086 /// Extends the span to the beginning of the spans line, incl. whitespaces.
1087 ///
1088 /// ```rust,ignore
1089 ///        let x = ();
1090 /// //             ^^
1091 /// // will be converted to
1092 ///        let x = ();
1093 /// // ^^^^^^^^^^^^^^
1094 /// ```
1095 fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
1096     let span = original_sp(span, DUMMY_SP);
1097     let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
1098     let line_no = source_map_and_line.line;
1099     let line_start = source_map_and_line.sf.lines[line_no];
1100     Span::new(line_start, span.hi(), span.ctxt())
1101 }
1102
1103 /// Gets the parent node, if any.
1104 pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
1105     tcx.hir().parent_iter(id).next().map(|(_, node)| node)
1106 }
1107
1108 /// Gets the parent expression, if any â€“- this is useful to constrain a lint.
1109 pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1110     get_parent_expr_for_hir(cx, e.hir_id)
1111 }
1112
1113 /// This retrieves the parent for the given `HirId` if it's an expression. This is useful for
1114 /// constraint lints
1115 pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> {
1116     match get_parent_node(cx.tcx, hir_id) {
1117         Some(Node::Expr(parent)) => Some(parent),
1118         _ => None,
1119     }
1120 }
1121
1122 pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
1123     let map = &cx.tcx.hir();
1124     let enclosing_node = map
1125         .get_enclosing_scope(hir_id)
1126         .and_then(|enclosing_id| map.find(enclosing_id));
1127     enclosing_node.and_then(|node| match node {
1128         Node::Block(block) => Some(block),
1129         Node::Item(&Item {
1130             kind: ItemKind::Fn(_, _, eid),
1131             ..
1132         })
1133         | Node::ImplItem(&ImplItem {
1134             kind: ImplItemKind::Fn(_, eid),
1135             ..
1136         }) => match cx.tcx.hir().body(eid).value.kind {
1137             ExprKind::Block(block, _) => Some(block),
1138             _ => None,
1139         },
1140         _ => None,
1141     })
1142 }
1143
1144 /// Gets the loop or closure enclosing the given expression, if any.
1145 pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1146     let map = tcx.hir();
1147     for (_, node) in map.parent_iter(expr.hir_id) {
1148         match node {
1149             Node::Expr(
1150                 e
1151                 @
1152                 Expr {
1153                     kind: ExprKind::Loop(..) | ExprKind::Closure(..),
1154                     ..
1155                 },
1156             ) => return Some(e),
1157             Node::Expr(_) | Node::Stmt(_) | Node::Block(_) | Node::Local(_) | Node::Arm(_) => (),
1158             _ => break,
1159         }
1160     }
1161     None
1162 }
1163
1164 /// Gets the parent node if it's an impl block.
1165 pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
1166     let map = tcx.hir();
1167     match map.parent_iter(id).next() {
1168         Some((
1169             _,
1170             Node::Item(Item {
1171                 kind: ItemKind::Impl(imp),
1172                 ..
1173             }),
1174         )) => Some(imp),
1175         _ => None,
1176     }
1177 }
1178
1179 /// Checks if the given expression is the else clause of either an `if` or `if let` expression.
1180 pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1181     let map = tcx.hir();
1182     let mut iter = map.parent_iter(expr.hir_id);
1183     match iter.next() {
1184         Some((arm_id, Node::Arm(..))) => matches!(
1185             iter.next(),
1186             Some((
1187                 _,
1188                 Node::Expr(Expr {
1189                     kind: ExprKind::Match(_, [_, else_arm], MatchSource::IfLetDesugar { .. }),
1190                     ..
1191                 })
1192             ))
1193             if else_arm.hir_id == arm_id
1194         ),
1195         Some((
1196             _,
1197             Node::Expr(Expr {
1198                 kind: ExprKind::If(_, _, Some(else_expr)),
1199                 ..
1200             }),
1201         )) => else_expr.hir_id == expr.hir_id,
1202         _ => false,
1203     }
1204 }
1205
1206 /// Checks whether the given expression is a constant integer of the given value.
1207 /// unlike `is_integer_literal`, this version does const folding
1208 pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
1209     if is_integer_literal(e, value) {
1210         return true;
1211     }
1212     let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id));
1213     if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
1214         value == v
1215     } else {
1216         false
1217     }
1218 }
1219
1220 /// Checks whether the given expression is a constant literal of the given value.
1221 pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
1222     // FIXME: use constant folding
1223     if let ExprKind::Lit(ref spanned) = expr.kind {
1224         if let LitKind::Int(v, _) = spanned.node {
1225             return v == value;
1226         }
1227     }
1228     false
1229 }
1230
1231 /// Returns `true` if the given `Expr` has been coerced before.
1232 ///
1233 /// Examples of coercions can be found in the Nomicon at
1234 /// <https://doc.rust-lang.org/nomicon/coercions.html>.
1235 ///
1236 /// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
1237 /// information on adjustments and coercions.
1238 pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
1239     cx.typeck_results().adjustments().get(e.hir_id).is_some()
1240 }
1241
1242 /// Returns the pre-expansion span if is this comes from an expansion of the
1243 /// macro `name`.
1244 /// See also `is_direct_expn_of`.
1245 #[must_use]
1246 pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
1247     loop {
1248         if span.from_expansion() {
1249             let data = span.ctxt().outer_expn_data();
1250             let new_span = data.call_site;
1251
1252             if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1253                 if mac_name.as_str() == name {
1254                     return Some(new_span);
1255                 }
1256             }
1257
1258             span = new_span;
1259         } else {
1260             return None;
1261         }
1262     }
1263 }
1264
1265 /// Returns the pre-expansion span if the span directly comes from an expansion
1266 /// of the macro `name`.
1267 /// The difference with `is_expn_of` is that in
1268 /// ```rust,ignore
1269 /// foo!(bar!(42));
1270 /// ```
1271 /// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
1272 /// `bar!` by
1273 /// `is_direct_expn_of`.
1274 #[must_use]
1275 pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
1276     if span.from_expansion() {
1277         let data = span.ctxt().outer_expn_data();
1278         let new_span = data.call_site;
1279
1280         if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1281             if mac_name.as_str() == name {
1282                 return Some(new_span);
1283             }
1284         }
1285     }
1286
1287     None
1288 }
1289
1290 /// Convenience function to get the return type of a function.
1291 pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
1292     let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
1293     let ret_ty = cx.tcx.fn_sig(fn_def_id).output();
1294     cx.tcx.erase_late_bound_regions(ret_ty)
1295 }
1296
1297 /// Checks if an expression is constructing a tuple-like enum variant or struct
1298 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1299     if let ExprKind::Call(fun, _) = expr.kind {
1300         if let ExprKind::Path(ref qp) = fun.kind {
1301             let res = cx.qpath_res(qp, fun.hir_id);
1302             return match res {
1303                 def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
1304                 def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
1305                 _ => false,
1306             };
1307         }
1308     }
1309     false
1310 }
1311
1312 /// Returns `true` if a pattern is refutable.
1313 // TODO: should be implemented using rustc/mir_build/thir machinery
1314 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
1315     fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
1316         matches!(
1317             cx.qpath_res(qpath, id),
1318             def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
1319         )
1320     }
1321
1322     fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
1323         i.into_iter().any(|pat| is_refutable(cx, pat))
1324     }
1325
1326     match pat.kind {
1327         PatKind::Wild => false,
1328         PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
1329         PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
1330         PatKind::Lit(..) | PatKind::Range(..) => true,
1331         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
1332         PatKind::Or(pats) => {
1333             // TODO: should be the honest check, that pats is exhaustive set
1334             are_refutable(cx, pats)
1335         },
1336         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
1337         PatKind::Struct(ref qpath, fields, _) => {
1338             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
1339         },
1340         PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
1341         PatKind::Slice(head, middle, tail) => {
1342             match &cx.typeck_results().node_type(pat.hir_id).kind() {
1343                 rustc_ty::Slice(..) => {
1344                     // [..] is the only irrefutable slice pattern.
1345                     !head.is_empty() || middle.is_none() || !tail.is_empty()
1346                 },
1347                 rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
1348                 _ => {
1349                     // unreachable!()
1350                     true
1351                 },
1352             }
1353         },
1354     }
1355 }
1356
1357 /// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call
1358 /// the function once on the given pattern.
1359 pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
1360     if let PatKind::Or(pats) = pat.kind {
1361         pats.iter().for_each(f);
1362     } else {
1363         f(pat);
1364     }
1365 }
1366
1367 /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
1368 /// implementations have.
1369 pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
1370     attrs.iter().any(|attr| attr.has_name(sym::automatically_derived))
1371 }
1372
1373 /// Remove blocks around an expression.
1374 ///
1375 /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return
1376 /// themselves.
1377 pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
1378     while let ExprKind::Block(block, ..) = expr.kind {
1379         match (block.stmts.is_empty(), block.expr.as_ref()) {
1380             (true, Some(e)) => expr = e,
1381             _ => break,
1382         }
1383     }
1384     expr
1385 }
1386
1387 pub fn is_self(slf: &Param<'_>) -> bool {
1388     if let PatKind::Binding(.., name, _) = slf.pat.kind {
1389         name.name == kw::SelfLower
1390     } else {
1391         false
1392     }
1393 }
1394
1395 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
1396     if_chain! {
1397         if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind;
1398         if let Res::SelfTy(..) = path.res;
1399         then {
1400             return true
1401         }
1402     }
1403     false
1404 }
1405
1406 pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator<Item = &'tcx Param<'tcx>> {
1407     (0..decl.inputs.len()).map(move |i| &body.params[i])
1408 }
1409
1410 /// Checks if a given expression is a match expression expanded from the `?`
1411 /// operator or the `try` macro.
1412 pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
1413     fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1414         if_chain! {
1415             if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind;
1416             if is_lang_ctor(cx, path, ResultOk);
1417             if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
1418             if path_to_local_id(arm.body, hir_id);
1419             then {
1420                 return true;
1421             }
1422         }
1423         false
1424     }
1425
1426     fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1427         if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
1428             is_lang_ctor(cx, path, ResultErr)
1429         } else {
1430             false
1431         }
1432     }
1433
1434     if let ExprKind::Match(_, arms, ref source) = expr.kind {
1435         // desugared from a `?` operator
1436         if let MatchSource::TryDesugar = *source {
1437             return Some(expr);
1438         }
1439
1440         if_chain! {
1441             if arms.len() == 2;
1442             if arms[0].guard.is_none();
1443             if arms[1].guard.is_none();
1444             if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) ||
1445                 (is_ok(cx, &arms[1]) && is_err(cx, &arms[0]));
1446             then {
1447                 return Some(expr);
1448             }
1449         }
1450     }
1451
1452     None
1453 }
1454
1455 /// Returns `true` if the lint is allowed in the current context
1456 ///
1457 /// Useful for skipping long running code when it's unnecessary
1458 pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
1459     cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
1460 }
1461
1462 pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
1463     while let PatKind::Ref(subpat, _) = pat.kind {
1464         pat = subpat;
1465     }
1466     pat
1467 }
1468
1469 pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 {
1470     Integer::from_int_ty(&tcx, ity).size().bits()
1471 }
1472
1473 #[allow(clippy::cast_possible_wrap)]
1474 /// Turn a constant int byte representation into an i128
1475 pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 {
1476     let amt = 128 - int_bits(tcx, ity);
1477     ((u as i128) << amt) >> amt
1478 }
1479
1480 #[allow(clippy::cast_sign_loss)]
1481 /// clip unused bytes
1482 pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 {
1483     let amt = 128 - int_bits(tcx, ity);
1484     ((u as u128) << amt) >> amt
1485 }
1486
1487 /// clip unused bytes
1488 pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 {
1489     let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
1490     let amt = 128 - bits;
1491     (u << amt) >> amt
1492 }
1493
1494 pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
1495     let map = &tcx.hir();
1496     let mut prev_enclosing_node = None;
1497     let mut enclosing_node = node;
1498     while Some(enclosing_node) != prev_enclosing_node {
1499         if is_automatically_derived(map.attrs(enclosing_node)) {
1500             return true;
1501         }
1502         prev_enclosing_node = Some(enclosing_node);
1503         enclosing_node = map.get_parent_item(enclosing_node);
1504     }
1505     false
1506 }
1507
1508 /// Matches a function call with the given path and returns the arguments.
1509 ///
1510 /// Usage:
1511 ///
1512 /// ```rust,ignore
1513 /// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
1514 /// ```
1515 pub fn match_function_call<'tcx>(
1516     cx: &LateContext<'tcx>,
1517     expr: &'tcx Expr<'_>,
1518     path: &[&str],
1519 ) -> Option<&'tcx [Expr<'tcx>]> {
1520     if_chain! {
1521         if let ExprKind::Call(fun, args) = expr.kind;
1522         if let ExprKind::Path(ref qpath) = fun.kind;
1523         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
1524         if match_def_path(cx, fun_def_id, path);
1525         then {
1526             return Some(args)
1527         }
1528     };
1529     None
1530 }
1531
1532 /// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
1533 /// any.
1534 ///
1535 /// Please use `match_any_diagnostic_items` if the targets are all diagnostic items.
1536 pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]]) -> Option<usize> {
1537     let search_path = cx.get_def_path(did);
1538     paths
1539         .iter()
1540         .position(|p| p.iter().map(|x| Symbol::intern(x)).eq(search_path.iter().copied()))
1541 }
1542
1543 /// Checks if the given `DefId` matches any of provided diagnostic items. Returns the index of
1544 /// matching path, if any.
1545 pub fn match_any_diagnostic_items(cx: &LateContext<'_>, def_id: DefId, diag_items: &[Symbol]) -> Option<usize> {
1546     diag_items
1547         .iter()
1548         .position(|item| cx.tcx.is_diagnostic_item(*item, def_id))
1549 }
1550
1551 /// Checks if the given `DefId` matches the path.
1552 pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool {
1553     // We should probably move to Symbols in Clippy as well rather than interning every time.
1554     let path = cx.get_def_path(did);
1555     syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied())
1556 }
1557
1558 pub fn match_panic_call(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1559     if let ExprKind::Call(func, [arg]) = expr.kind {
1560         expr_path_res(cx, func)
1561             .opt_def_id()
1562             .map_or(false, |id| match_panic_def_id(cx, id))
1563             .then(|| arg)
1564     } else {
1565         None
1566     }
1567 }
1568
1569 pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool {
1570     match_any_def_paths(
1571         cx,
1572         did,
1573         &[
1574             &paths::BEGIN_PANIC,
1575             &paths::BEGIN_PANIC_FMT,
1576             &paths::PANIC_ANY,
1577             &paths::PANICKING_PANIC,
1578             &paths::PANICKING_PANIC_FMT,
1579             &paths::PANICKING_PANIC_STR,
1580         ],
1581     )
1582     .is_some()
1583 }
1584
1585 /// Returns the list of condition expressions and the list of blocks in a
1586 /// sequence of `if/else`.
1587 /// E.g., this returns `([a, b], [c, d, e])` for the expression
1588 /// `if a { c } else if b { d } else { e }`.
1589 pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) {
1590     let mut conds = Vec::new();
1591     let mut blocks: Vec<&Block<'_>> = Vec::new();
1592
1593     while let ExprKind::If(cond, then_expr, ref else_expr) = expr.kind {
1594         conds.push(cond);
1595         if let ExprKind::Block(block, _) = then_expr.kind {
1596             blocks.push(block);
1597         } else {
1598             panic!("ExprKind::If node is not an ExprKind::Block");
1599         }
1600
1601         if let Some(else_expr) = *else_expr {
1602             expr = else_expr;
1603         } else {
1604             break;
1605         }
1606     }
1607
1608     // final `else {..}`
1609     if !blocks.is_empty() {
1610         if let ExprKind::Block(block, _) = expr.kind {
1611             blocks.push(block);
1612         }
1613     }
1614
1615     (conds, blocks)
1616 }
1617
1618 /// Checks if the given function kind is an async function.
1619 pub fn is_async_fn(kind: FnKind<'_>) -> bool {
1620     matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
1621 }
1622
1623 /// Peels away all the compiler generated code surrounding the body of an async function,
1624 pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
1625     if let ExprKind::Call(
1626         _,
1627         &[Expr {
1628             kind: ExprKind::Closure(_, _, body, _, _),
1629             ..
1630         }],
1631     ) = body.value.kind
1632     {
1633         if let ExprKind::Block(
1634             Block {
1635                 stmts: [],
1636                 expr:
1637                     Some(Expr {
1638                         kind: ExprKind::DropTemps(expr),
1639                         ..
1640                     }),
1641                 ..
1642             },
1643             _,
1644         ) = tcx.hir().body(body).value.kind
1645         {
1646             return Some(expr);
1647         }
1648     };
1649     None
1650 }
1651
1652 // Finds the `#[must_use]` attribute, if any
1653 pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
1654     attrs.iter().find(|a| a.has_name(sym::must_use))
1655 }
1656
1657 // check if expr is calling method or function with #[must_use] attribute
1658 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1659     let did = match expr.kind {
1660         ExprKind::Call(path, _) => if_chain! {
1661             if let ExprKind::Path(ref qpath) = path.kind;
1662             if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
1663             then {
1664                 Some(did)
1665             } else {
1666                 None
1667             }
1668         },
1669         ExprKind::MethodCall(_, _, _, _) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1670         _ => None,
1671     };
1672
1673     did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some())
1674 }
1675
1676 /// Checks if an expression represents the identity function
1677 /// Only examines closures and `std::convert::identity`
1678 pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1679     /// Checks if a function's body represents the identity function. Looks for bodies of the form:
1680     /// * `|x| x`
1681     /// * `|x| return x`
1682     /// * `|x| { return x }`
1683     /// * `|x| { return x; }`
1684     fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
1685         let id = if_chain! {
1686             if let [param] = func.params;
1687             if let PatKind::Binding(_, id, _, _) = param.pat.kind;
1688             then {
1689                 id
1690             } else {
1691                 return false;
1692             }
1693         };
1694
1695         let mut expr = &func.value;
1696         loop {
1697             match expr.kind {
1698                 #[rustfmt::skip]
1699                 ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, )
1700                 | ExprKind::Ret(Some(e)) => expr = e,
1701                 #[rustfmt::skip]
1702                 ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => {
1703                     if_chain! {
1704                         if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
1705                         if let ExprKind::Ret(Some(ret_val)) = e.kind;
1706                         then {
1707                             expr = ret_val;
1708                         } else {
1709                             return false;
1710                         }
1711                     }
1712                 },
1713                 _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
1714             }
1715         }
1716     }
1717
1718     match expr.kind {
1719         ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
1720         ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY),
1721         _ => false,
1722     }
1723 }
1724
1725 /// Gets the node where an expression is either used, or it's type is unified with another branch.
1726 pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
1727     let map = tcx.hir();
1728     let mut child_id = expr.hir_id;
1729     let mut iter = map.parent_iter(child_id);
1730     loop {
1731         match iter.next() {
1732             None => break None,
1733             Some((id, Node::Block(_))) => child_id = id,
1734             Some((id, Node::Arm(arm))) if arm.body.hir_id == child_id => child_id = id,
1735             Some((_, Node::Expr(expr))) => match expr.kind {
1736                 ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id,
1737                 ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id,
1738                 ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None,
1739                 _ => break Some(Node::Expr(expr)),
1740             },
1741             Some((_, node)) => break Some(node),
1742         }
1743     }
1744 }
1745
1746 /// Checks if the result of an expression is used, or it's type is unified with another branch.
1747 pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1748     !matches!(
1749         get_expr_use_or_unification_node(tcx, expr),
1750         None | Some(Node::Stmt(Stmt {
1751             kind: StmtKind::Expr(_)
1752                 | StmtKind::Semi(_)
1753                 | StmtKind::Local(Local {
1754                     pat: Pat {
1755                         kind: PatKind::Wild,
1756                         ..
1757                     },
1758                     ..
1759                 }),
1760             ..
1761         }))
1762     )
1763 }
1764
1765 /// Checks if the expression is the final expression returned from a block.
1766 pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1767     matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..)))
1768 }
1769
1770 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
1771     cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
1772         if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
1773             attr.path == sym::no_std
1774         } else {
1775             false
1776         }
1777     })
1778 }
1779
1780 /// Check if parent of a hir node is a trait implementation block.
1781 /// For example, `f` in
1782 /// ```rust,ignore
1783 /// impl Trait for S {
1784 ///     fn f() {}
1785 /// }
1786 /// ```
1787 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
1788     if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
1789         matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
1790     } else {
1791         false
1792     }
1793 }
1794
1795 /// Check if it's even possible to satisfy the `where` clause for the item.
1796 ///
1797 /// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example:
1798 ///
1799 /// ```ignore
1800 /// fn foo() where i32: Iterator {
1801 ///     for _ in 2i32 {}
1802 /// }
1803 /// ```
1804 pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
1805     use rustc_trait_selection::traits;
1806     let predicates = cx
1807         .tcx
1808         .predicates_of(did)
1809         .predicates
1810         .iter()
1811         .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
1812     traits::impossible_predicates(
1813         cx.tcx,
1814         traits::elaborate_predicates(cx.tcx, predicates)
1815             .map(|o| o.predicate)
1816             .collect::<Vec<_>>(),
1817     )
1818 }
1819
1820 /// Returns the `DefId` of the callee if the given expression is a function or method call.
1821 pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
1822     match &expr.kind {
1823         ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1824         ExprKind::Call(
1825             Expr {
1826                 kind: ExprKind::Path(qpath),
1827                 hir_id: path_hir_id,
1828                 ..
1829             },
1830             ..,
1831         ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
1832         _ => None,
1833     }
1834 }
1835
1836 /// Returns Option<String> where String is a textual representation of the type encapsulated in the
1837 /// slice iff the given expression is a slice of primitives (as defined in the
1838 /// `is_recursively_primitive_type` function) and None otherwise.
1839 pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
1840     let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
1841     let expr_kind = expr_type.kind();
1842     let is_primitive = match expr_kind {
1843         rustc_ty::Slice(element_type) => is_recursively_primitive_type(element_type),
1844         rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => {
1845             if let rustc_ty::Slice(element_type) = inner_ty.kind() {
1846                 is_recursively_primitive_type(element_type)
1847             } else {
1848                 unreachable!()
1849             }
1850         },
1851         _ => false,
1852     };
1853
1854     if is_primitive {
1855         // if we have wrappers like Array, Slice or Tuple, print these
1856         // and get the type enclosed in the slice ref
1857         match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
1858             rustc_ty::Slice(..) => return Some("slice".into()),
1859             rustc_ty::Array(..) => return Some("array".into()),
1860             rustc_ty::Tuple(..) => return Some("tuple".into()),
1861             _ => {
1862                 // is_recursively_primitive_type() should have taken care
1863                 // of the rest and we can rely on the type that is found
1864                 let refs_peeled = expr_type.peel_refs();
1865                 return Some(refs_peeled.walk().last().unwrap().to_string());
1866             },
1867         }
1868     }
1869     None
1870 }
1871
1872 /// returns list of all pairs (a, b) from `exprs` such that `eq(a, b)`
1873 /// `hash` must be comformed with `eq`
1874 pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
1875 where
1876     Hash: Fn(&T) -> u64,
1877     Eq: Fn(&T, &T) -> bool,
1878 {
1879     match exprs {
1880         [a, b] if eq(a, b) => return vec![(a, b)],
1881         _ if exprs.len() <= 2 => return vec![],
1882         _ => {},
1883     }
1884
1885     let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
1886
1887     let mut map: UnhashMap<u64, Vec<&_>> =
1888         UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
1889
1890     for expr in exprs {
1891         match map.entry(hash(expr)) {
1892             Entry::Occupied(mut o) => {
1893                 for o in o.get() {
1894                     if eq(o, expr) {
1895                         match_expr_list.push((o, expr));
1896                     }
1897                 }
1898                 o.get_mut().push(expr);
1899             },
1900             Entry::Vacant(v) => {
1901                 v.insert(vec![expr]);
1902             },
1903         }
1904     }
1905
1906     match_expr_list
1907 }
1908
1909 /// Peels off all references on the pattern. Returns the underlying pattern and the number of
1910 /// references removed.
1911 pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
1912     fn peel(pat: &'a Pat<'a>, count: usize) -> (&'a Pat<'a>, usize) {
1913         if let PatKind::Ref(pat, _) = pat.kind {
1914             peel(pat, count + 1)
1915         } else {
1916             (pat, count)
1917         }
1918     }
1919     peel(pat, 0)
1920 }
1921
1922 /// Peels of expressions while the given closure returns `Some`.
1923 pub fn peel_hir_expr_while<'tcx>(
1924     mut expr: &'tcx Expr<'tcx>,
1925     mut f: impl FnMut(&'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>>,
1926 ) -> &'tcx Expr<'tcx> {
1927     while let Some(e) = f(expr) {
1928         expr = e;
1929     }
1930     expr
1931 }
1932
1933 /// Peels off up to the given number of references on the expression. Returns the underlying
1934 /// expression and the number of references removed.
1935 pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
1936     let mut remaining = count;
1937     let e = peel_hir_expr_while(expr, |e| match e.kind {
1938         ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) if remaining != 0 => {
1939             remaining -= 1;
1940             Some(e)
1941         },
1942         _ => None,
1943     });
1944     (e, count - remaining)
1945 }
1946
1947 /// Peels off all references on the expression. Returns the underlying expression and the number of
1948 /// references removed.
1949 pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
1950     let mut count = 0;
1951     let e = peel_hir_expr_while(expr, |e| match e.kind {
1952         ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) => {
1953             count += 1;
1954             Some(e)
1955         },
1956         _ => None,
1957     });
1958     (e, count)
1959 }
1960
1961 /// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
1962 /// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
1963 pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
1964     loop {
1965         match expr.kind {
1966             ExprKind::AddrOf(_, _, e) => expr = e,
1967             ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
1968             _ => break,
1969         }
1970     }
1971     expr
1972 }
1973
1974 #[macro_export]
1975 macro_rules! unwrap_cargo_metadata {
1976     ($cx: ident, $lint: ident, $deps: expr) => {{
1977         let mut command = cargo_metadata::MetadataCommand::new();
1978         if !$deps {
1979             command.no_deps();
1980         }
1981
1982         match command.exec() {
1983             Ok(metadata) => metadata,
1984             Err(err) => {
1985                 span_lint($cx, $lint, DUMMY_SP, &format!("could not read cargo metadata: {}", err));
1986                 return;
1987             },
1988         }
1989     }};
1990 }
1991
1992 pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
1993     if_chain! {
1994         if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
1995         if let Res::Def(_, def_id) = path.res;
1996         then {
1997             cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr)
1998         } else {
1999             false
2000         }
2001     }
2002 }
2003
2004 /// Checks whether item either has `test` attribute applied, or
2005 /// is a module with `test` in its name.
2006 pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
2007     if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) {
2008         if tcx.has_attr(def_id.to_def_id(), sym::test) {
2009             return true;
2010         }
2011     }
2012
2013     matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
2014 }
2015
2016 macro_rules! op_utils {
2017     ($($name:ident $assign:ident)*) => {
2018         /// Binary operation traits like `LangItem::Add`
2019         pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
2020
2021         /// Operator-Assign traits like `LangItem::AddAssign`
2022         pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
2023
2024         /// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
2025         pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
2026             match kind {
2027                 $(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
2028                 _ => None,
2029             }
2030         }
2031     };
2032 }
2033
2034 op_utils! {
2035     Add    AddAssign
2036     Sub    SubAssign
2037     Mul    MulAssign
2038     Div    DivAssign
2039     Rem    RemAssign
2040     BitXor BitXorAssign
2041     BitAnd BitAndAssign
2042     BitOr  BitOrAssign
2043     Shl    ShlAssign
2044     Shr    ShrAssign
2045 }