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