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