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