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