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