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