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