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