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