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