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