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