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