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