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