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