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