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