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