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