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