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