clippy_utils/
lib.rs

1#![feature(array_chunks)]
2#![feature(box_patterns)]
3#![feature(f128)]
4#![feature(f16)]
5#![feature(if_let_guard)]
6#![feature(macro_metavar_expr_concat)]
7#![feature(let_chains)]
8#![feature(never_type)]
9#![feature(rustc_private)]
10#![feature(assert_matches)]
11#![feature(unwrap_infallible)]
12#![feature(array_windows)]
13#![recursion_limit = "512"]
14#![allow(
15    clippy::missing_errors_doc,
16    clippy::missing_panics_doc,
17    clippy::must_use_candidate,
18    rustc::diagnostic_outside_of_impl,
19    rustc::untranslatable_diagnostic
20)]
21#![warn(
22    trivial_casts,
23    trivial_numeric_casts,
24    rust_2018_idioms,
25    unused_lifetimes,
26    unused_qualifications,
27    rustc::internal
28)]
29
30// FIXME: switch to something more ergonomic here, once available.
31// (Currently there is no way to opt into sysroot crates without `extern crate`.)
32extern crate rustc_abi;
33extern crate rustc_ast;
34extern crate rustc_ast_pretty;
35extern crate rustc_attr_parsing;
36extern crate rustc_const_eval;
37extern crate rustc_data_structures;
38// The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate.
39#[allow(unused_extern_crates)]
40extern crate rustc_driver;
41extern crate rustc_errors;
42extern crate rustc_hir;
43extern crate rustc_hir_typeck;
44extern crate rustc_index;
45extern crate rustc_infer;
46extern crate rustc_lexer;
47extern crate rustc_lint;
48extern crate rustc_middle;
49extern crate rustc_mir_dataflow;
50extern crate rustc_session;
51extern crate rustc_span;
52extern crate rustc_trait_selection;
53extern crate smallvec;
54
55#[macro_use]
56pub mod sym_helper;
57
58pub mod ast_utils;
59pub mod attrs;
60mod check_proc_macro;
61pub mod comparisons;
62pub mod consts;
63pub mod diagnostics;
64pub mod eager_or_lazy;
65pub mod higher;
66mod hir_utils;
67pub mod macros;
68pub mod mir;
69pub mod msrvs;
70pub mod numeric_literal;
71pub mod paths;
72pub mod ptr;
73pub mod qualify_min_const_fn;
74pub mod source;
75pub mod str_utils;
76pub mod sugg;
77pub mod ty;
78pub mod usage;
79pub mod visitors;
80
81pub use self::attrs::*;
82pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match};
83pub use self::hir_utils::{
84    HirEqInterExpr, SpanlessEq, SpanlessHash, both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over,
85};
86
87use core::mem;
88use core::ops::ControlFlow;
89use std::collections::hash_map::Entry;
90use std::hash::BuildHasherDefault;
91use std::iter::{once, repeat_n};
92use std::sync::{Mutex, MutexGuard, OnceLock};
93
94use itertools::Itertools;
95use rustc_ast::ast::{self, LitKind, RangeLimits};
96use rustc_data_structures::fx::FxHashMap;
97use rustc_data_structures::packed::Pu128;
98use rustc_data_structures::unhash::UnhashMap;
99use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
100use rustc_hir::def::{DefKind, Res};
101use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
102use rustc_hir::definitions::{DefPath, DefPathData};
103use rustc_hir::hir_id::{HirIdMap, HirIdSet};
104use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
105use rustc_hir::{
106    self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
107    Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
108    ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
109    PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind,
110    TraitItemRef, TraitRef, TyKind, UnOp, def,
111};
112use rustc_lexer::{TokenKind, tokenize};
113use rustc_lint::{LateContext, Level, Lint, LintContext};
114use rustc_middle::hir::place::PlaceBase;
115use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
116use rustc_middle::ty::fast_reject::SimplifiedType;
117use rustc_middle::ty::layout::IntegerExt;
118use rustc_middle::ty::{
119    self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgKind, GenericArgsRef, IntTy, Ty,
120    TyCtxt, TypeVisitableExt, UintTy, UpvarCapture,
121};
122use rustc_span::hygiene::{ExpnKind, MacroKind};
123use rustc_span::source_map::SourceMap;
124use rustc_span::symbol::{Ident, Symbol, kw};
125use rustc_span::{InnerSpan, Span, sym};
126use rustc_abi::Integer;
127use visitors::{Visitable, for_each_unconsumed_temporary};
128
129use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
130use crate::higher::Range;
131use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
132use crate::visitors::for_each_expr_without_closures;
133use rustc_middle::hir::nested_filter;
134
135#[macro_export]
136macro_rules! extract_msrv_attr {
137    (LateContext) => {
138        fn check_attributes(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) {
139            let sess = rustc_lint::LintContext::sess(cx);
140            self.msrv.check_attributes(sess, attrs);
141        }
142
143        fn check_attributes_post(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) {
144            let sess = rustc_lint::LintContext::sess(cx);
145            self.msrv.check_attributes_post(sess, attrs);
146        }
147    };
148    (EarlyContext) => {
149        fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) {
150            let sess = rustc_lint::LintContext::sess(cx);
151            self.msrv.check_attributes(sess, attrs);
152        }
153
154        fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) {
155            let sess = rustc_lint::LintContext::sess(cx);
156            self.msrv.check_attributes_post(sess, attrs);
157        }
158    };
159}
160
161/// If the given expression is a local binding, find the initializer expression.
162/// If that initializer expression is another local binding, find its initializer again.
163///
164/// This process repeats as long as possible (but usually no more than once). Initializer
165/// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
166/// instead.
167///
168/// Examples:
169/// ```no_run
170/// let abc = 1;
171/// //        ^ output
172/// let def = abc;
173/// dbg!(def);
174/// //   ^^^ input
175///
176/// // or...
177/// let abc = 1;
178/// let def = abc + 2;
179/// //        ^^^^^^^ output
180/// dbg!(def);
181/// //   ^^^ input
182/// ```
183pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
184    while let Some(init) = path_to_local(expr)
185        .and_then(|id| find_binding_init(cx, id))
186        .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
187    {
188        expr = init;
189    }
190    expr
191}
192
193/// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
194///
195/// By only considering immutable bindings, we guarantee that the returned expression represents the
196/// value of the binding wherever it is referenced.
197///
198/// Example: For `let x = 1`, if the `HirId` of `x` is provided, the `Expr` `1` is returned.
199/// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the
200/// canonical binding `HirId`.
201pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
202    if let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
203        && matches!(pat.kind, PatKind::Binding(BindingMode::NONE, ..))
204        && let Node::LetStmt(local) = cx.tcx.parent_hir_node(hir_id)
205    {
206        return local.init;
207    }
208    None
209}
210
211/// Checks if the given local has an initializer or is from something other than a `let` statement
212///
213/// e.g. returns true for `x` in `fn f(x: usize) { .. }` and `let x = 1;` but false for `let x;`
214pub fn local_is_initialized(cx: &LateContext<'_>, local: HirId) -> bool {
215    for (_, node) in cx.tcx.hir().parent_iter(local) {
216        match node {
217            Node::Pat(..) | Node::PatField(..) => {},
218            Node::LetStmt(let_stmt) => return let_stmt.init.is_some(),
219            _ => return true,
220        }
221    }
222
223    false
224}
225
226/// Checks if we are currently in a const context (e.g. `const fn`, `static`/`const` initializer).
227///
228/// The current context is determined based on the current body which is set before calling a lint's
229/// entry point (any function on `LateLintPass`). If you need to check in a different context use
230/// `tcx.hir().is_inside_const_context(_)`.
231///
232/// Do not call this unless the `LateContext` has an enclosing body. For release build this case
233/// will safely return `false`, but debug builds will ICE. Note that `check_expr`, `check_block`,
234/// `check_pat` and a few other entry points will always have an enclosing body. Some entry points
235/// like `check_path` or `check_ty` may or may not have one.
236pub fn is_in_const_context(cx: &LateContext<'_>) -> bool {
237    debug_assert!(cx.enclosing_body.is_some(), "`LateContext` has no enclosing body");
238    cx.enclosing_body.is_some_and(|id| {
239        cx.tcx
240            .hir()
241            .body_const_context(cx.tcx.hir().body_owner_def_id(id))
242            .is_some()
243    })
244}
245
246/// Returns `true` if the given `HirId` is inside an always constant context.
247///
248/// This context includes:
249///  * const/static items
250///  * const blocks (or inline consts)
251///  * associated constants
252pub fn is_inside_always_const_context(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
253    use ConstContext::{Const, ConstFn, Static};
254    let hir = tcx.hir();
255    let Some(ctx) = hir.body_const_context(hir.enclosing_body_owner(hir_id)) else {
256        return false;
257    };
258    match ctx {
259        ConstFn => false,
260        Static(_) | Const { inline: _ } => true,
261    }
262}
263
264/// Checks if a `Res` refers to a constructor of a `LangItem`
265/// For example, use this to check whether a function call or a pattern is `Some(..)`.
266pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
267    if let Res::Def(DefKind::Ctor(..), id) = res
268        && let Some(lang_id) = cx.tcx.lang_items().get(lang_item)
269        && let Some(id) = cx.tcx.opt_parent(id)
270    {
271        id == lang_id
272    } else {
273        false
274    }
275}
276
277/// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`.
278pub fn is_enum_variant_ctor(
279    cx: &LateContext<'_>,
280    enum_item: Symbol,
281    variant_name: Symbol,
282    ctor_call_id: DefId,
283) -> bool {
284    let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else {
285        return false;
286    };
287
288    let variants = cx.tcx.adt_def(enum_def_id).variants().iter();
289    variants
290        .filter(|variant| variant.name == variant_name)
291        .filter_map(|variant| variant.ctor.as_ref())
292        .any(|(_, ctor_def_id)| *ctor_def_id == ctor_call_id)
293}
294
295/// Checks if the `DefId` matches the given diagnostic item or it's constructor.
296pub fn is_diagnostic_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: Symbol) -> bool {
297    let did = match cx.tcx.def_kind(did) {
298        DefKind::Ctor(..) => cx.tcx.parent(did),
299        // Constructors for types in external crates seem to have `DefKind::Variant`
300        DefKind::Variant => match cx.tcx.opt_parent(did) {
301            Some(did) if matches!(cx.tcx.def_kind(did), DefKind::Variant) => did,
302            _ => did,
303        },
304        _ => did,
305    };
306
307    cx.tcx.is_diagnostic_item(item, did)
308}
309
310/// Checks if the `DefId` matches the given `LangItem` or it's constructor.
311pub fn is_lang_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: LangItem) -> bool {
312    let did = match cx.tcx.def_kind(did) {
313        DefKind::Ctor(..) => cx.tcx.parent(did),
314        // Constructors for types in external crates seem to have `DefKind::Variant`
315        DefKind::Variant => match cx.tcx.opt_parent(did) {
316            Some(did) if matches!(cx.tcx.def_kind(did), DefKind::Variant) => did,
317            _ => did,
318        },
319        _ => did,
320    };
321
322    cx.tcx.lang_items().get(item) == Some(did)
323}
324
325pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
326    matches!(
327        expr.kind,
328        ExprKind::Block(
329            Block {
330                stmts: [],
331                expr: None,
332                ..
333            },
334            _
335        ) | ExprKind::Tup([])
336    )
337}
338
339/// Checks if given pattern is a wildcard (`_`)
340pub fn is_wild(pat: &Pat<'_>) -> bool {
341    matches!(pat.kind, PatKind::Wild)
342}
343
344// Checks if arm has the form `None => None`
345pub fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
346    matches!(
347        arm.pat.kind,
348        PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), .. })
349            if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone)
350    )
351}
352
353/// Checks if the given `QPath` belongs to a type alias.
354pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
355    match *qpath {
356        QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)),
357        QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => is_ty_alias(&qpath),
358        _ => false,
359    }
360}
361
362/// Checks if the method call given in `expr` belongs to the given trait.
363/// This is a deprecated function, consider using [`is_trait_method`].
364pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
365    let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
366    let trt_id = cx.tcx.trait_of_item(def_id);
367    trt_id.is_some_and(|trt_id| match_def_path(cx, trt_id, path))
368}
369
370/// Checks if the given method call expression calls an inherent method.
371pub fn is_inherent_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
372    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
373        cx.tcx.trait_of_item(method_id).is_none()
374    } else {
375        false
376    }
377}
378
379/// Checks if a method is defined in an impl of a diagnostic item
380pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
381    if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
382        if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() {
383            return cx.tcx.is_diagnostic_item(diag_item, adt.did());
384        }
385    }
386    false
387}
388
389/// Checks if a method is in a diagnostic item trait
390pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
391    if let Some(trait_did) = cx.tcx.trait_of_item(def_id) {
392        return cx.tcx.is_diagnostic_item(diag_item, trait_did);
393    }
394    false
395}
396
397/// Checks if the method call given in `expr` belongs to the given trait.
398pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
399    cx.typeck_results()
400        .type_dependent_def_id(expr.hir_id)
401        .is_some_and(|did| is_diag_trait_item(cx, did, diag_item))
402}
403
404/// Checks if the `def_id` belongs to a function that is part of a trait impl.
405pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
406    if let Node::Item(item) = cx.tcx.parent_hir_node(cx.tcx.local_def_id_to_hir_id(def_id))
407        && let ItemKind::Impl(imp) = item.kind
408    {
409        imp.of_trait.is_some()
410    } else {
411        false
412    }
413}
414
415/// Checks if the given expression is a path referring an item on the trait
416/// that is marked with the given diagnostic item.
417///
418/// For checking method call expressions instead of path expressions, use
419/// [`is_trait_method`].
420///
421/// For example, this can be used to find if an expression like `u64::default`
422/// refers to an item of the trait `Default`, which is associated with the
423/// `diag_item` of `sym::Default`.
424pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
425    if let ExprKind::Path(ref qpath) = expr.kind {
426        cx.qpath_res(qpath, expr.hir_id)
427            .opt_def_id()
428            .is_some_and(|def_id| is_diag_trait_item(cx, def_id, diag_item))
429    } else {
430        false
431    }
432}
433
434pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
435    match *path {
436        QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
437        QPath::TypeRelative(_, seg) => seg,
438        QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
439    }
440}
441
442pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
443    last_path_segment(qpath)
444        .args
445        .map_or(&[][..], |a| a.args)
446        .iter()
447        .filter_map(|a| match a {
448            hir::GenericArg::Type(ty) => Some(ty.as_unambig_ty()),
449            _ => None,
450        })
451}
452
453/// THIS METHOD IS DEPRECATED. Matches a `QPath` against a slice of segment string literals.
454///
455/// This method is deprecated and will eventually be removed since it does not match against the
456/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
457/// `QPath::Resolved.1.res.opt_def_id()`.
458///
459/// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a
460/// `rustc_hir::QPath`.
461///
462/// # Examples
463/// ```rust,ignore
464/// match_qpath(path, &["std", "rt", "begin_unwind"])
465/// ```
466pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
467    match *path {
468        QPath::Resolved(_, path) => match_path(path, segments),
469        QPath::TypeRelative(ty, segment) => match ty.kind {
470            TyKind::Path(ref inner_path) => {
471                if let [prefix @ .., end] = segments {
472                    if match_qpath(inner_path, prefix) {
473                        return segment.ident.name.as_str() == *end;
474                    }
475                }
476                false
477            },
478            _ => false,
479        },
480        QPath::LangItem(..) => false,
481    }
482}
483
484/// If the expression is a path, resolves it to a `DefId` and checks if it matches the given path.
485///
486/// Please use `is_path_diagnostic_item` if the target is a diagnostic item.
487pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool {
488    path_def_id(cx, expr).is_some_and(|id| match_def_path(cx, id, segments))
489}
490
491/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
492/// it matches the given lang item.
493pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool {
494    path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.lang_items().get(lang_item) == Some(id))
495}
496
497/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
498/// it matches the given diagnostic item.
499pub fn is_path_diagnostic_item<'tcx>(
500    cx: &LateContext<'_>,
501    maybe_path: &impl MaybePath<'tcx>,
502    diag_item: Symbol,
503) -> bool {
504    path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.is_diagnostic_item(diag_item, id))
505}
506
507/// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals.
508///
509/// This method is deprecated and will eventually be removed since it does not match against the
510/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
511/// `QPath::Resolved.1.res.opt_def_id()`.
512///
513/// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a
514/// `rustc_hir::Path`.
515///
516/// # Examples
517///
518/// ```rust,ignore
519/// if match_path(&trait_ref.path, &paths::HASH) {
520///     // This is the `std::hash::Hash` trait.
521/// }
522///
523/// if match_path(ty_path, &["rustc", "lint", "Lint"]) {
524///     // This is a `rustc_middle::lint::Lint`.
525/// }
526/// ```
527pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
528    path.segments
529        .iter()
530        .rev()
531        .zip(segments.iter().rev())
532        .all(|(a, b)| a.ident.name.as_str() == *b)
533}
534
535/// If the expression is a path to a local, returns the canonical `HirId` of the local.
536pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
537    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
538        if let Res::Local(id) = path.res {
539            return Some(id);
540        }
541    }
542    None
543}
544
545/// Returns true if the expression is a path to a local with the specified `HirId`.
546/// Use this function to see if an expression matches a function argument or a match binding.
547pub fn path_to_local_id(expr: &Expr<'_>, id: HirId) -> bool {
548    path_to_local(expr) == Some(id)
549}
550
551pub trait MaybePath<'hir> {
552    fn hir_id(&self) -> HirId;
553    fn qpath_opt(&self) -> Option<&QPath<'hir>>;
554}
555
556macro_rules! maybe_path {
557    ($ty:ident, $kind:ident) => {
558        impl<'hir> MaybePath<'hir> for hir::$ty<'hir> {
559            fn hir_id(&self) -> HirId {
560                self.hir_id
561            }
562            fn qpath_opt(&self) -> Option<&QPath<'hir>> {
563                match &self.kind {
564                    hir::$kind::Path(qpath) => Some(qpath),
565                    _ => None,
566                }
567            }
568        }
569    };
570}
571maybe_path!(Expr, ExprKind);
572impl<'hir> MaybePath<'hir> for Pat<'hir> {
573    fn hir_id(&self) -> HirId {
574        self.hir_id
575    }
576    fn qpath_opt(&self) -> Option<&QPath<'hir>> {
577        match &self.kind {
578            PatKind::Expr(PatExpr {
579                kind: PatExprKind::Path(qpath),
580                ..
581            }) => Some(qpath),
582            _ => None,
583        }
584    }
585}
586maybe_path!(Ty, TyKind);
587
588/// If `maybe_path` is a path node, resolves it, otherwise returns `Res::Err`
589pub fn path_res<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>) -> Res {
590    match maybe_path.qpath_opt() {
591        None => Res::Err,
592        Some(qpath) => cx.qpath_res(qpath, maybe_path.hir_id()),
593    }
594}
595
596/// If `maybe_path` is a path node which resolves to an item, retrieves the item ID
597pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>) -> Option<DefId> {
598    path_res(cx, maybe_path).opt_def_id()
599}
600
601fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
602    let ty = match name {
603        "bool" => SimplifiedType::Bool,
604        "char" => SimplifiedType::Char,
605        "str" => SimplifiedType::Str,
606        "array" => SimplifiedType::Array,
607        "slice" => SimplifiedType::Slice,
608        // FIXME: rustdoc documents these two using just `pointer`.
609        //
610        // Maybe this is something we should do here too.
611        "const_ptr" => SimplifiedType::Ptr(Mutability::Not),
612        "mut_ptr" => SimplifiedType::Ptr(Mutability::Mut),
613        "isize" => SimplifiedType::Int(IntTy::Isize),
614        "i8" => SimplifiedType::Int(IntTy::I8),
615        "i16" => SimplifiedType::Int(IntTy::I16),
616        "i32" => SimplifiedType::Int(IntTy::I32),
617        "i64" => SimplifiedType::Int(IntTy::I64),
618        "i128" => SimplifiedType::Int(IntTy::I128),
619        "usize" => SimplifiedType::Uint(UintTy::Usize),
620        "u8" => SimplifiedType::Uint(UintTy::U8),
621        "u16" => SimplifiedType::Uint(UintTy::U16),
622        "u32" => SimplifiedType::Uint(UintTy::U32),
623        "u64" => SimplifiedType::Uint(UintTy::U64),
624        "u128" => SimplifiedType::Uint(UintTy::U128),
625        "f32" => SimplifiedType::Float(FloatTy::F32),
626        "f64" => SimplifiedType::Float(FloatTy::F64),
627        _ => {
628            return [].iter().copied();
629        },
630    };
631
632    tcx.incoherent_impls(ty).iter().copied()
633}
634
635fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
636    match tcx.def_kind(def_id) {
637        DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
638            .module_children(def_id)
639            .iter()
640            .filter(|item| item.ident.name == name)
641            .map(|child| child.res.expect_non_local())
642            .collect(),
643        DefKind::Impl { .. } => tcx
644            .associated_item_def_ids(def_id)
645            .iter()
646            .copied()
647            .filter(|assoc_def_id| tcx.item_name(*assoc_def_id) == name)
648            .map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id))
649            .collect(),
650        _ => Vec::new(),
651    }
652}
653
654fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symbol) -> Vec<Res> {
655    let hir = tcx.hir();
656
657    let root_mod;
658    let item_kind = match tcx.hir_node_by_def_id(local_id) {
659        Node::Crate(r#mod) => {
660            root_mod = ItemKind::Mod(r#mod);
661            &root_mod
662        },
663        Node::Item(item) => &item.kind,
664        _ => return Vec::new(),
665    };
666
667    let res = |ident: Ident, owner_id: OwnerId| {
668        if ident.name == name {
669            let def_id = owner_id.to_def_id();
670            Some(Res::Def(tcx.def_kind(def_id), def_id))
671        } else {
672            None
673        }
674    };
675
676    match item_kind {
677        ItemKind::Mod(r#mod) => r#mod
678            .item_ids
679            .iter()
680            .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
681            .collect(),
682        ItemKind::Impl(r#impl) => r#impl
683            .items
684            .iter()
685            .filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.owner_id))
686            .collect(),
687        ItemKind::Trait(.., trait_item_refs) => trait_item_refs
688            .iter()
689            .filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.owner_id))
690            .collect(),
691        _ => Vec::new(),
692    }
693}
694
695fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
696    if let Some(local_id) = def_id.as_local() {
697        local_item_children_by_name(tcx, local_id, name)
698    } else {
699        non_local_item_children_by_name(tcx, def_id, name)
700    }
701}
702
703/// Finds the crates called `name`, may be multiple due to multiple major versions.
704pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> Vec<Res> {
705    tcx.crates(())
706        .iter()
707        .copied()
708        .filter(move |&num| tcx.crate_name(num) == name)
709        .map(CrateNum::as_def_id)
710        .map(|id| Res::Def(tcx.def_kind(id), id))
711        .collect()
712}
713
714/// Resolves a def path like `std::vec::Vec`.
715///
716/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
717/// `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0.
718///
719/// Also returns multiple results when there are multiple paths under the same name e.g. `std::vec`
720/// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
721///
722/// This function is expensive and should be used sparingly.
723pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
724    let (base, path) = match path {
725        [primitive] => {
726            return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
727        },
728        [base, path @ ..] => (base, path),
729        _ => return Vec::new(),
730    };
731
732    let base_sym = Symbol::intern(base);
733
734    let local_crate = if tcx.crate_name(LOCAL_CRATE) == base_sym {
735        Some(LOCAL_CRATE.as_def_id())
736    } else {
737        None
738    };
739
740    let crates = find_primitive_impls(tcx, base)
741        .chain(local_crate)
742        .map(|id| Res::Def(tcx.def_kind(id), id))
743        .chain(find_crates(tcx, base_sym))
744        .collect();
745
746    def_path_res_with_base(tcx, crates, path)
747}
748
749/// Resolves a def path like `vec::Vec` with the base `std`.
750///
751/// This is lighter than [`def_path_res`], and should be called with [`find_crates`] looking up
752/// items from the same crate repeatedly, although should still be used sparingly.
753pub fn def_path_res_with_base(tcx: TyCtxt<'_>, mut base: Vec<Res>, mut path: &[&str]) -> Vec<Res> {
754    while let [segment, rest @ ..] = path {
755        path = rest;
756        let segment = Symbol::intern(segment);
757
758        base = base
759            .into_iter()
760            .filter_map(|res| res.opt_def_id())
761            .flat_map(|def_id| {
762                // When the current def_id is e.g. `struct S`, check the impl items in
763                // `impl S { ... }`
764                let inherent_impl_children = tcx
765                    .inherent_impls(def_id)
766                    .iter()
767                    .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
768
769                let direct_children = item_children_by_name(tcx, def_id, segment);
770
771                inherent_impl_children.chain(direct_children)
772            })
773            .collect();
774    }
775
776    base
777}
778
779/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
780pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator<Item = DefId> + use<> {
781    def_path_res(tcx, path).into_iter().filter_map(|res| res.opt_def_id())
782}
783
784/// Convenience function to get the `DefId` of a trait by path.
785/// It could be a trait or trait alias.
786///
787/// This function is expensive and should be used sparingly.
788pub fn get_trait_def_id(tcx: TyCtxt<'_>, path: &[&str]) -> Option<DefId> {
789    def_path_res(tcx, path).into_iter().find_map(|res| match res {
790        Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
791        _ => None,
792    })
793}
794
795/// Gets the `hir::TraitRef` of the trait the given method is implemented for.
796///
797/// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
798///
799/// ```no_run
800/// struct Point(isize, isize);
801///
802/// impl std::ops::Add for Point {
803///     type Output = Self;
804///
805///     fn add(self, other: Self) -> Self {
806///         Point(0, 0)
807///     }
808/// }
809/// ```
810pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> Option<&'tcx TraitRef<'tcx>> {
811    // Get the implemented trait for the current function
812    let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
813    let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
814    if parent_impl != hir::CRATE_OWNER_ID
815        && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_impl.def_id)
816        && let ItemKind::Impl(impl_) = &item.kind
817    {
818        return impl_.of_trait.as_ref();
819    }
820    None
821}
822
823/// This method will return tuple of projection stack and root of the expression,
824/// used in `can_mut_borrow_both`.
825///
826/// For example, if `e` represents the `v[0].a.b[x]`
827/// this method will return a tuple, composed of a `Vec`
828/// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
829/// and an `Expr` for root of them, `v`
830fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
831    let mut result = vec![];
832    let root = loop {
833        match e.kind {
834            ExprKind::Index(ep, _, _) | ExprKind::Field(ep, _) => {
835                result.push(e);
836                e = ep;
837            },
838            _ => break e,
839        }
840    };
841    result.reverse();
842    (result, root)
843}
844
845/// Gets the mutability of the custom deref adjustment, if any.
846pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<Mutability> {
847    cx.typeck_results()
848        .expr_adjustments(e)
849        .iter()
850        .find_map(|a| match a.kind {
851            Adjust::Deref(Some(d)) => Some(Some(d.mutbl)),
852            Adjust::Deref(None) => None,
853            _ => Some(None),
854        })
855        .and_then(|x| x)
856}
857
858/// Checks if two expressions can be mutably borrowed simultaneously
859/// and they aren't dependent on borrowing same thing twice
860pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool {
861    let (s1, r1) = projection_stack(e1);
862    let (s2, r2) = projection_stack(e2);
863    if !eq_expr_value(cx, r1, r2) {
864        return true;
865    }
866    if expr_custom_deref_adjustment(cx, r1).is_some() || expr_custom_deref_adjustment(cx, r2).is_some() {
867        return false;
868    }
869
870    for (x1, x2) in s1.iter().zip(s2.iter()) {
871        if expr_custom_deref_adjustment(cx, x1).is_some() || expr_custom_deref_adjustment(cx, x2).is_some() {
872            return false;
873        }
874
875        match (&x1.kind, &x2.kind) {
876            (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => {
877                if i1 != i2 {
878                    return true;
879                }
880            },
881            (ExprKind::Index(_, i1, _), ExprKind::Index(_, i2, _)) => {
882                if !eq_expr_value(cx, i1, i2) {
883                    return false;
884                }
885            },
886            _ => return false,
887        }
888    }
889    false
890}
891
892/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent"
893/// constructor from the std library
894fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
895    let std_types_symbols = &[
896        sym::Vec,
897        sym::VecDeque,
898        sym::LinkedList,
899        sym::HashMap,
900        sym::BTreeMap,
901        sym::HashSet,
902        sym::BTreeSet,
903        sym::BinaryHeap,
904    ];
905
906    if let QPath::TypeRelative(_, method) = path {
907        if method.ident.name == sym::new {
908            if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
909                if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() {
910                    return std_types_symbols.iter().any(|&symbol| {
911                        cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
912                    });
913                }
914            }
915        }
916    }
917    false
918}
919
920/// Returns true if the expr is equal to `Default::default` when evaluated.
921pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool {
922    if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind
923        && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id()
924        && (is_diag_trait_item(cx, repl_def_id, sym::Default)
925            || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath))
926    {
927        true
928    } else {
929        false
930    }
931}
932
933/// Returns true if the expr is equal to `Default::default()` of it's type when evaluated.
934///
935/// It doesn't cover all cases, for example indirect function calls (some of std
936/// functions are supported) but it is the best we have.
937pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
938    match &e.kind {
939        ExprKind::Lit(lit) => match lit.node {
940            LitKind::Bool(false) | LitKind::Int(Pu128(0), _) => true,
941            LitKind::Str(s, _) => s.is_empty(),
942            _ => false,
943        },
944        ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
945        ExprKind::Repeat(x, len) => {
946            if let ConstArgKind::Anon(anon_const) = len.kind
947                && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
948                && let LitKind::Int(v, _) = const_lit.node
949                && v <= 32
950                && is_default_equivalent(cx, x)
951            {
952                true
953            } else {
954                false
955            }
956        },
957        ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func),
958        ExprKind::Call(from_func, [arg]) => is_default_equivalent_from(cx, from_func, arg),
959        ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
960        ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
961        _ => false,
962    }
963}
964
965fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &Expr<'_>) -> bool {
966    if let ExprKind::Path(QPath::TypeRelative(ty, seg)) = from_func.kind
967        && seg.ident.name == sym::from
968    {
969        match arg.kind {
970            ExprKind::Lit(hir::Lit {
971                node: LitKind::Str(sym, _),
972                ..
973            }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
974            ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
975            ExprKind::Repeat(_, len) => {
976                if let ConstArgKind::Anon(anon_const) = len.kind
977                    && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
978                    && let LitKind::Int(v, _) = const_lit.node
979                {
980                    return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
981                }
982            },
983            _ => (),
984        }
985    }
986    false
987}
988
989/// Checks if the top level expression can be moved into a closure as is.
990/// Currently checks for:
991/// * Break/Continue outside the given loop HIR ids.
992/// * Yield/Return statements.
993/// * Inline assembly.
994/// * Usages of a field of a local where the type of the local can be partially moved.
995///
996/// For example, given the following function:
997///
998/// ```no_run
999/// fn f<'a>(iter: &mut impl Iterator<Item = (usize, &'a mut String)>) {
1000///     for item in iter {
1001///         let s = item.1;
1002///         if item.0 > 10 {
1003///             continue;
1004///         } else {
1005///             s.clear();
1006///         }
1007///     }
1008/// }
1009/// ```
1010///
1011/// When called on the expression `item.0` this will return false unless the local `item` is in the
1012/// `ignore_locals` set. The type `(usize, &mut String)` can have the second element moved, so it
1013/// isn't always safe to move into a closure when only a single field is needed.
1014///
1015/// When called on the `continue` expression this will return false unless the outer loop expression
1016/// is in the `loop_ids` set.
1017///
1018/// Note that this check is not recursive, so passing the `if` expression will always return true
1019/// even though sub-expressions might return false.
1020pub fn can_move_expr_to_closure_no_visit<'tcx>(
1021    cx: &LateContext<'tcx>,
1022    expr: &'tcx Expr<'_>,
1023    loop_ids: &[HirId],
1024    ignore_locals: &HirIdSet,
1025) -> bool {
1026    match expr.kind {
1027        ExprKind::Break(Destination { target_id: Ok(id), .. }, _)
1028        | ExprKind::Continue(Destination { target_id: Ok(id), .. })
1029            if loop_ids.contains(&id) =>
1030        {
1031            true
1032        },
1033        ExprKind::Break(..)
1034        | ExprKind::Continue(_)
1035        | ExprKind::Ret(_)
1036        | ExprKind::Yield(..)
1037        | ExprKind::InlineAsm(_) => false,
1038        // Accessing a field of a local value can only be done if the type isn't
1039        // partially moved.
1040        ExprKind::Field(
1041            &Expr {
1042                hir_id,
1043                kind:
1044                    ExprKind::Path(QPath::Resolved(
1045                        _,
1046                        Path {
1047                            res: Res::Local(local_id),
1048                            ..
1049                        },
1050                    )),
1051                ..
1052            },
1053            _,
1054        ) if !ignore_locals.contains(local_id) && can_partially_move_ty(cx, cx.typeck_results().node_type(hir_id)) => {
1055            // TODO: check if the local has been partially moved. Assume it has for now.
1056            false
1057        },
1058        _ => true,
1059    }
1060}
1061
1062/// How a local is captured by a closure
1063#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1064pub enum CaptureKind {
1065    Value,
1066    Ref(Mutability),
1067}
1068impl CaptureKind {
1069    pub fn is_imm_ref(self) -> bool {
1070        self == Self::Ref(Mutability::Not)
1071    }
1072}
1073impl std::ops::BitOr for CaptureKind {
1074    type Output = Self;
1075    fn bitor(self, rhs: Self) -> Self::Output {
1076        match (self, rhs) {
1077            (CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
1078            (CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
1079            | (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
1080            (CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
1081        }
1082    }
1083}
1084impl std::ops::BitOrAssign for CaptureKind {
1085    fn bitor_assign(&mut self, rhs: Self) {
1086        *self = *self | rhs;
1087    }
1088}
1089
1090/// Given an expression referencing a local, determines how it would be captured in a closure.
1091///
1092/// Note as this will walk up to parent expressions until the capture can be determined it should
1093/// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
1094/// function argument (other than a receiver).
1095pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
1096    fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
1097        let mut capture = CaptureKind::Ref(Mutability::Not);
1098        pat.each_binding_or_first(&mut |_, id, span, _| match cx
1099            .typeck_results()
1100            .extract_binding_mode(cx.sess(), id, span)
1101            .unwrap()
1102            .0
1103        {
1104            ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => {
1105                capture = CaptureKind::Value;
1106            },
1107            ByRef::Yes(Mutability::Mut) if capture != CaptureKind::Value => {
1108                capture = CaptureKind::Ref(Mutability::Mut);
1109            },
1110            _ => (),
1111        });
1112        capture
1113    }
1114
1115    debug_assert!(matches!(
1116        e.kind,
1117        ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
1118    ));
1119
1120    let mut child_id = e.hir_id;
1121    let mut capture = CaptureKind::Value;
1122    let mut capture_expr_ty = e;
1123
1124    for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
1125        if let [
1126            Adjustment {
1127                kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
1128                target,
1129            },
1130            ref adjust @ ..,
1131        ] = *cx
1132            .typeck_results()
1133            .adjustments()
1134            .get(child_id)
1135            .map_or(&[][..], |x| &**x)
1136        {
1137            if let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) =
1138                *adjust.last().map_or(target, |a| a.target).kind()
1139            {
1140                return CaptureKind::Ref(mutability);
1141            }
1142        }
1143
1144        match parent {
1145            Node::Expr(e) => match e.kind {
1146                ExprKind::AddrOf(_, mutability, _) => return CaptureKind::Ref(mutability),
1147                ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, _) => capture = CaptureKind::Ref(Mutability::Not),
1148                ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) if lhs.hir_id == child_id => {
1149                    return CaptureKind::Ref(Mutability::Mut);
1150                },
1151                ExprKind::Field(..) => {
1152                    if capture == CaptureKind::Value {
1153                        capture_expr_ty = e;
1154                    }
1155                },
1156                ExprKind::Let(let_expr) => {
1157                    let mutability = match pat_capture_kind(cx, let_expr.pat) {
1158                        CaptureKind::Value => Mutability::Not,
1159                        CaptureKind::Ref(m) => m,
1160                    };
1161                    return CaptureKind::Ref(mutability);
1162                },
1163                ExprKind::Match(_, arms, _) => {
1164                    let mut mutability = Mutability::Not;
1165                    for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
1166                        match capture {
1167                            CaptureKind::Value => break,
1168                            CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
1169                            CaptureKind::Ref(Mutability::Not) => (),
1170                        }
1171                    }
1172                    return CaptureKind::Ref(mutability);
1173                },
1174                _ => break,
1175            },
1176            Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) {
1177                CaptureKind::Value => break,
1178                capture @ CaptureKind::Ref(_) => return capture,
1179            },
1180            _ => break,
1181        }
1182
1183        child_id = parent_id;
1184    }
1185
1186    if capture == CaptureKind::Value && is_copy(cx, cx.typeck_results().expr_ty(capture_expr_ty)) {
1187        // Copy types are never automatically captured by value.
1188        CaptureKind::Ref(Mutability::Not)
1189    } else {
1190        capture
1191    }
1192}
1193
1194/// Checks if the expression can be moved into a closure as is. This will return a list of captures
1195/// if so, otherwise, `None`.
1196pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<HirIdMap<CaptureKind>> {
1197    struct V<'cx, 'tcx> {
1198        cx: &'cx LateContext<'tcx>,
1199        // Stack of potential break targets contained in the expression.
1200        loops: Vec<HirId>,
1201        /// Local variables created in the expression. These don't need to be captured.
1202        locals: HirIdSet,
1203        /// Whether this expression can be turned into a closure.
1204        allow_closure: bool,
1205        /// Locals which need to be captured, and whether they need to be by value, reference, or
1206        /// mutable reference.
1207        captures: HirIdMap<CaptureKind>,
1208    }
1209    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
1210        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
1211            if !self.allow_closure {
1212                return;
1213            }
1214
1215            match e.kind {
1216                ExprKind::Path(QPath::Resolved(None, &Path { res: Res::Local(l), .. })) => {
1217                    if !self.locals.contains(&l) {
1218                        let cap = capture_local_usage(self.cx, e);
1219                        self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
1220                    }
1221                },
1222                ExprKind::Closure(closure) => {
1223                    for capture in self.cx.typeck_results().closure_min_captures_flattened(closure.def_id) {
1224                        let local_id = match capture.place.base {
1225                            PlaceBase::Local(id) => id,
1226                            PlaceBase::Upvar(var) => var.var_path.hir_id,
1227                            _ => continue,
1228                        };
1229                        if !self.locals.contains(&local_id) {
1230                            let capture = match capture.info.capture_kind {
1231                                UpvarCapture::ByValue => CaptureKind::Value,
1232                                UpvarCapture::ByRef(kind) => match kind {
1233                                    BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
1234                                    BorrowKind::UniqueImmutable | BorrowKind::Mutable => {
1235                                        CaptureKind::Ref(Mutability::Mut)
1236                                    },
1237                                },
1238                            };
1239                            self.captures
1240                                .entry(local_id)
1241                                .and_modify(|e| *e |= capture)
1242                                .or_insert(capture);
1243                        }
1244                    }
1245                },
1246                ExprKind::Loop(b, ..) => {
1247                    self.loops.push(e.hir_id);
1248                    self.visit_block(b);
1249                    self.loops.pop();
1250                },
1251                _ => {
1252                    self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops, &self.locals);
1253                    walk_expr(self, e);
1254                },
1255            }
1256        }
1257
1258        fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
1259            p.each_binding_or_first(&mut |_, id, _, _| {
1260                self.locals.insert(id);
1261            });
1262        }
1263    }
1264
1265    let mut v = V {
1266        cx,
1267        loops: Vec::new(),
1268        locals: HirIdSet::default(),
1269        allow_closure: true,
1270        captures: HirIdMap::default(),
1271    };
1272    v.visit_expr(expr);
1273    v.allow_closure.then_some(v.captures)
1274}
1275
1276/// Arguments of a method: the receiver and all the additional arguments.
1277pub type MethodArguments<'tcx> = Vec<(&'tcx Expr<'tcx>, &'tcx [Expr<'tcx>])>;
1278
1279/// Returns the method names and argument list of nested method call expressions that make up
1280/// `expr`. method/span lists are sorted with the most recent call first.
1281pub fn method_calls<'tcx>(expr: &'tcx Expr<'tcx>, max_depth: usize) -> (Vec<Symbol>, MethodArguments<'tcx>, Vec<Span>) {
1282    let mut method_names = Vec::with_capacity(max_depth);
1283    let mut arg_lists = Vec::with_capacity(max_depth);
1284    let mut spans = Vec::with_capacity(max_depth);
1285
1286    let mut current = expr;
1287    for _ in 0..max_depth {
1288        if let ExprKind::MethodCall(path, receiver, args, _) = &current.kind {
1289            if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
1290                break;
1291            }
1292            method_names.push(path.ident.name);
1293            arg_lists.push((*receiver, &**args));
1294            spans.push(path.ident.span);
1295            current = receiver;
1296        } else {
1297            break;
1298        }
1299    }
1300
1301    (method_names, arg_lists, spans)
1302}
1303
1304/// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
1305///
1306/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
1307/// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
1308/// containing the `Expr`s for
1309/// `.bar()` and `.baz()`
1310pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<(&'a Expr<'a>, &'a [Expr<'a>])>> {
1311    let mut current = expr;
1312    let mut matched = Vec::with_capacity(methods.len());
1313    for method_name in methods.iter().rev() {
1314        // method chains are stored last -> first
1315        if let ExprKind::MethodCall(path, receiver, args, _) = current.kind {
1316            if path.ident.name.as_str() == *method_name {
1317                if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
1318                    return None;
1319                }
1320                matched.push((receiver, args)); // build up `matched` backwards
1321                current = receiver; // go to parent expression
1322            } else {
1323                return None;
1324            }
1325        } else {
1326            return None;
1327        }
1328    }
1329    // Reverse `matched` so that it is in the same order as `methods`.
1330    matched.reverse();
1331    Some(matched)
1332}
1333
1334/// Returns `true` if the provided `def_id` is an entrypoint to a program.
1335pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
1336    cx.tcx
1337        .entry_fn(())
1338        .is_some_and(|(entry_fn_def_id, _)| def_id == entry_fn_def_id)
1339}
1340
1341/// Returns `true` if the expression is in the program's `#[panic_handler]`.
1342pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
1343    let parent = cx.tcx.hir().get_parent_item(e.hir_id);
1344    Some(parent.to_def_id()) == cx.tcx.lang_items().panic_impl()
1345}
1346
1347/// Gets the name of the item the expression is in, if available.
1348pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
1349    let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
1350    match cx.tcx.hir_node_by_def_id(parent_id) {
1351        Node::Item(Item { ident, .. })
1352        | Node::TraitItem(TraitItem { ident, .. })
1353        | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
1354        _ => None,
1355    }
1356}
1357
1358pub struct ContainsName<'a, 'tcx> {
1359    pub cx: &'a LateContext<'tcx>,
1360    pub name: Symbol,
1361}
1362
1363impl<'tcx> Visitor<'tcx> for ContainsName<'_, 'tcx> {
1364    type Result = ControlFlow<()>;
1365    type NestedFilter = nested_filter::OnlyBodies;
1366
1367    fn visit_name(&mut self, name: Symbol) -> Self::Result {
1368        if self.name == name {
1369            ControlFlow::Break(())
1370        } else {
1371            ControlFlow::Continue(())
1372        }
1373    }
1374
1375    fn nested_visit_map(&mut self) -> Self::Map {
1376        self.cx.tcx.hir()
1377    }
1378}
1379
1380/// Checks if an `Expr` contains a certain name.
1381pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
1382    let mut cn = ContainsName { cx, name };
1383    cn.visit_expr(expr).is_break()
1384}
1385
1386/// Returns `true` if `expr` contains a return expression
1387pub fn contains_return<'tcx>(expr: impl Visitable<'tcx>) -> bool {
1388    for_each_expr_without_closures(expr, |e| {
1389        if matches!(e.kind, ExprKind::Ret(..)) {
1390            ControlFlow::Break(())
1391        } else {
1392            ControlFlow::Continue(())
1393        }
1394    })
1395    .is_some()
1396}
1397
1398/// Gets the parent expression, if any –- this is useful to constrain a lint.
1399pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1400    get_parent_expr_for_hir(cx, e.hir_id)
1401}
1402
1403/// This retrieves the parent for the given `HirId` if it's an expression. This is useful for
1404/// constraint lints
1405pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
1406    match cx.tcx.parent_hir_node(hir_id) {
1407        Node::Expr(parent) => Some(parent),
1408        _ => None,
1409    }
1410}
1411
1412/// Gets the enclosing block, if any.
1413pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
1414    let map = &cx.tcx.hir();
1415    let enclosing_node = map
1416        .get_enclosing_scope(hir_id)
1417        .map(|enclosing_id| cx.tcx.hir_node(enclosing_id));
1418    enclosing_node.and_then(|node| match node {
1419        Node::Block(block) => Some(block),
1420        Node::Item(&Item {
1421            kind: ItemKind::Fn { body: eid, .. },
1422            ..
1423        })
1424        | Node::ImplItem(&ImplItem {
1425            kind: ImplItemKind::Fn(_, eid),
1426            ..
1427        }) => match cx.tcx.hir().body(eid).value.kind {
1428            ExprKind::Block(block, _) => Some(block),
1429            _ => None,
1430        },
1431        _ => None,
1432    })
1433}
1434
1435/// Gets the loop or closure enclosing the given expression, if any.
1436pub fn get_enclosing_loop_or_multi_call_closure<'tcx>(
1437    cx: &LateContext<'tcx>,
1438    expr: &Expr<'_>,
1439) -> Option<&'tcx Expr<'tcx>> {
1440    for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) {
1441        match node {
1442            Node::Expr(e) => match e.kind {
1443                ExprKind::Closure { .. }
1444                    if let rustc_ty::Closure(_, subs) = cx.typeck_results().expr_ty(e).kind()
1445                        && subs.as_closure().kind() == ClosureKind::FnOnce => {},
1446
1447                // Note: A closure's kind is determined by how it's used, not it's captures.
1448                ExprKind::Closure { .. } | ExprKind::Loop(..) => return Some(e),
1449                _ => (),
1450            },
1451            Node::Stmt(_) | Node::Block(_) | Node::LetStmt(_) | Node::Arm(_) | Node::ExprField(_) => (),
1452            _ => break,
1453        }
1454    }
1455    None
1456}
1457
1458/// Gets the parent node if it's an impl block.
1459pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
1460    match tcx.hir().parent_iter(id).next() {
1461        Some((
1462            _,
1463            Node::Item(Item {
1464                kind: ItemKind::Impl(imp),
1465                ..
1466            }),
1467        )) => Some(imp),
1468        _ => None,
1469    }
1470}
1471
1472/// Removes blocks around an expression, only if the block contains just one expression
1473/// and no statements. Unsafe blocks are not removed.
1474///
1475/// Examples:
1476///  * `{}`               -> `{}`
1477///  * `{ x }`            -> `x`
1478///  * `{{ x }}`          -> `x`
1479///  * `{ x; }`           -> `{ x; }`
1480///  * `{ x; y }`         -> `{ x; y }`
1481///  * `{ unsafe { x } }` -> `unsafe { x }`
1482pub fn peel_blocks<'a>(mut expr: &'a Expr<'a>) -> &'a Expr<'a> {
1483    while let ExprKind::Block(
1484        Block {
1485            stmts: [],
1486            expr: Some(inner),
1487            rules: BlockCheckMode::DefaultBlock,
1488            ..
1489        },
1490        _,
1491    ) = expr.kind
1492    {
1493        expr = inner;
1494    }
1495    expr
1496}
1497
1498/// Removes blocks around an expression, only if the block contains just one expression
1499/// or just one expression statement with a semicolon. Unsafe blocks are not removed.
1500///
1501/// Examples:
1502///  * `{}`               -> `{}`
1503///  * `{ x }`            -> `x`
1504///  * `{ x; }`           -> `x`
1505///  * `{{ x; }}`         -> `x`
1506///  * `{ x; y }`         -> `{ x; y }`
1507///  * `{ unsafe { x } }` -> `unsafe { x }`
1508pub fn peel_blocks_with_stmt<'a>(mut expr: &'a Expr<'a>) -> &'a Expr<'a> {
1509    while let ExprKind::Block(
1510        Block {
1511            stmts: [],
1512            expr: Some(inner),
1513            rules: BlockCheckMode::DefaultBlock,
1514            ..
1515        }
1516        | Block {
1517            stmts:
1518                [
1519                    Stmt {
1520                        kind: StmtKind::Expr(inner) | StmtKind::Semi(inner),
1521                        ..
1522                    },
1523                ],
1524            expr: None,
1525            rules: BlockCheckMode::DefaultBlock,
1526            ..
1527        },
1528        _,
1529    ) = expr.kind
1530    {
1531        expr = inner;
1532    }
1533    expr
1534}
1535
1536/// Checks if the given expression is the else clause of either an `if` or `if let` expression.
1537pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1538    let mut iter = tcx.hir().parent_iter(expr.hir_id);
1539    match iter.next() {
1540        Some((
1541            _,
1542            Node::Expr(Expr {
1543                kind: ExprKind::If(_, _, Some(else_expr)),
1544                ..
1545            }),
1546        )) => else_expr.hir_id == expr.hir_id,
1547        _ => false,
1548    }
1549}
1550
1551/// Checks if the given expression is a part of `let else`
1552/// returns `true` for both the `init` and the `else` part
1553pub fn is_inside_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1554    let mut child_id = expr.hir_id;
1555    for (parent_id, node) in tcx.hir().parent_iter(child_id) {
1556        if let Node::LetStmt(LetStmt {
1557            init: Some(init),
1558            els: Some(els),
1559            ..
1560        }) = node
1561            && (init.hir_id == child_id || els.hir_id == child_id)
1562        {
1563            return true;
1564        }
1565
1566        child_id = parent_id;
1567    }
1568
1569    false
1570}
1571
1572/// Checks if the given expression is the else clause of a `let else` expression
1573pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1574    let mut child_id = expr.hir_id;
1575    for (parent_id, node) in tcx.hir().parent_iter(child_id) {
1576        if let Node::LetStmt(LetStmt { els: Some(els), .. }) = node
1577            && els.hir_id == child_id
1578        {
1579            return true;
1580        }
1581
1582        child_id = parent_id;
1583    }
1584
1585    false
1586}
1587
1588/// Checks whether the given `Expr` is a range equivalent to a `RangeFull`.
1589///
1590/// For the lower bound, this means that:
1591/// - either there is none
1592/// - or it is the smallest value that can be represented by the range's integer type
1593///
1594/// For the upper bound, this means that:
1595/// - either there is none
1596/// - or it is the largest value that can be represented by the range's integer type and is
1597///   inclusive
1598/// - or it is a call to some container's `len` method and is exclusive, and the range is passed to
1599///   a method call on that same container (e.g. `v.drain(..v.len())`)
1600///
1601/// If the given `Expr` is not some kind of range, the function returns `false`.
1602pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool {
1603    let ty = cx.typeck_results().expr_ty(expr);
1604    if let Some(Range { start, end, limits }) = Range::hir(expr) {
1605        let start_is_none_or_min = start.is_none_or(|start| {
1606            if let rustc_ty::Adt(_, subst) = ty.kind()
1607                && let bnd_ty = subst.type_at(0)
1608                && let Some(min_const) = bnd_ty.numeric_min_val(cx.tcx)
1609                && let Some(min_const) = mir_to_const(cx.tcx, min_const)
1610                && let Some(start_const) = ConstEvalCtxt::new(cx).eval(start)
1611            {
1612                start_const == min_const
1613            } else {
1614                false
1615            }
1616        });
1617        let end_is_none_or_max = end.is_none_or(|end| match limits {
1618            RangeLimits::Closed => {
1619                if let rustc_ty::Adt(_, subst) = ty.kind()
1620                    && let bnd_ty = subst.type_at(0)
1621                    && let Some(max_const) = bnd_ty.numeric_max_val(cx.tcx)
1622                    && let Some(max_const) = mir_to_const(cx.tcx, max_const)
1623                    && let Some(end_const) = ConstEvalCtxt::new(cx).eval(end)
1624                {
1625                    end_const == max_const
1626                } else {
1627                    false
1628                }
1629            },
1630            RangeLimits::HalfOpen => {
1631                if let Some(container_path) = container_path
1632                    && let ExprKind::MethodCall(name, self_arg, [], _) = end.kind
1633                    && name.ident.name == sym::len
1634                    && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind
1635                {
1636                    container_path.res == path.res
1637                } else {
1638                    false
1639                }
1640            },
1641        });
1642        return start_is_none_or_min && end_is_none_or_max;
1643    }
1644    false
1645}
1646
1647/// Checks whether the given expression is a constant integer of the given value.
1648/// unlike `is_integer_literal`, this version does const folding
1649pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
1650    if is_integer_literal(e, value) {
1651        return true;
1652    }
1653    let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
1654    if let Some(Constant::Int(v)) =
1655        ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e)
1656    {
1657        return value == v;
1658    }
1659    false
1660}
1661
1662/// Checks whether the given expression is a constant literal of the given value.
1663pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
1664    // FIXME: use constant folding
1665    if let ExprKind::Lit(spanned) = expr.kind {
1666        if let LitKind::Int(v, _) = spanned.node {
1667            return v == value;
1668        }
1669    }
1670    false
1671}
1672
1673/// Returns `true` if the given `Expr` has been coerced before.
1674///
1675/// Examples of coercions can be found in the Nomicon at
1676/// <https://doc.rust-lang.org/nomicon/coercions.html>.
1677///
1678/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_hir_analysis::check::coercion` for
1679/// more information on adjustments and coercions.
1680pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
1681    cx.typeck_results().adjustments().get(e.hir_id).is_some()
1682}
1683
1684/// Returns the pre-expansion span if this comes from an expansion of the
1685/// macro `name`.
1686/// See also [`is_direct_expn_of`].
1687#[must_use]
1688pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
1689    loop {
1690        if span.from_expansion() {
1691            let data = span.ctxt().outer_expn_data();
1692            let new_span = data.call_site;
1693
1694            if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1695                if mac_name.as_str() == name {
1696                    return Some(new_span);
1697                }
1698            }
1699
1700            span = new_span;
1701        } else {
1702            return None;
1703        }
1704    }
1705}
1706
1707/// Returns the pre-expansion span if the span directly comes from an expansion
1708/// of the macro `name`.
1709/// The difference with [`is_expn_of`] is that in
1710/// ```no_run
1711/// # macro_rules! foo { ($name:tt!$args:tt) => { $name!$args } }
1712/// # macro_rules! bar { ($e:expr) => { $e } }
1713/// foo!(bar!(42));
1714/// ```
1715/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
1716/// from `bar!` by `is_direct_expn_of`.
1717#[must_use]
1718pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
1719    if span.from_expansion() {
1720        let data = span.ctxt().outer_expn_data();
1721        let new_span = data.call_site;
1722
1723        if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1724            if mac_name.as_str() == name {
1725                return Some(new_span);
1726            }
1727        }
1728    }
1729
1730    None
1731}
1732
1733/// Convenience function to get the return type of a function.
1734pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId) -> Ty<'tcx> {
1735    let ret_ty = cx.tcx.fn_sig(fn_def_id).instantiate_identity().output();
1736    cx.tcx.instantiate_bound_regions_with_erased(ret_ty)
1737}
1738
1739/// Convenience function to get the nth argument type of a function.
1740pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId, nth: usize) -> Ty<'tcx> {
1741    let arg = cx.tcx.fn_sig(fn_def_id).instantiate_identity().input(nth);
1742    cx.tcx.instantiate_bound_regions_with_erased(arg)
1743}
1744
1745/// Checks if an expression is constructing a tuple-like enum variant or struct
1746pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1747    if let ExprKind::Call(fun, _) = expr.kind {
1748        if let ExprKind::Path(ref qp) = fun.kind {
1749            let res = cx.qpath_res(qp, fun.hir_id);
1750            return match res {
1751                Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
1752                Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
1753                _ => false,
1754            };
1755        }
1756    }
1757    false
1758}
1759
1760/// Returns `true` if a pattern is refutable.
1761// TODO: should be implemented using rustc/mir_build/thir machinery
1762pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
1763    fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
1764        matches!(
1765            cx.qpath_res(qpath, id),
1766            Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
1767        )
1768    }
1769
1770    fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
1771        i.into_iter().any(|pat| is_refutable(cx, pat))
1772    }
1773
1774    match pat.kind {
1775        PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
1776        PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
1777        PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
1778        PatKind::Expr(PatExpr {
1779            kind: PatExprKind::Path(qpath),
1780            hir_id,
1781            ..
1782        }) => is_enum_variant(cx, qpath, *hir_id),
1783        PatKind::Or(pats) => {
1784            // TODO: should be the honest check, that pats is exhaustive set
1785            are_refutable(cx, pats)
1786        },
1787        PatKind::Tuple(pats, _) => are_refutable(cx, pats),
1788        PatKind::Struct(ref qpath, fields, _) => {
1789            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
1790        },
1791        PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
1792        PatKind::Slice(head, middle, tail) => {
1793            match &cx.typeck_results().node_type(pat.hir_id).kind() {
1794                rustc_ty::Slice(..) => {
1795                    // [..] is the only irrefutable slice pattern.
1796                    !head.is_empty() || middle.is_none() || !tail.is_empty()
1797                },
1798                rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
1799                _ => {
1800                    // unreachable!()
1801                    true
1802                },
1803            }
1804        },
1805        PatKind::Expr(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) | PatKind::Guard(..) => true,
1806    }
1807}
1808
1809/// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call
1810/// the function once on the given pattern.
1811pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
1812    if let PatKind::Or(pats) = pat.kind {
1813        pats.iter().for_each(f);
1814    } else {
1815        f(pat);
1816    }
1817}
1818
1819pub fn is_self(slf: &Param<'_>) -> bool {
1820    if let PatKind::Binding(.., name, _) = slf.pat.kind {
1821        name.name == kw::SelfLower
1822    } else {
1823        false
1824    }
1825}
1826
1827pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
1828    if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind {
1829        if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res {
1830            return true;
1831        }
1832    }
1833    false
1834}
1835
1836pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator<Item = &'tcx Param<'tcx>> {
1837    (0..decl.inputs.len()).map(move |i| &body.params[i])
1838}
1839
1840/// Checks if a given expression is a match expression expanded from the `?`
1841/// operator or the `try` macro.
1842pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
1843    fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1844        if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind
1845            && ddpos.as_opt_usize().is_none()
1846            && is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk)
1847            && let PatKind::Binding(_, hir_id, _, None) = pat[0].kind
1848            && path_to_local_id(arm.body, hir_id)
1849        {
1850            return true;
1851        }
1852        false
1853    }
1854
1855    fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1856        if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
1857            is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultErr)
1858        } else {
1859            false
1860        }
1861    }
1862
1863    if let ExprKind::Match(_, arms, ref source) = expr.kind {
1864        // desugared from a `?` operator
1865        if let MatchSource::TryDesugar(_) = *source {
1866            return Some(expr);
1867        }
1868
1869        if arms.len() == 2
1870            && arms[0].guard.is_none()
1871            && arms[1].guard.is_none()
1872            && ((is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || (is_ok(cx, &arms[1]) && is_err(cx, &arms[0])))
1873        {
1874            return Some(expr);
1875        }
1876    }
1877
1878    None
1879}
1880
1881/// Returns `true` if the lint is `#[allow]`ed or `#[expect]`ed at any of the `ids`, fulfilling all
1882/// of the expectations in `ids`
1883///
1884/// This should only be used when the lint would otherwise be emitted, for a way to check if a lint
1885/// is allowed early to skip work see [`is_lint_allowed`]
1886///
1887/// To emit at a lint at a different context than the one current see
1888/// [`span_lint_hir`](diagnostics::span_lint_hir) or
1889/// [`span_lint_hir_and_then`](diagnostics::span_lint_hir_and_then)
1890pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl IntoIterator<Item = HirId>) -> bool {
1891    let mut suppress_lint = false;
1892
1893    for id in ids {
1894        let (level, _) = cx.tcx.lint_level_at_node(lint, id);
1895        if let Some(expectation) = level.get_expectation_id() {
1896            cx.fulfill_expectation(expectation);
1897        }
1898
1899        match level {
1900            Level::Allow | Level::Expect(_) => suppress_lint = true,
1901            Level::Warn | Level::ForceWarn(_) | Level::Deny | Level::Forbid => {},
1902        }
1903    }
1904
1905    suppress_lint
1906}
1907
1908/// Returns `true` if the lint is allowed in the current context. This is useful for
1909/// skipping long running code when it's unnecessary
1910///
1911/// This function should check the lint level for the same node, that the lint will
1912/// be emitted at. If the information is buffered to be emitted at a later point, please
1913/// make sure to use `span_lint_hir` functions to emit the lint. This ensures that
1914/// expectations at the checked nodes will be fulfilled.
1915pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
1916    cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
1917}
1918
1919pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
1920    while let PatKind::Ref(subpat, _) = pat.kind {
1921        pat = subpat;
1922    }
1923    pat
1924}
1925
1926pub fn int_bits(tcx: TyCtxt<'_>, ity: IntTy) -> u64 {
1927    Integer::from_int_ty(&tcx, ity).size().bits()
1928}
1929
1930#[expect(clippy::cast_possible_wrap)]
1931/// Turn a constant int byte representation into an i128
1932pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: IntTy) -> i128 {
1933    let amt = 128 - int_bits(tcx, ity);
1934    ((u as i128) << amt) >> amt
1935}
1936
1937#[expect(clippy::cast_sign_loss)]
1938/// clip unused bytes
1939pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: IntTy) -> u128 {
1940    let amt = 128 - int_bits(tcx, ity);
1941    ((u as u128) << amt) >> amt
1942}
1943
1944/// clip unused bytes
1945pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 {
1946    let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
1947    let amt = 128 - bits;
1948    (u << amt) >> amt
1949}
1950
1951pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
1952    attrs.iter().any(|attr| attr.has_name(symbol))
1953}
1954
1955pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
1956    has_attr(cx.tcx.hir().attrs(hir_id), sym::repr)
1957}
1958
1959pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
1960    let map = &tcx.hir();
1961    let mut prev_enclosing_node = None;
1962    let mut enclosing_node = node;
1963    while Some(enclosing_node) != prev_enclosing_node {
1964        if has_attr(map.attrs(enclosing_node), symbol) {
1965            return true;
1966        }
1967        prev_enclosing_node = Some(enclosing_node);
1968        enclosing_node = map.get_parent_item(enclosing_node).into();
1969    }
1970
1971    false
1972}
1973
1974/// Checks if the given HIR node is inside an `impl` block with the `automatically_derived`
1975/// attribute.
1976pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
1977    tcx.hir()
1978        .parent_owner_iter(id)
1979        .filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
1980        .any(|(id, _)| {
1981            has_attr(
1982                tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
1983                sym::automatically_derived,
1984            )
1985        })
1986}
1987
1988/// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
1989/// any.
1990///
1991/// Please use `tcx.get_diagnostic_name` if the targets are all diagnostic items.
1992pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]]) -> Option<usize> {
1993    let search_path = cx.get_def_path(did);
1994    paths
1995        .iter()
1996        .position(|p| p.iter().map(|x| Symbol::intern(x)).eq(search_path.iter().copied()))
1997}
1998
1999/// Checks if the given `DefId` matches the path.
2000pub fn match_def_path(cx: &LateContext<'_>, did: DefId, syms: &[&str]) -> bool {
2001    // We should probably move to Symbols in Clippy as well rather than interning every time.
2002    let path = cx.get_def_path(did);
2003    syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied())
2004}
2005
2006/// Checks if the given `DefId` matches the `libc` item.
2007pub fn match_libc_symbol(cx: &LateContext<'_>, did: DefId, name: &str) -> bool {
2008    let path = cx.get_def_path(did);
2009    // libc is meant to be used as a flat list of names, but they're all actually defined in different
2010    // modules based on the target platform. Ignore everything but crate name and the item name.
2011    path.first().is_some_and(|s| s.as_str() == "libc") && path.last().is_some_and(|s| s.as_str() == name)
2012}
2013
2014/// Returns the list of condition expressions and the list of blocks in a
2015/// sequence of `if/else`.
2016/// E.g., this returns `([a, b], [c, d, e])` for the expression
2017/// `if a { c } else if b { d } else { e }`.
2018pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) {
2019    let mut conds = Vec::new();
2020    let mut blocks: Vec<&Block<'_>> = Vec::new();
2021
2022    while let Some(higher::IfOrIfLet { cond, then, r#else }) = higher::IfOrIfLet::hir(expr) {
2023        conds.push(cond);
2024        if let ExprKind::Block(block, _) = then.kind {
2025            blocks.push(block);
2026        } else {
2027            panic!("ExprKind::If node is not an ExprKind::Block");
2028        }
2029
2030        if let Some(else_expr) = r#else {
2031            expr = else_expr;
2032        } else {
2033            break;
2034        }
2035    }
2036
2037    // final `else {..}`
2038    if !blocks.is_empty() {
2039        if let ExprKind::Block(block, _) = expr.kind {
2040            blocks.push(block);
2041        }
2042    }
2043
2044    (conds, blocks)
2045}
2046
2047/// Checks if the given function kind is an async function.
2048pub fn is_async_fn(kind: FnKind<'_>) -> bool {
2049    match kind {
2050        FnKind::ItemFn(_, _, header) => header.asyncness.is_async(),
2051        FnKind::Method(_, sig) => sig.header.asyncness.is_async(),
2052        FnKind::Closure => false,
2053    }
2054}
2055
2056/// Peels away all the compiler generated code surrounding the body of an async function,
2057pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
2058    if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
2059        if let ExprKind::Block(
2060            Block {
2061                stmts: [],
2062                expr:
2063                    Some(Expr {
2064                        kind: ExprKind::DropTemps(expr),
2065                        ..
2066                    }),
2067                ..
2068            },
2069            _,
2070        ) = tcx.hir().body(body).value.kind
2071        {
2072            return Some(expr);
2073        }
2074    }
2075    None
2076}
2077
2078// check if expr is calling method or function with #[must_use] attribute
2079pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
2080    let did = match expr.kind {
2081        ExprKind::Call(path, _) => {
2082            if let ExprKind::Path(ref qpath) = path.kind
2083                && let Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id)
2084            {
2085                Some(did)
2086            } else {
2087                None
2088            }
2089        },
2090        ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
2091        _ => None,
2092    };
2093
2094    did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use))
2095}
2096
2097/// Checks if a function's body represents the identity function. Looks for bodies of the form:
2098/// * `|x| x`
2099/// * `|x| return x`
2100/// * `|x| { return x }`
2101/// * `|x| { return x; }`
2102/// * `|(x, y)| (x, y)`
2103///
2104/// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
2105fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
2106    fn check_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
2107        if cx
2108            .typeck_results()
2109            .pat_binding_modes()
2110            .get(pat.hir_id)
2111            .is_some_and(|mode| matches!(mode.0, ByRef::Yes(_)))
2112        {
2113            // If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics,
2114            // the inner patterns become references. Don't consider this the identity function
2115            // as that changes types.
2116            return false;
2117        }
2118
2119        match (pat.kind, expr.kind) {
2120            (PatKind::Binding(_, id, _, _), _) => {
2121                path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty()
2122            },
2123            (PatKind::Tuple(pats, dotdot), ExprKind::Tup(tup))
2124                if dotdot.as_opt_usize().is_none() && pats.len() == tup.len() =>
2125            {
2126                pats.iter().zip(tup).all(|(pat, expr)| check_pat(cx, pat, expr))
2127            },
2128            _ => false,
2129        }
2130    }
2131
2132    let [param] = func.params else {
2133        return false;
2134    };
2135
2136    let mut expr = func.value;
2137    loop {
2138        match expr.kind {
2139            ExprKind::Block(
2140                &Block {
2141                    stmts: [],
2142                    expr: Some(e),
2143                    ..
2144                },
2145                _,
2146            )
2147            | ExprKind::Ret(Some(e)) => expr = e,
2148            ExprKind::Block(
2149                &Block {
2150                    stmts: [stmt],
2151                    expr: None,
2152                    ..
2153                },
2154                _,
2155            ) => {
2156                if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind
2157                    && let ExprKind::Ret(Some(ret_val)) = e.kind
2158                {
2159                    expr = ret_val;
2160                } else {
2161                    return false;
2162                }
2163            },
2164            _ => return check_pat(cx, param.pat, expr),
2165        }
2166    }
2167}
2168
2169/// This is the same as [`is_expr_identity_function`], but does not consider closures
2170/// with type annotations for its bindings (or similar) as identity functions:
2171/// * `|x: u8| x`
2172/// * `std::convert::identity::<u8>`
2173pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
2174    match expr.kind {
2175        ExprKind::Closure(&Closure { body, fn_decl, .. })
2176            if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) =>
2177        {
2178            is_body_identity_function(cx, cx.tcx.hir().body(body))
2179        },
2180        ExprKind::Path(QPath::Resolved(_, path))
2181            if path.segments.iter().all(|seg| seg.infer_args)
2182                && let Some(did) = path.res.opt_def_id() =>
2183        {
2184            cx.tcx.is_diagnostic_item(sym::convert_identity, did)
2185        },
2186        _ => false,
2187    }
2188}
2189
2190/// Checks if an expression represents the identity function
2191/// Only examines closures and `std::convert::identity`
2192///
2193/// NOTE: If you want to use this function to find out if a closure is unnecessary, you likely want
2194/// to call [`is_expr_untyped_identity_function`] instead, which makes sure that the closure doesn't
2195/// have type annotations. This is important because removing a closure with bindings can
2196/// remove type information that helped type inference before, which can then lead to compile
2197/// errors.
2198pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
2199    match expr.kind {
2200        ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
2201        _ => path_def_id(cx, expr).is_some_and(|id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
2202    }
2203}
2204
2205/// Gets the node where an expression is either used, or it's type is unified with another branch.
2206/// Returns both the node and the `HirId` of the closest child node.
2207pub fn get_expr_use_or_unification_node<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<(Node<'tcx>, HirId)> {
2208    let mut child_id = expr.hir_id;
2209    let mut iter = tcx.hir().parent_iter(child_id);
2210    loop {
2211        match iter.next() {
2212            None => break None,
2213            Some((id, Node::Block(_))) => child_id = id,
2214            Some((id, Node::Arm(arm))) if arm.body.hir_id == child_id => child_id = id,
2215            Some((_, Node::Expr(expr))) => match expr.kind {
2216                ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id,
2217                ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id,
2218                ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None,
2219                _ => break Some((Node::Expr(expr), child_id)),
2220            },
2221            Some((_, node)) => break Some((node, child_id)),
2222        }
2223    }
2224}
2225
2226/// Checks if the result of an expression is used, or it's type is unified with another branch.
2227pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
2228    !matches!(
2229        get_expr_use_or_unification_node(tcx, expr),
2230        None | Some((
2231            Node::Stmt(Stmt {
2232                kind: StmtKind::Expr(_)
2233                    | StmtKind::Semi(_)
2234                    | StmtKind::Let(LetStmt {
2235                        pat: Pat {
2236                            kind: PatKind::Wild,
2237                            ..
2238                        },
2239                        ..
2240                    }),
2241                ..
2242            }),
2243            _
2244        ))
2245    )
2246}
2247
2248/// Checks if the expression is the final expression returned from a block.
2249pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
2250    matches!(tcx.parent_hir_node(expr.hir_id), Node::Block(..))
2251}
2252
2253pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
2254    if !is_no_std_crate(cx) {
2255        Some("std")
2256    } else if !is_no_core_crate(cx) {
2257        Some("core")
2258    } else {
2259        None
2260    }
2261}
2262
2263pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
2264    cx.tcx
2265        .hir()
2266        .attrs(hir::CRATE_HIR_ID)
2267        .iter()
2268        .any(|attr| attr.name_or_empty() == sym::no_std)
2269}
2270
2271pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
2272    cx.tcx
2273        .hir()
2274        .attrs(hir::CRATE_HIR_ID)
2275        .iter()
2276        .any(|attr| attr.name_or_empty() == sym::no_core)
2277}
2278
2279/// Check if parent of a hir node is a trait implementation block.
2280/// For example, `f` in
2281/// ```no_run
2282/// # struct S;
2283/// # trait Trait { fn f(); }
2284/// impl Trait for S {
2285///     fn f() {}
2286/// }
2287/// ```
2288pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
2289    if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
2290        matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }))
2291    } else {
2292        false
2293    }
2294}
2295
2296/// Check if it's even possible to satisfy the `where` clause for the item.
2297///
2298/// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example:
2299///
2300/// ```ignore
2301/// fn foo() where i32: Iterator {
2302///     for _ in 2i32 {}
2303/// }
2304/// ```
2305pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
2306    use rustc_trait_selection::traits;
2307    let predicates = cx
2308        .tcx
2309        .predicates_of(did)
2310        .predicates
2311        .iter()
2312        .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
2313    traits::impossible_predicates(cx.tcx, traits::elaborate(cx.tcx, predicates).collect::<Vec<_>>())
2314}
2315
2316/// Returns the `DefId` of the callee if the given expression is a function or method call.
2317pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
2318    fn_def_id_with_node_args(cx, expr).map(|(did, _)| did)
2319}
2320
2321/// Returns the `DefId` of the callee if the given expression is a function or method call,
2322/// as well as its node args.
2323pub fn fn_def_id_with_node_args<'tcx>(
2324    cx: &LateContext<'tcx>,
2325    expr: &Expr<'_>,
2326) -> Option<(DefId, GenericArgsRef<'tcx>)> {
2327    let typeck = cx.typeck_results();
2328    match &expr.kind {
2329        ExprKind::MethodCall(..) => Some((
2330            typeck.type_dependent_def_id(expr.hir_id)?,
2331            typeck.node_args(expr.hir_id),
2332        )),
2333        ExprKind::Call(
2334            Expr {
2335                kind: ExprKind::Path(qpath),
2336                hir_id: path_hir_id,
2337                ..
2338            },
2339            ..,
2340        ) => {
2341            // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or
2342            // deref to fn pointers, dyn Fn, impl Fn - #8850
2343            if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) =
2344                typeck.qpath_res(qpath, *path_hir_id)
2345            {
2346                Some((id, typeck.node_args(*path_hir_id)))
2347            } else {
2348                None
2349            }
2350        },
2351        _ => None,
2352    }
2353}
2354
2355/// Returns `Option<String>` where String is a textual representation of the type encapsulated in
2356/// the slice iff the given expression is a slice of primitives.
2357///
2358/// (As defined in the `is_recursively_primitive_type` function.) Returns `None` otherwise.
2359pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
2360    let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
2361    let expr_kind = expr_type.kind();
2362    let is_primitive = match expr_kind {
2363        rustc_ty::Slice(element_type) => is_recursively_primitive_type(*element_type),
2364        rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => {
2365            if let rustc_ty::Slice(element_type) = inner_ty.kind() {
2366                is_recursively_primitive_type(*element_type)
2367            } else {
2368                unreachable!()
2369            }
2370        },
2371        _ => false,
2372    };
2373
2374    if is_primitive {
2375        // if we have wrappers like Array, Slice or Tuple, print these
2376        // and get the type enclosed in the slice ref
2377        match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
2378            rustc_ty::Slice(..) => return Some("slice".into()),
2379            rustc_ty::Array(..) => return Some("array".into()),
2380            rustc_ty::Tuple(..) => return Some("tuple".into()),
2381            _ => {
2382                // is_recursively_primitive_type() should have taken care
2383                // of the rest and we can rely on the type that is found
2384                let refs_peeled = expr_type.peel_refs();
2385                return Some(refs_peeled.walk().last().unwrap().to_string());
2386            },
2387        }
2388    }
2389    None
2390}
2391
2392/// Returns list of all pairs `(a, b)` where `eq(a, b) == true`
2393/// and `a` is before `b` in `exprs` for all `a` and `b` in
2394/// `exprs`
2395///
2396/// Given functions `eq` and `hash` such that `eq(a, b) == true`
2397/// implies `hash(a) == hash(b)`
2398pub fn search_same<T, Hash, Eq>(exprs: &[T], mut hash: Hash, mut eq: Eq) -> Vec<(&T, &T)>
2399where
2400    Hash: FnMut(&T) -> u64,
2401    Eq: FnMut(&T, &T) -> bool,
2402{
2403    match exprs {
2404        [a, b] if eq(a, b) => return vec![(a, b)],
2405        _ if exprs.len() <= 2 => return vec![],
2406        _ => {},
2407    }
2408
2409    let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
2410
2411    let mut map: UnhashMap<u64, Vec<&_>> =
2412        UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
2413
2414    for expr in exprs {
2415        match map.entry(hash(expr)) {
2416            Entry::Occupied(mut o) => {
2417                for o in o.get() {
2418                    if eq(o, expr) {
2419                        match_expr_list.push((o, expr));
2420                    }
2421                }
2422                o.get_mut().push(expr);
2423            },
2424            Entry::Vacant(v) => {
2425                v.insert(vec![expr]);
2426            },
2427        }
2428    }
2429
2430    match_expr_list
2431}
2432
2433/// Peels off all references on the pattern. Returns the underlying pattern and the number of
2434/// references removed.
2435pub fn peel_hir_pat_refs<'a>(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
2436    fn peel<'a>(pat: &'a Pat<'a>, count: usize) -> (&'a Pat<'a>, usize) {
2437        if let PatKind::Ref(pat, _) = pat.kind {
2438            peel(pat, count + 1)
2439        } else {
2440            (pat, count)
2441        }
2442    }
2443    peel(pat, 0)
2444}
2445
2446/// Peels of expressions while the given closure returns `Some`.
2447pub fn peel_hir_expr_while<'tcx>(
2448    mut expr: &'tcx Expr<'tcx>,
2449    mut f: impl FnMut(&'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>>,
2450) -> &'tcx Expr<'tcx> {
2451    while let Some(e) = f(expr) {
2452        expr = e;
2453    }
2454    expr
2455}
2456
2457/// Peels off up to the given number of references on the expression. Returns the underlying
2458/// expression and the number of references removed.
2459pub fn peel_n_hir_expr_refs<'a>(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
2460    let mut remaining = count;
2461    let e = peel_hir_expr_while(expr, |e| match e.kind {
2462        ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) if remaining != 0 => {
2463            remaining -= 1;
2464            Some(e)
2465        },
2466        _ => None,
2467    });
2468    (e, count - remaining)
2469}
2470
2471/// Peels off all unary operators of an expression. Returns the underlying expression and the number
2472/// of operators removed.
2473pub fn peel_hir_expr_unary<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
2474    let mut count: usize = 0;
2475    let mut curr_expr = expr;
2476    while let ExprKind::Unary(_, local_expr) = curr_expr.kind {
2477        count = count.wrapping_add(1);
2478        curr_expr = local_expr;
2479    }
2480    (curr_expr, count)
2481}
2482
2483/// Peels off all references on the expression. Returns the underlying expression and the number of
2484/// references removed.
2485pub fn peel_hir_expr_refs<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
2486    let mut count = 0;
2487    let e = peel_hir_expr_while(expr, |e| match e.kind {
2488        ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) => {
2489            count += 1;
2490            Some(e)
2491        },
2492        _ => None,
2493    });
2494    (e, count)
2495}
2496
2497/// Peels off all references on the type. Returns the underlying type and the number of references
2498/// removed.
2499pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) {
2500    let mut count = 0;
2501    loop {
2502        match &ty.kind {
2503            TyKind::Ref(_, ref_ty) => {
2504                ty = ref_ty.ty;
2505                count += 1;
2506            },
2507            _ => break (ty, count),
2508        }
2509    }
2510}
2511
2512/// Peels off all references on the type. Returns the underlying type and the number of references
2513/// removed.
2514pub fn peel_middle_ty_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
2515    let mut count = 0;
2516    while let rustc_ty::Ref(_, dest_ty, _) = ty.kind() {
2517        ty = *dest_ty;
2518        count += 1;
2519    }
2520    (ty, count)
2521}
2522
2523/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
2524/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
2525pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
2526    loop {
2527        match expr.kind {
2528            ExprKind::AddrOf(_, _, e) => expr = e,
2529            ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
2530            _ => break,
2531        }
2532    }
2533    expr
2534}
2535
2536pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
2537    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
2538        if let Res::Def(_, def_id) = path.res {
2539            return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
2540        }
2541    }
2542    false
2543}
2544
2545static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalModDefId, Vec<Symbol>>>> = OnceLock::new();
2546
2547fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
2548    let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
2549    let mut map: MutexGuard<'_, FxHashMap<LocalModDefId, Vec<Symbol>>> = cache.lock().unwrap();
2550    let value = map.entry(module);
2551    match value {
2552        Entry::Occupied(entry) => f(entry.get()),
2553        Entry::Vacant(entry) => {
2554            let mut names = Vec::new();
2555            for id in tcx.hir().module_items(module) {
2556                if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
2557                    && let item = tcx.hir().item(id)
2558                    && let ItemKind::Const(ty, _generics, _body) = item.kind
2559                {
2560                    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
2561                        // We could also check for the type name `test::TestDescAndFn`
2562                        if let Res::Def(DefKind::Struct, _) = path.res {
2563                            let has_test_marker = tcx
2564                                .hir()
2565                                .attrs(item.hir_id())
2566                                .iter()
2567                                .any(|a| a.has_name(sym::rustc_test_marker));
2568                            if has_test_marker {
2569                                names.push(item.ident.name);
2570                            }
2571                        }
2572                    }
2573                }
2574            }
2575            names.sort_unstable();
2576            f(entry.insert(names))
2577        },
2578    }
2579}
2580
2581/// Checks if the function containing the given `HirId` is a `#[test]` function
2582///
2583/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function
2584pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
2585    with_test_item_names(tcx, tcx.parent_module(id), |names| {
2586        let node = tcx.hir_node(id);
2587        once((id, node))
2588            .chain(tcx.hir().parent_iter(id))
2589            // Since you can nest functions we need to collect all until we leave
2590            // function scope
2591            .any(|(_id, node)| {
2592                if let Node::Item(item) = node {
2593                    if let ItemKind::Fn { .. } = item.kind {
2594                        // Note that we have sorted the item names in the visitor,
2595                        // so the binary_search gets the same as `contains`, but faster.
2596                        return names.binary_search(&item.ident.name).is_ok();
2597                    }
2598                }
2599                false
2600            })
2601    })
2602}
2603
2604/// Checks if `id` has a `#[cfg(test)]` attribute applied
2605///
2606/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
2607/// use [`is_in_cfg_test`]
2608pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
2609    tcx.hir().attrs(id).iter().any(|attr| {
2610        if attr.has_name(sym::cfg)
2611            && let Some(items) = attr.meta_item_list()
2612            && let [item] = &*items
2613            && item.has_name(sym::test)
2614        {
2615            true
2616        } else {
2617            false
2618        }
2619    })
2620}
2621
2622/// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied
2623pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
2624    tcx.hir()
2625        .parent_id_iter(id)
2626        .any(|parent_id| is_cfg_test(tcx, parent_id))
2627}
2628
2629/// Checks if the node is in a `#[test]` function or has any parent node marked `#[cfg(test)]`
2630pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
2631    is_in_test_function(tcx, hir_id) || is_in_cfg_test(tcx, hir_id)
2632}
2633
2634/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
2635pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
2636    let hir = tcx.hir();
2637
2638    tcx.has_attr(def_id, sym::cfg)
2639        || hir
2640            .parent_iter(tcx.local_def_id_to_hir_id(def_id))
2641            .flat_map(|(parent_id, _)| hir.attrs(parent_id))
2642            .any(|attr| attr.has_name(sym::cfg))
2643}
2644
2645/// Walks up the HIR tree from the given expression in an attempt to find where the value is
2646/// consumed.
2647///
2648/// Termination has three conditions:
2649/// - The given function returns `Break`. This function will return the value.
2650/// - The consuming node is found. This function will return `Continue(use_node, child_id)`.
2651/// - No further parent nodes are found. This will trigger a debug assert or return `None`.
2652///
2653/// This allows walking through `if`, `match`, `break`, and block expressions to find where the
2654/// value produced by the expression is consumed.
2655pub fn walk_to_expr_usage<'tcx, T>(
2656    cx: &LateContext<'tcx>,
2657    e: &Expr<'tcx>,
2658    mut f: impl FnMut(HirId, Node<'tcx>, HirId) -> ControlFlow<T>,
2659) -> Option<ControlFlow<T, (Node<'tcx>, HirId)>> {
2660    let map = cx.tcx.hir();
2661    let mut iter = map.parent_iter(e.hir_id);
2662    let mut child_id = e.hir_id;
2663
2664    while let Some((parent_id, parent)) = iter.next() {
2665        if let ControlFlow::Break(x) = f(parent_id, parent, child_id) {
2666            return Some(ControlFlow::Break(x));
2667        }
2668        let parent_expr = match parent {
2669            Node::Expr(e) => e,
2670            Node::Block(Block { expr: Some(body), .. }) | Node::Arm(Arm { body, .. }) if body.hir_id == child_id => {
2671                child_id = parent_id;
2672                continue;
2673            },
2674            Node::Arm(a) if a.body.hir_id == child_id => {
2675                child_id = parent_id;
2676                continue;
2677            },
2678            _ => return Some(ControlFlow::Continue((parent, child_id))),
2679        };
2680        match parent_expr.kind {
2681            ExprKind::If(child, ..) | ExprKind::Match(child, ..) if child.hir_id != child_id => child_id = parent_id,
2682            ExprKind::Break(Destination { target_id: Ok(id), .. }, _) => {
2683                child_id = id;
2684                iter = map.parent_iter(id);
2685            },
2686            ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = parent_id,
2687            _ => return Some(ControlFlow::Continue((parent, child_id))),
2688        }
2689    }
2690    debug_assert!(false, "no parent node found for `{child_id:?}`");
2691    None
2692}
2693
2694/// A type definition as it would be viewed from within a function.
2695#[derive(Clone, Copy)]
2696pub enum DefinedTy<'tcx> {
2697    // Used for locals and closures defined within the function.
2698    Hir(&'tcx hir::Ty<'tcx>),
2699    /// Used for function signatures, and constant and static values. The type is
2700    /// in the context of its definition site. We also track the `def_id` of its
2701    /// definition site.
2702    ///
2703    /// WARNING: As the `ty` in in the scope of the definition, not of the function
2704    /// using it, you must be very careful with how you use it. Using it in the wrong
2705    /// scope easily results in ICEs.
2706    Mir {
2707        def_site_def_id: Option<DefId>,
2708        ty: Binder<'tcx, Ty<'tcx>>,
2709    },
2710}
2711
2712/// The context an expressions value is used in.
2713pub struct ExprUseCtxt<'tcx> {
2714    /// The parent node which consumes the value.
2715    pub node: Node<'tcx>,
2716    /// The child id of the node the value came from.
2717    pub child_id: HirId,
2718    /// Any adjustments applied to the type.
2719    pub adjustments: &'tcx [Adjustment<'tcx>],
2720    /// Whether the type must unify with another code path.
2721    pub is_ty_unified: bool,
2722    /// Whether the value will be moved before it's used.
2723    pub moved_before_use: bool,
2724    /// Whether the use site has the same `SyntaxContext` as the value.
2725    pub same_ctxt: bool,
2726}
2727impl<'tcx> ExprUseCtxt<'tcx> {
2728    pub fn use_node(&self, cx: &LateContext<'tcx>) -> ExprUseNode<'tcx> {
2729        match self.node {
2730            Node::LetStmt(l) => ExprUseNode::LetStmt(l),
2731            Node::ExprField(field) => ExprUseNode::Field(field),
2732
2733            Node::Item(&Item {
2734                kind: ItemKind::Static(..) | ItemKind::Const(..),
2735                owner_id,
2736                ..
2737            })
2738            | Node::TraitItem(&TraitItem {
2739                kind: TraitItemKind::Const(..),
2740                owner_id,
2741                ..
2742            })
2743            | Node::ImplItem(&ImplItem {
2744                kind: ImplItemKind::Const(..),
2745                owner_id,
2746                ..
2747            }) => ExprUseNode::ConstStatic(owner_id),
2748
2749            Node::Item(&Item {
2750                kind: ItemKind::Fn { .. },
2751                owner_id,
2752                ..
2753            })
2754            | Node::TraitItem(&TraitItem {
2755                kind: TraitItemKind::Fn(..),
2756                owner_id,
2757                ..
2758            })
2759            | Node::ImplItem(&ImplItem {
2760                kind: ImplItemKind::Fn(..),
2761                owner_id,
2762                ..
2763            }) => ExprUseNode::Return(owner_id),
2764
2765            Node::Expr(use_expr) => match use_expr.kind {
2766                ExprKind::Ret(_) => ExprUseNode::Return(OwnerId {
2767                    def_id: cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
2768                }),
2769
2770                ExprKind::Closure(closure) => ExprUseNode::Return(OwnerId { def_id: closure.def_id }),
2771                ExprKind::Call(func, args) => match args.iter().position(|arg| arg.hir_id == self.child_id) {
2772                    Some(i) => ExprUseNode::FnArg(func, i),
2773                    None => ExprUseNode::Callee,
2774                },
2775                ExprKind::MethodCall(name, _, args, _) => ExprUseNode::MethodArg(
2776                    use_expr.hir_id,
2777                    name.args,
2778                    args.iter()
2779                        .position(|arg| arg.hir_id == self.child_id)
2780                        .map_or(0, |i| i + 1),
2781                ),
2782                ExprKind::Field(_, name) => ExprUseNode::FieldAccess(name),
2783                ExprKind::AddrOf(kind, mutbl, _) => ExprUseNode::AddrOf(kind, mutbl),
2784                _ => ExprUseNode::Other,
2785            },
2786            _ => ExprUseNode::Other,
2787        }
2788    }
2789}
2790
2791/// The node which consumes a value.
2792pub enum ExprUseNode<'tcx> {
2793    /// Assignment to, or initializer for, a local
2794    LetStmt(&'tcx LetStmt<'tcx>),
2795    /// Initializer for a const or static item.
2796    ConstStatic(OwnerId),
2797    /// Implicit or explicit return from a function.
2798    Return(OwnerId),
2799    /// Initialization of a struct field.
2800    Field(&'tcx ExprField<'tcx>),
2801    /// An argument to a function.
2802    FnArg(&'tcx Expr<'tcx>, usize),
2803    /// An argument to a method.
2804    MethodArg(HirId, Option<&'tcx GenericArgs<'tcx>>, usize),
2805    /// The callee of a function call.
2806    Callee,
2807    /// Access of a field.
2808    FieldAccess(Ident),
2809    /// Borrow expression.
2810    AddrOf(ast::BorrowKind, Mutability),
2811    Other,
2812}
2813impl<'tcx> ExprUseNode<'tcx> {
2814    /// Checks if the value is returned from the function.
2815    pub fn is_return(&self) -> bool {
2816        matches!(self, Self::Return(_))
2817    }
2818
2819    /// Checks if the value is used as a method call receiver.
2820    pub fn is_recv(&self) -> bool {
2821        matches!(self, Self::MethodArg(_, _, 0))
2822    }
2823
2824    /// Gets the needed type as it's defined without any type inference.
2825    pub fn defined_ty(&self, cx: &LateContext<'tcx>) -> Option<DefinedTy<'tcx>> {
2826        match *self {
2827            Self::LetStmt(LetStmt { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)),
2828            Self::ConstStatic(id) => Some(DefinedTy::Mir {
2829                def_site_def_id: Some(id.def_id.to_def_id()),
2830                ty: Binder::dummy(cx.tcx.type_of(id).instantiate_identity()),
2831            }),
2832            Self::Return(id) => {
2833                if let Node::Expr(Expr {
2834                    kind: ExprKind::Closure(c),
2835                    ..
2836                }) = cx.tcx.hir_node_by_def_id(id.def_id)
2837                {
2838                    match c.fn_decl.output {
2839                        FnRetTy::DefaultReturn(_) => None,
2840                        FnRetTy::Return(ty) => Some(DefinedTy::Hir(ty)),
2841                    }
2842                } else {
2843                    let ty = cx.tcx.fn_sig(id).instantiate_identity().output();
2844                    Some(DefinedTy::Mir {
2845                        def_site_def_id: Some(id.def_id.to_def_id()),
2846                        ty,
2847                    })
2848                }
2849            },
2850            Self::Field(field) => match get_parent_expr_for_hir(cx, field.hir_id) {
2851                Some(Expr {
2852                    hir_id,
2853                    kind: ExprKind::Struct(path, ..),
2854                    ..
2855                }) => adt_and_variant_of_res(cx, cx.qpath_res(path, *hir_id))
2856                    .and_then(|(adt, variant)| {
2857                        variant
2858                            .fields
2859                            .iter()
2860                            .find(|f| f.name == field.ident.name)
2861                            .map(|f| (adt, f))
2862                    })
2863                    .map(|(adt, field_def)| DefinedTy::Mir {
2864                        def_site_def_id: Some(adt.did()),
2865                        ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()),
2866                    }),
2867                _ => None,
2868            },
2869            Self::FnArg(callee, i) => {
2870                let sig = expr_sig(cx, callee)?;
2871                let (hir_ty, ty) = sig.input_with_hir(i)?;
2872                Some(match hir_ty {
2873                    Some(hir_ty) => DefinedTy::Hir(hir_ty),
2874                    None => DefinedTy::Mir {
2875                        def_site_def_id: sig.predicates_id(),
2876                        ty,
2877                    },
2878                })
2879            },
2880            Self::MethodArg(id, _, i) => {
2881                let id = cx.typeck_results().type_dependent_def_id(id)?;
2882                let sig = cx.tcx.fn_sig(id).skip_binder();
2883                Some(DefinedTy::Mir {
2884                    def_site_def_id: Some(id),
2885                    ty: sig.input(i),
2886                })
2887            },
2888            Self::LetStmt(_) | Self::FieldAccess(..) | Self::Callee | Self::Other | Self::AddrOf(..) => None,
2889        }
2890    }
2891}
2892
2893/// Gets the context an expression's value is used in.
2894pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprUseCtxt<'tcx> {
2895    let mut adjustments = [].as_slice();
2896    let mut is_ty_unified = false;
2897    let mut moved_before_use = false;
2898    let mut same_ctxt = true;
2899    let ctxt = e.span.ctxt();
2900    let node = walk_to_expr_usage(cx, e, &mut |parent_id, parent, child_id| -> ControlFlow<!> {
2901        if adjustments.is_empty()
2902            && let Node::Expr(e) = cx.tcx.hir_node(child_id)
2903        {
2904            adjustments = cx.typeck_results().expr_adjustments(e);
2905        }
2906        same_ctxt &= cx.tcx.hir().span(parent_id).ctxt() == ctxt;
2907        if let Node::Expr(e) = parent {
2908            match e.kind {
2909                ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id != child_id => {
2910                    is_ty_unified = true;
2911                    moved_before_use = true;
2912                },
2913                ExprKind::Block(_, Some(_)) | ExprKind::Break(..) => {
2914                    is_ty_unified = true;
2915                    moved_before_use = true;
2916                },
2917                ExprKind::Block(..) => moved_before_use = true,
2918                _ => {},
2919            }
2920        }
2921        ControlFlow::Continue(())
2922    });
2923    match node {
2924        Some(ControlFlow::Continue((node, child_id))) => ExprUseCtxt {
2925            node,
2926            child_id,
2927            adjustments,
2928            is_ty_unified,
2929            moved_before_use,
2930            same_ctxt,
2931        },
2932        #[allow(unreachable_patterns)]
2933        Some(ControlFlow::Break(_)) => unreachable!("type of node is ControlFlow<!>"),
2934        None => ExprUseCtxt {
2935            node: Node::Crate(cx.tcx.hir().root_module()),
2936            child_id: HirId::INVALID,
2937            adjustments: &[],
2938            is_ty_unified: true,
2939            moved_before_use: true,
2940            same_ctxt: false,
2941        },
2942    }
2943}
2944
2945/// Tokenizes the input while keeping the text associated with each token.
2946pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> {
2947    let mut pos = 0;
2948    tokenize(s).map(move |t| {
2949        let end = pos + t.len;
2950        let range = pos as usize..end as usize;
2951        let inner = InnerSpan::new(range.start, range.end);
2952        pos = end;
2953        (t.kind, s.get(range).unwrap_or_default(), inner)
2954    })
2955}
2956
2957/// Checks whether a given span has any comment token
2958/// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
2959pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
2960    let Ok(snippet) = sm.span_to_snippet(span) else {
2961        return false;
2962    };
2963    return tokenize(&snippet).any(|token| {
2964        matches!(
2965            token.kind,
2966            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }
2967        )
2968    });
2969}
2970
2971/// Returns all the comments a given span contains
2972///
2973/// Comments are returned wrapped with their relevant delimiters
2974pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
2975    span_extract_comments(sm, span).join("\n")
2976}
2977
2978/// Returns all the comments a given span contains.
2979///
2980/// Comments are returned wrapped with their relevant delimiters.
2981pub fn span_extract_comments(sm: &SourceMap, span: Span) -> Vec<String> {
2982    let snippet = sm.span_to_snippet(span).unwrap_or_default();
2983    tokenize_with_text(&snippet)
2984        .filter(|(t, ..)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
2985        .map(|(_, s, _)| s.to_string())
2986        .collect::<Vec<_>>()
2987}
2988
2989pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
2990    sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
2991}
2992
2993/// Returns whether the given let pattern and else body can be turned into a question mark
2994///
2995/// For this example:
2996/// ```ignore
2997/// let FooBar { a, b } = if let Some(a) = ex { a } else { return None };
2998/// ```
2999/// We get as parameters:
3000/// ```ignore
3001/// pat: Some(a)
3002/// else_body: return None
3003/// ```
3004///
3005/// And for this example:
3006/// ```ignore
3007/// let Some(FooBar { a, b }) = ex else { return None };
3008/// ```
3009/// We get as parameters:
3010/// ```ignore
3011/// pat: Some(FooBar { a, b })
3012/// else_body: return None
3013/// ```
3014///
3015/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
3016/// the question mark operator is applicable here. Callers have to check whether we are in a
3017/// constant or not.
3018pub fn pat_and_expr_can_be_question_mark<'a, 'hir>(
3019    cx: &LateContext<'_>,
3020    pat: &'a Pat<'hir>,
3021    else_body: &Expr<'_>,
3022) -> Option<&'a Pat<'hir>> {
3023    if let PatKind::TupleStruct(pat_path, [inner_pat], _) = pat.kind
3024        && is_res_lang_ctor(cx, cx.qpath_res(&pat_path, pat.hir_id), OptionSome)
3025        && !is_refutable(cx, inner_pat)
3026        && let else_body = peel_blocks(else_body)
3027        && let ExprKind::Ret(Some(ret_val)) = else_body.kind
3028        && let ExprKind::Path(ret_path) = ret_val.kind
3029        && is_res_lang_ctor(cx, cx.qpath_res(&ret_path, ret_val.hir_id), OptionNone)
3030    {
3031        Some(inner_pat)
3032    } else {
3033        None
3034    }
3035}
3036
3037macro_rules! op_utils {
3038    ($($name:ident $assign:ident)*) => {
3039        /// Binary operation traits like `LangItem::Add`
3040        pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
3041
3042        /// Operator-Assign traits like `LangItem::AddAssign`
3043        pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
3044
3045        /// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
3046        pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
3047            match kind {
3048                $(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
3049                _ => None,
3050            }
3051        }
3052    };
3053}
3054
3055op_utils! {
3056    Add    AddAssign
3057    Sub    SubAssign
3058    Mul    MulAssign
3059    Div    DivAssign
3060    Rem    RemAssign
3061    BitXor BitXorAssign
3062    BitAnd BitAndAssign
3063    BitOr  BitOrAssign
3064    Shl    ShlAssign
3065    Shr    ShrAssign
3066}
3067
3068/// Returns `true` if the pattern is a `PatWild`, or is an ident prefixed with `_`
3069/// that is not locally used.
3070pub fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: impl Visitable<'tcx>) -> bool {
3071    match *pat {
3072        PatKind::Wild => true,
3073        PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => {
3074            !visitors::is_local_used(cx, body, id)
3075        },
3076        _ => false,
3077    }
3078}
3079
3080#[derive(Clone, Copy)]
3081pub enum RequiresSemi {
3082    Yes,
3083    No,
3084}
3085impl RequiresSemi {
3086    pub fn requires_semi(self) -> bool {
3087        matches!(self, Self::Yes)
3088    }
3089}
3090
3091/// Check if the expression return `!`, a type coerced from `!`, or could return `!` if the final
3092/// expression were turned into a statement.
3093#[expect(clippy::too_many_lines)]
3094pub fn is_never_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<RequiresSemi> {
3095    struct BreakTarget {
3096        id: HirId,
3097        unused: bool,
3098    }
3099
3100    struct V<'cx, 'tcx> {
3101        cx: &'cx LateContext<'tcx>,
3102        break_targets: Vec<BreakTarget>,
3103        break_targets_for_result_ty: u32,
3104        in_final_expr: bool,
3105        requires_semi: bool,
3106        is_never: bool,
3107    }
3108
3109    impl V<'_, '_> {
3110        fn push_break_target(&mut self, id: HirId) {
3111            self.break_targets.push(BreakTarget { id, unused: true });
3112            self.break_targets_for_result_ty += u32::from(self.in_final_expr);
3113        }
3114    }
3115
3116    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
3117        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
3118            // Note: Part of the complexity here comes from the fact that
3119            // coercions are applied to the innermost expression.
3120            // e.g. In `let x: u32 = { break () };` the never-to-any coercion
3121            // is applied to the break expression. This means we can't just
3122            // check the block's type as it will be `u32` despite the fact
3123            // that the block always diverges.
3124
3125            // The rest of the complexity comes from checking blocks which
3126            // syntactically return a value, but will always diverge before
3127            // reaching that point.
3128            // e.g. In `let x = { foo(panic!()) };` the block's type will be the
3129            // return type of `foo` even though it will never actually run. This
3130            // can be trivially fixed by adding a semicolon after the call, but
3131            // we must first detect that a semicolon is needed to make that
3132            // suggestion.
3133
3134            if self.is_never && self.break_targets.is_empty() {
3135                if self.in_final_expr && !self.requires_semi {
3136                    // This expression won't ever run, but we still need to check
3137                    // if it can affect the type of the final expression.
3138                    match e.kind {
3139                        ExprKind::DropTemps(e) => self.visit_expr(e),
3140                        ExprKind::If(_, then, Some(else_)) => {
3141                            self.visit_expr(then);
3142                            self.visit_expr(else_);
3143                        },
3144                        ExprKind::Match(_, arms, _) => {
3145                            for arm in arms {
3146                                self.visit_expr(arm.body);
3147                            }
3148                        },
3149                        ExprKind::Loop(b, ..) => {
3150                            self.push_break_target(e.hir_id);
3151                            self.in_final_expr = false;
3152                            self.visit_block(b);
3153                            self.break_targets.pop();
3154                        },
3155                        ExprKind::Block(b, _) => {
3156                            if b.targeted_by_break {
3157                                self.push_break_target(b.hir_id);
3158                                self.visit_block(b);
3159                                self.break_targets.pop();
3160                            } else {
3161                                self.visit_block(b);
3162                            }
3163                        },
3164                        _ => {
3165                            self.requires_semi = !self.cx.typeck_results().expr_ty(e).is_never();
3166                        },
3167                    }
3168                }
3169                return;
3170            }
3171            match e.kind {
3172                ExprKind::DropTemps(e) => self.visit_expr(e),
3173                ExprKind::Ret(None) | ExprKind::Continue(_) => self.is_never = true,
3174                ExprKind::Ret(Some(e)) | ExprKind::Become(e) => {
3175                    self.in_final_expr = false;
3176                    self.visit_expr(e);
3177                    self.is_never = true;
3178                },
3179                ExprKind::Break(dest, e) => {
3180                    if let Some(e) = e {
3181                        self.in_final_expr = false;
3182                        self.visit_expr(e);
3183                    }
3184                    if let Ok(id) = dest.target_id
3185                        && let Some((i, target)) = self
3186                            .break_targets
3187                            .iter_mut()
3188                            .enumerate()
3189                            .find(|(_, target)| target.id == id)
3190                    {
3191                        target.unused &= self.is_never;
3192                        if i < self.break_targets_for_result_ty as usize {
3193                            self.requires_semi = true;
3194                        }
3195                    }
3196                    self.is_never = true;
3197                },
3198                ExprKind::If(cond, then, else_) => {
3199                    let in_final_expr = mem::replace(&mut self.in_final_expr, false);
3200                    self.visit_expr(cond);
3201                    self.in_final_expr = in_final_expr;
3202
3203                    if self.is_never {
3204                        self.visit_expr(then);
3205                        if let Some(else_) = else_ {
3206                            self.visit_expr(else_);
3207                        }
3208                    } else {
3209                        self.visit_expr(then);
3210                        let is_never = mem::replace(&mut self.is_never, false);
3211                        if let Some(else_) = else_ {
3212                            self.visit_expr(else_);
3213                            self.is_never &= is_never;
3214                        }
3215                    }
3216                },
3217                ExprKind::Match(scrutinee, arms, _) => {
3218                    let in_final_expr = mem::replace(&mut self.in_final_expr, false);
3219                    self.visit_expr(scrutinee);
3220                    self.in_final_expr = in_final_expr;
3221
3222                    if self.is_never {
3223                        for arm in arms {
3224                            self.visit_arm(arm);
3225                        }
3226                    } else {
3227                        let mut is_never = true;
3228                        for arm in arms {
3229                            self.is_never = false;
3230                            if let Some(guard) = arm.guard {
3231                                let in_final_expr = mem::replace(&mut self.in_final_expr, false);
3232                                self.visit_expr(guard);
3233                                self.in_final_expr = in_final_expr;
3234                                // The compiler doesn't consider diverging guards as causing the arm to diverge.
3235                                self.is_never = false;
3236                            }
3237                            self.visit_expr(arm.body);
3238                            is_never &= self.is_never;
3239                        }
3240                        self.is_never = is_never;
3241                    }
3242                },
3243                ExprKind::Loop(b, _, _, _) => {
3244                    self.push_break_target(e.hir_id);
3245                    self.in_final_expr = false;
3246                    self.visit_block(b);
3247                    self.is_never = self.break_targets.pop().unwrap().unused;
3248                },
3249                ExprKind::Block(b, _) => {
3250                    if b.targeted_by_break {
3251                        self.push_break_target(b.hir_id);
3252                        self.visit_block(b);
3253                        self.is_never &= self.break_targets.pop().unwrap().unused;
3254                    } else {
3255                        self.visit_block(b);
3256                    }
3257                },
3258                _ => {
3259                    self.in_final_expr = false;
3260                    walk_expr(self, e);
3261                    self.is_never |= self.cx.typeck_results().expr_ty(e).is_never();
3262                },
3263            }
3264        }
3265
3266        fn visit_block(&mut self, b: &'tcx Block<'_>) {
3267            let in_final_expr = mem::replace(&mut self.in_final_expr, false);
3268            for s in b.stmts {
3269                self.visit_stmt(s);
3270            }
3271            self.in_final_expr = in_final_expr;
3272            if let Some(e) = b.expr {
3273                self.visit_expr(e);
3274            }
3275        }
3276
3277        fn visit_local(&mut self, l: &'tcx LetStmt<'_>) {
3278            if let Some(e) = l.init {
3279                self.visit_expr(e);
3280            }
3281            if let Some(else_) = l.els {
3282                let is_never = self.is_never;
3283                self.visit_block(else_);
3284                self.is_never = is_never;
3285            }
3286        }
3287
3288        fn visit_arm(&mut self, arm: &Arm<'tcx>) {
3289            if let Some(guard) = arm.guard {
3290                let in_final_expr = mem::replace(&mut self.in_final_expr, false);
3291                self.visit_expr(guard);
3292                self.in_final_expr = in_final_expr;
3293            }
3294            self.visit_expr(arm.body);
3295        }
3296    }
3297
3298    if cx.typeck_results().expr_ty(e).is_never() {
3299        Some(RequiresSemi::No)
3300    } else if let ExprKind::Block(b, _) = e.kind
3301        && !b.targeted_by_break
3302        && b.expr.is_none()
3303    {
3304        // If a block diverges without a final expression then it's type is `!`.
3305        None
3306    } else {
3307        let mut v = V {
3308            cx,
3309            break_targets: Vec::new(),
3310            break_targets_for_result_ty: 0,
3311            in_final_expr: true,
3312            requires_semi: false,
3313            is_never: false,
3314        };
3315        v.visit_expr(e);
3316        v.is_never
3317            .then_some(if v.requires_semi && matches!(e.kind, ExprKind::Block(..)) {
3318                RequiresSemi::Yes
3319            } else {
3320                RequiresSemi::No
3321            })
3322    }
3323}
3324
3325/// Produces a path from a local caller to the type of the called method. Suitable for user
3326/// output/suggestions.
3327///
3328/// Returned path can be either absolute (for methods defined non-locally), or relative (for local
3329/// methods).
3330pub fn get_path_from_caller_to_method_type<'tcx>(
3331    tcx: TyCtxt<'tcx>,
3332    from: LocalDefId,
3333    method: DefId,
3334    args: GenericArgsRef<'tcx>,
3335) -> String {
3336    let assoc_item = tcx.associated_item(method);
3337    let def_id = assoc_item.container_id(tcx);
3338    match assoc_item.container {
3339        rustc_ty::AssocItemContainer::Trait => get_path_to_callee(tcx, from, def_id),
3340        rustc_ty::AssocItemContainer::Impl => {
3341            let ty = tcx.type_of(def_id).instantiate_identity();
3342            get_path_to_ty(tcx, from, ty, args)
3343        },
3344    }
3345}
3346
3347fn get_path_to_ty<'tcx>(tcx: TyCtxt<'tcx>, from: LocalDefId, ty: Ty<'tcx>, args: GenericArgsRef<'tcx>) -> String {
3348    match ty.kind() {
3349        rustc_ty::Adt(adt, _) => get_path_to_callee(tcx, from, adt.did()),
3350        // TODO these types need to be recursively resolved as well
3351        rustc_ty::Array(..)
3352        | rustc_ty::Dynamic(..)
3353        | rustc_ty::Never
3354        | rustc_ty::RawPtr(_, _)
3355        | rustc_ty::Ref(..)
3356        | rustc_ty::Slice(_)
3357        | rustc_ty::Tuple(_) => format!("<{}>", EarlyBinder::bind(ty).instantiate(tcx, args)),
3358        _ => ty.to_string(),
3359    }
3360}
3361
3362/// Produce a path from some local caller to the callee. Suitable for user output/suggestions.
3363fn get_path_to_callee(tcx: TyCtxt<'_>, from: LocalDefId, callee: DefId) -> String {
3364    // only search for a relative path if the call is fully local
3365    if callee.is_local() {
3366        let callee_path = tcx.def_path(callee);
3367        let caller_path = tcx.def_path(from.to_def_id());
3368        maybe_get_relative_path(&caller_path, &callee_path, 2)
3369    } else {
3370        tcx.def_path_str(callee)
3371    }
3372}
3373
3374/// Tries to produce a relative path from `from` to `to`; if such a path would contain more than
3375/// `max_super` `super` items, produces an absolute path instead. Both `from` and `to` should be in
3376/// the local crate.
3377///
3378/// Suitable for user output/suggestions.
3379///
3380/// This ignores use items, and assumes that the target path is visible from the source
3381/// path (which _should_ be a reasonable assumption since we in order to be able to use an object of
3382/// certain type T, T is required to be visible).
3383///
3384/// TODO make use of `use` items. Maybe we should have something more sophisticated like
3385/// rust-analyzer does? <https://docs.rs/ra_ap_hir_def/0.0.169/src/ra_ap_hir_def/find_path.rs.html#19-27>
3386fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> String {
3387    use itertools::EitherOrBoth::{Both, Left, Right};
3388
3389    // 1. skip the segments common for both paths (regardless of their type)
3390    let unique_parts = to
3391        .data
3392        .iter()
3393        .zip_longest(from.data.iter())
3394        .skip_while(|el| matches!(el, Both(l, r) if l == r))
3395        .map(|el| match el {
3396            Both(l, r) => Both(l.data, r.data),
3397            Left(l) => Left(l.data),
3398            Right(r) => Right(r.data),
3399        });
3400
3401    // 2. for the remaining segments, construct relative path using only mod names and `super`
3402    let mut go_up_by = 0;
3403    let mut path = Vec::new();
3404    for el in unique_parts {
3405        match el {
3406            Both(l, r) => {
3407                // consider:
3408                // a::b::sym:: ::    refers to
3409                // c::d::e  ::f::sym
3410                // result should be super::super::c::d::e::f
3411                //
3412                // alternatively:
3413                // a::b::c  ::d::sym refers to
3414                // e::f::sym:: ::
3415                // result should be super::super::super::super::e::f
3416                if let DefPathData::TypeNs(s) = l {
3417                    path.push(s.to_string());
3418                }
3419                if let DefPathData::TypeNs(_) = r {
3420                    go_up_by += 1;
3421                }
3422            },
3423            // consider:
3424            // a::b::sym:: ::    refers to
3425            // c::d::e  ::f::sym
3426            // when looking at `f`
3427            Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
3428            // consider:
3429            // a::b::c  ::d::sym refers to
3430            // e::f::sym:: ::
3431            // when looking at `d`
3432            Right(DefPathData::TypeNs(_)) => go_up_by += 1,
3433            _ => {},
3434        }
3435    }
3436
3437    if go_up_by > max_super {
3438        // `super` chain would be too long, just use the absolute path instead
3439        once(String::from("crate"))
3440            .chain(to.data.iter().filter_map(|el| {
3441                if let DefPathData::TypeNs(sym) = el.data {
3442                    Some(sym.to_string())
3443                } else {
3444                    None
3445                }
3446            }))
3447            .join("::")
3448    } else {
3449        repeat_n(String::from("super"), go_up_by).chain(path).join("::")
3450    }
3451}
3452
3453/// Returns true if the specified `HirId` is the top-level expression of a statement or the only
3454/// expression in a block.
3455pub fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
3456    matches!(
3457        cx.tcx.parent_hir_node(id),
3458        Node::Stmt(..) | Node::Block(Block { stmts: [], .. })
3459    )
3460}
3461
3462/// Returns true if the given `expr` is a block or resembled as a block,
3463/// such as `if`, `loop`, `match` expressions etc.
3464pub fn is_block_like(expr: &Expr<'_>) -> bool {
3465    matches!(
3466        expr.kind,
3467        ExprKind::Block(..) | ExprKind::ConstBlock(..) | ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..)
3468    )
3469}
3470
3471/// Returns true if the given `expr` is binary expression that needs to be wrapped in parentheses.
3472pub fn binary_expr_needs_parentheses(expr: &Expr<'_>) -> bool {
3473    fn contains_block(expr: &Expr<'_>, is_operand: bool) -> bool {
3474        match expr.kind {
3475            ExprKind::Binary(_, lhs, _) => contains_block(lhs, true),
3476            _ if is_block_like(expr) => is_operand,
3477            _ => false,
3478        }
3479    }
3480
3481    contains_block(expr, false)
3482}
3483
3484/// Returns true if the specified expression is in a receiver position.
3485pub fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
3486    if let Some(parent_expr) = get_parent_expr(cx, expr)
3487        && let ExprKind::MethodCall(_, receiver, ..) = parent_expr.kind
3488        && receiver.hir_id == expr.hir_id
3489    {
3490        return true;
3491    }
3492    false
3493}
3494
3495/// Returns true if `expr` creates any temporary whose type references a non-static lifetime and has
3496/// a significant drop and does not consume it.
3497pub fn leaks_droppable_temporary_with_limited_lifetime<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
3498    for_each_unconsumed_temporary(cx, expr, |temporary_ty| {
3499        if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env())
3500            && temporary_ty
3501                .walk()
3502                .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
3503        {
3504            ControlFlow::Break(())
3505        } else {
3506            ControlFlow::Continue(())
3507        }
3508    })
3509    .is_break()
3510}