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