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