]> git.lizzy.rs Git - rust.git/blob - clippy_utils/src/lib.rs
Fix suspicious_map false positives
[rust.git] / clippy_utils / src / lib.rs
1 #![feature(box_patterns)]
2 #![feature(in_band_lifetimes)]
3 #![feature(or_patterns)]
4 #![feature(rustc_private)]
5 #![recursion_limit = "512"]
6 #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
7
8 // FIXME: switch to something more ergonomic here, once available.
9 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
10 extern crate rustc_ast;
11 extern crate rustc_ast_pretty;
12 extern crate rustc_data_structures;
13 extern crate rustc_errors;
14 extern crate rustc_hir;
15 extern crate rustc_hir_pretty;
16 extern crate rustc_infer;
17 extern crate rustc_lexer;
18 extern crate rustc_lint;
19 extern crate rustc_middle;
20 extern crate rustc_mir;
21 extern crate rustc_session;
22 extern crate rustc_span;
23 extern crate rustc_target;
24 extern crate rustc_trait_selection;
25 extern crate rustc_typeck;
26
27 #[macro_use]
28 pub mod sym_helper;
29
30 #[allow(clippy::module_name_repetitions)]
31 pub mod ast_utils;
32 pub mod attrs;
33 pub mod camel_case;
34 pub mod comparisons;
35 pub mod consts;
36 mod diagnostics;
37 pub mod eager_or_lazy;
38 pub mod higher;
39 mod hir_utils;
40 pub mod numeric_literal;
41 pub mod paths;
42 pub mod ptr;
43 pub mod qualify_min_const_fn;
44 pub mod sugg;
45 pub mod usage;
46 pub mod visitors;
47
48 pub use self::attrs::*;
49 pub use self::diagnostics::*;
50 pub use self::hir_utils::{both, eq_expr_value, over, SpanlessEq, SpanlessHash};
51
52 use std::borrow::Cow;
53 use std::collections::hash_map::Entry;
54 use std::hash::BuildHasherDefault;
55
56 use if_chain::if_chain;
57 use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind, Mutability};
58 use rustc_data_structures::fx::FxHashMap;
59 use rustc_errors::Applicability;
60 use rustc_hir as hir;
61 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
62 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
63 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
64 use rustc_hir::{
65     def, Arm, BindingAnnotation, Block, Body, Constness, CrateItem, Expr, ExprKind, FnDecl, ForeignItem, GenericArgs,
66     GenericParam, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, LangItem, Lifetime, Local, MacroDef,
67     MatchSource, Node, Param, Pat, PatKind, Path, PathSegment, QPath, Stmt, StructField, TraitItem, TraitItemKind,
68     TraitRef, TyKind, Unsafety, Variant, Visibility,
69 };
70 use rustc_infer::infer::TyCtxtInferExt;
71 use rustc_lint::{LateContext, Level, Lint, LintContext};
72 use rustc_middle::hir::exports::Export;
73 use rustc_middle::hir::map::Map;
74 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
75 use rustc_middle::ty::{self, layout::IntegerExt, DefIdTree, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
76 use rustc_semver::RustcVersion;
77 use rustc_session::Session;
78 use rustc_span::hygiene::{self, ExpnKind, MacroKind};
79 use rustc_span::source_map::original_sp;
80 use rustc_span::sym;
81 use rustc_span::symbol::{kw, Ident, Symbol};
82 use rustc_span::{BytePos, Pos, Span, SyntaxContext, DUMMY_SP};
83 use rustc_target::abi::Integer;
84 use rustc_trait_selection::traits::query::normalize::AtExt;
85 use smallvec::SmallVec;
86
87 use crate::consts::{constant, Constant};
88 use std::collections::HashMap;
89
90 pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
91     if let Ok(version) = RustcVersion::parse(msrv) {
92         return Some(version);
93     } else if let Some(sess) = sess {
94         if let Some(span) = span {
95             sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
96         }
97     }
98     None
99 }
100
101 pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool {
102     msrv.map_or(true, |msrv| msrv.meets(*lint_msrv))
103 }
104
105 #[macro_export]
106 macro_rules! extract_msrv_attr {
107     (LateContext) => {
108         extract_msrv_attr!(@LateContext, ());
109     };
110     (EarlyContext) => {
111         extract_msrv_attr!(@EarlyContext);
112     };
113     (@$context:ident$(, $call:tt)?) => {
114         fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'tcx>, attrs: &'tcx [rustc_ast::ast::Attribute]) {
115             use $crate::get_unique_inner_attr;
116             match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") {
117                 Some(msrv_attr) => {
118                     if let Some(msrv) = msrv_attr.value_str() {
119                         self.msrv = $crate::parse_msrv(
120                             &msrv.to_string(),
121                             Some(cx.sess$($call)?),
122                             Some(msrv_attr.span),
123                         );
124                     } else {
125                         cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute");
126                     }
127                 },
128                 _ => (),
129             }
130         }
131     };
132 }
133
134 /// Returns `true` if the two spans come from differing expansions (i.e., one is
135 /// from a macro and one isn't).
136 #[must_use]
137 pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
138     rhs.ctxt() != lhs.ctxt()
139 }
140
141 /// If the given expression is a local binding, find the initializer expression.
142 /// If that initializer expression is another local binding, find its initializer again.
143 /// This process repeats as long as possible (but usually no more than once). Initializer
144 /// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
145 /// instead.
146 ///
147 /// Examples:
148 /// ```ignore
149 /// let abc = 1;
150 /// //        ^ output
151 /// let def = abc;
152 /// dbg!(def)
153 /// //   ^^^ input
154 ///
155 /// // or...
156 /// let abc = 1;
157 /// let def = abc + 2;
158 /// //        ^^^^^^^ output
159 /// dbg!(def)
160 /// //   ^^^ input
161 /// ```
162 pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
163     while let Some(init) = path_to_local(expr)
164         .and_then(|id| find_binding_init(cx, id))
165         .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
166     {
167         expr = init;
168     }
169     expr
170 }
171
172 /// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
173 /// By only considering immutable bindings, we guarantee that the returned expression represents the
174 /// value of the binding wherever it is referenced.
175 ///
176 /// Example:
177 /// ```ignore
178 /// let abc = 1;
179 /// //        ^ output
180 /// dbg!(abc)
181 /// //   ^^^ input
182 /// ```
183 pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
184     let hir = cx.tcx.hir();
185     if_chain! {
186         if let Some(Node::Binding(pat)) = hir.find(hir_id);
187         if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..));
188         let parent = hir.get_parent_node(hir_id);
189         if let Some(Node::Local(local)) = hir.find(parent);
190         then {
191             return local.init;
192         }
193     }
194     None
195 }
196
197 /// Returns `true` if the given `NodeId` is inside a constant context
198 ///
199 /// # Example
200 ///
201 /// ```rust,ignore
202 /// if in_constant(cx, expr.hir_id) {
203 ///     // Do something
204 /// }
205 /// ```
206 pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
207     let parent_id = cx.tcx.hir().get_parent_item(id);
208     match cx.tcx.hir().get(parent_id) {
209         Node::Item(&Item {
210             kind: ItemKind::Const(..) | ItemKind::Static(..),
211             ..
212         })
213         | Node::TraitItem(&TraitItem {
214             kind: TraitItemKind::Const(..),
215             ..
216         })
217         | Node::ImplItem(&ImplItem {
218             kind: ImplItemKind::Const(..),
219             ..
220         })
221         | Node::AnonConst(_) => true,
222         Node::Item(&Item {
223             kind: ItemKind::Fn(ref sig, ..),
224             ..
225         })
226         | Node::ImplItem(&ImplItem {
227             kind: ImplItemKind::Fn(ref sig, _),
228             ..
229         }) => sig.header.constness == Constness::Const,
230         _ => false,
231     }
232 }
233
234 /// Returns `true` if this `span` was expanded by any macro.
235 #[must_use]
236 pub fn in_macro(span: Span) -> bool {
237     if span.from_expansion() {
238         !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
239     } else {
240         false
241     }
242 }
243
244 // If the snippet is empty, it's an attribute that was inserted during macro
245 // expansion and we want to ignore those, because they could come from external
246 // sources that the user has no control over.
247 // For some reason these attributes don't have any expansion info on them, so
248 // we have to check it this way until there is a better way.
249 pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
250     if let Some(snippet) = snippet_opt(cx, span) {
251         if snippet.is_empty() {
252             return false;
253         }
254     }
255     true
256 }
257
258 /// Checks if given pattern is a wildcard (`_`)
259 pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool {
260     matches!(pat.kind, PatKind::Wild)
261 }
262
263 /// Checks if type is struct, enum or union type with the given def path.
264 ///
265 /// If the type is a diagnostic item, use `is_type_diagnostic_item` instead.
266 /// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
267 pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool {
268     match ty.kind() {
269         ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
270         _ => false,
271     }
272 }
273
274 /// Checks if the type is equal to a diagnostic item
275 ///
276 /// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
277 pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
278     match ty.kind() {
279         ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
280         _ => false,
281     }
282 }
283
284 /// Checks if the type is equal to a lang item
285 pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
286     match ty.kind() {
287         ty::Adt(adt, _) => cx.tcx.lang_items().require(lang_item).unwrap() == adt.did,
288         _ => false,
289     }
290 }
291
292 /// Checks if the first type parameter is a lang item.
293 pub fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> {
294     let ty = get_qpath_generic_tys(qpath).next()?;
295
296     if let TyKind::Path(qpath) = &ty.kind {
297         cx.qpath_res(qpath, ty.hir_id)
298             .opt_def_id()
299             .map_or(false, |id| {
300                 cx.tcx.lang_items().require(item).map_or(false, |lang_id| id == lang_id)
301             })
302             .then(|| ty)
303     } else {
304         None
305     }
306 }
307
308 /// Checks if the first type parameter is a diagnostic item.
309 pub fn is_ty_param_diagnostic_item(
310     cx: &LateContext<'_>,
311     qpath: &QPath<'tcx>,
312     item: Symbol,
313 ) -> Option<&'tcx hir::Ty<'tcx>> {
314     let ty = get_qpath_generic_tys(qpath).next()?;
315
316     if let TyKind::Path(qpath) = &ty.kind {
317         cx.qpath_res(qpath, ty.hir_id)
318             .opt_def_id()
319             .map_or(false, |id| cx.tcx.is_diagnostic_item(item, id))
320             .then(|| ty)
321     } else {
322         None
323     }
324 }
325
326 /// Return `true` if the passed `typ` is `isize` or `usize`.
327 pub fn is_isize_or_usize(typ: Ty<'_>) -> bool {
328     matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize))
329 }
330
331 /// Checks if the method call given in `expr` belongs to the given trait.
332 /// This is a deprecated function, consider using [`is_trait_method`].
333 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
334     let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
335     let trt_id = cx.tcx.trait_of_item(def_id);
336     trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path))
337 }
338
339 /// Checks if the method call given in `def_id` belongs to a trait or other container with a given
340 /// diagnostic item
341 pub fn is_diagnostic_assoc_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
342     cx.tcx
343         .opt_associated_item(def_id)
344         .and_then(|associated_item| match associated_item.container {
345             ty::TraitContainer(assoc_def_id) => Some(assoc_def_id),
346             ty::ImplContainer(assoc_def_id) => match cx.tcx.type_of(assoc_def_id).kind() {
347                 ty::Adt(adt, _) => Some(adt.did),
348                 ty::Slice(_) => cx.tcx.get_diagnostic_item(sym::slice), // this isn't perfect but it works
349                 _ => None,
350             },
351         })
352         .map_or(false, |assoc_def_id| cx.tcx.is_diagnostic_item(diag_item, assoc_def_id))
353 }
354
355 /// Checks if the method call given in `expr` belongs to the given trait.
356 pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
357     cx.typeck_results()
358         .type_dependent_def_id(expr.hir_id)
359         .map_or(false, |did| is_diagnostic_assoc_item(cx, did, diag_item))
360 }
361
362 /// Checks if an expression references a variable of the given name.
363 pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool {
364     if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
365         if let [p] = path.segments {
366             return p.ident.name == var;
367         }
368     }
369     false
370 }
371
372 pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
373     match *path {
374         QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"),
375         QPath::TypeRelative(_, ref seg) => seg,
376         QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
377     }
378 }
379
380 pub fn get_qpath_generics(path: &QPath<'tcx>) -> Option<&'tcx GenericArgs<'tcx>> {
381     match path {
382         QPath::Resolved(_, p) => p.segments.last().and_then(|s| s.args),
383         QPath::TypeRelative(_, s) => s.args,
384         QPath::LangItem(..) => None,
385     }
386 }
387
388 pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
389     get_qpath_generics(path)
390         .map_or([].as_ref(), |a| a.args)
391         .iter()
392         .filter_map(|a| {
393             if let hir::GenericArg::Type(ty) = a {
394                 Some(ty)
395             } else {
396                 None
397             }
398         })
399 }
400
401 pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
402     match *path {
403         QPath::Resolved(_, ref path) => path.segments.get(0),
404         QPath::TypeRelative(_, ref seg) => Some(seg),
405         QPath::LangItem(..) => None,
406     }
407 }
408
409 /// Matches a `QPath` against a slice of segment string literals.
410 ///
411 /// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a
412 /// `rustc_hir::QPath`.
413 ///
414 /// # Examples
415 /// ```rust,ignore
416 /// match_qpath(path, &["std", "rt", "begin_unwind"])
417 /// ```
418 pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
419     match *path {
420         QPath::Resolved(_, ref path) => match_path(path, segments),
421         QPath::TypeRelative(ref ty, ref segment) => match ty.kind {
422             TyKind::Path(ref inner_path) => {
423                 if let [prefix @ .., end] = segments {
424                     if match_qpath(inner_path, prefix) {
425                         return segment.ident.name.as_str() == *end;
426                     }
427                 }
428                 false
429             },
430             _ => false,
431         },
432         QPath::LangItem(..) => false,
433     }
434 }
435
436 /// Matches a `Path` against a slice of segment string literals.
437 ///
438 /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a
439 /// `rustc_hir::Path`.
440 ///
441 /// # Examples
442 ///
443 /// ```rust,ignore
444 /// if match_path(&trait_ref.path, &paths::HASH) {
445 ///     // This is the `std::hash::Hash` trait.
446 /// }
447 ///
448 /// if match_path(ty_path, &["rustc", "lint", "Lint"]) {
449 ///     // This is a `rustc_middle::lint::Lint`.
450 /// }
451 /// ```
452 pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
453     path.segments
454         .iter()
455         .rev()
456         .zip(segments.iter().rev())
457         .all(|(a, b)| a.ident.name.as_str() == *b)
458 }
459
460 /// Matches a `Path` against a slice of segment string literals, e.g.
461 ///
462 /// # Examples
463 /// ```rust,ignore
464 /// match_path_ast(path, &["std", "rt", "begin_unwind"])
465 /// ```
466 pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
467     path.segments
468         .iter()
469         .rev()
470         .zip(segments.iter().rev())
471         .all(|(a, b)| a.ident.name.as_str() == *b)
472 }
473
474 /// If the expression is a path to a local, returns the canonical `HirId` of the local.
475 pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
476     if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
477         if let Res::Local(id) = path.res {
478             return Some(id);
479         }
480     }
481     None
482 }
483
484 /// Returns true if the expression is a path to a local with the specified `HirId`.
485 /// Use this function to see if an expression matches a function argument or a match binding.
486 pub fn path_to_local_id(expr: &Expr<'_>, id: HirId) -> bool {
487     path_to_local(expr) == Some(id)
488 }
489
490 /// Gets the definition associated to a path.
491 #[allow(clippy::shadow_unrelated)] // false positive #6563
492 pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
493     macro_rules! try_res {
494         ($e:expr) => {
495             match $e {
496                 Some(e) => e,
497                 None => return Res::Err,
498             }
499         };
500     }
501     fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
502         tcx.item_children(def_id)
503             .iter()
504             .find(|item| item.ident.name.as_str() == name)
505     }
506
507     let (krate, first, path) = match *path {
508         [krate, first, ref path @ ..] => (krate, first, path),
509         _ => return Res::Err,
510     };
511     let tcx = cx.tcx;
512     let crates = tcx.crates();
513     let krate = try_res!(crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate));
514     let first = try_res!(item_child_by_name(tcx, krate.as_def_id(), first));
515     let last = path
516         .iter()
517         .copied()
518         // `get_def_path` seems to generate these empty segments for extern blocks.
519         // We can just ignore them.
520         .filter(|segment| !segment.is_empty())
521         // for each segment, find the child item
522         .try_fold(first, |item, segment| {
523             let def_id = item.res.def_id();
524             if let Some(item) = item_child_by_name(tcx, def_id, segment) {
525                 Some(item)
526             } else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
527                 // it is not a child item so check inherent impl items
528                 tcx.inherent_impls(def_id)
529                     .iter()
530                     .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
531             } else {
532                 None
533             }
534         });
535     try_res!(last).res
536 }
537
538 /// Convenience function to get the `DefId` of a trait by path.
539 /// It could be a trait or trait alias.
540 pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
541     match path_to_res(cx, path) {
542         Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
543         _ => None,
544     }
545 }
546
547 /// Checks whether a type implements a trait.
548 /// See also `get_trait_def_id`.
549 pub fn implements_trait<'tcx>(
550     cx: &LateContext<'tcx>,
551     ty: Ty<'tcx>,
552     trait_id: DefId,
553     ty_params: &[GenericArg<'tcx>],
554 ) -> bool {
555     // Do not check on infer_types to avoid panic in evaluate_obligation.
556     if ty.has_infer_types() {
557         return false;
558     }
559     let ty = cx.tcx.erase_regions(ty);
560     if ty.has_escaping_bound_vars() {
561         return false;
562     }
563     let ty_params = cx.tcx.mk_substs(ty_params.iter());
564     cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env))
565 }
566
567 /// Gets the `hir::TraitRef` of the trait the given method is implemented for.
568 ///
569 /// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
570 ///
571 /// ```rust
572 /// struct Point(isize, isize);
573 ///
574 /// impl std::ops::Add for Point {
575 ///     type Output = Self;
576 ///
577 ///     fn add(self, other: Self) -> Self {
578 ///         Point(0, 0)
579 ///     }
580 /// }
581 /// ```
582 pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> {
583     // Get the implemented trait for the current function
584     let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
585     if_chain! {
586         if parent_impl != hir::CRATE_HIR_ID;
587         if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
588         if let hir::ItemKind::Impl(impl_) = &item.kind;
589         then { return impl_.of_trait.as_ref(); }
590     }
591     None
592 }
593
594 /// Checks whether this type implements `Drop`.
595 pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
596     match ty.ty_adt_def() {
597         Some(def) => def.has_dtor(cx.tcx),
598         None => false,
599     }
600 }
601
602 /// Checks whether a type can be partially moved.
603 pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
604     if has_drop(cx, ty) || is_copy(cx, ty) {
605         return false;
606     }
607     match ty.kind() {
608         ty::Param(_) => false,
609         ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs))),
610         _ => true,
611     }
612 }
613
614 /// Returns the method names and argument list of nested method call expressions that make up
615 /// `expr`. method/span lists are sorted with the most recent call first.
616 pub fn method_calls<'tcx>(
617     expr: &'tcx Expr<'tcx>,
618     max_depth: usize,
619 ) -> (Vec<Symbol>, Vec<&'tcx [Expr<'tcx>]>, Vec<Span>) {
620     let mut method_names = Vec::with_capacity(max_depth);
621     let mut arg_lists = Vec::with_capacity(max_depth);
622     let mut spans = Vec::with_capacity(max_depth);
623
624     let mut current = expr;
625     for _ in 0..max_depth {
626         if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
627             if args.iter().any(|e| e.span.from_expansion()) {
628                 break;
629             }
630             method_names.push(path.ident.name);
631             arg_lists.push(&**args);
632             spans.push(*span);
633             current = &args[0];
634         } else {
635             break;
636         }
637     }
638
639     (method_names, arg_lists, spans)
640 }
641
642 /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
643 ///
644 /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
645 /// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
646 /// containing the `Expr`s for
647 /// `.bar()` and `.baz()`
648 pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
649     let mut current = expr;
650     let mut matched = Vec::with_capacity(methods.len());
651     for method_name in methods.iter().rev() {
652         // method chains are stored last -> first
653         if let ExprKind::MethodCall(ref path, _, ref args, _) = current.kind {
654             if path.ident.name.as_str() == *method_name {
655                 if args.iter().any(|e| e.span.from_expansion()) {
656                     return None;
657                 }
658                 matched.push(&**args); // build up `matched` backwards
659                 current = &args[0] // go to parent expression
660             } else {
661                 return None;
662             }
663         } else {
664             return None;
665         }
666     }
667     // Reverse `matched` so that it is in the same order as `methods`.
668     matched.reverse();
669     Some(matched)
670 }
671
672 /// Returns `true` if the provided `def_id` is an entrypoint to a program.
673 pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
674     cx.tcx
675         .entry_fn(LOCAL_CRATE)
676         .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id.to_def_id())
677 }
678
679 /// Returns `true` if the expression is in the program's `#[panic_handler]`.
680 pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
681     let parent = cx.tcx.hir().get_parent_item(e.hir_id);
682     let def_id = cx.tcx.hir().local_def_id(parent).to_def_id();
683     Some(def_id) == cx.tcx.lang_items().panic_impl()
684 }
685
686 /// Gets the name of the item the expression is in, if available.
687 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
688     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
689     match cx.tcx.hir().find(parent_id) {
690         Some(
691             Node::Item(Item { ident, .. })
692             | Node::TraitItem(TraitItem { ident, .. })
693             | Node::ImplItem(ImplItem { ident, .. }),
694         ) => Some(ident.name),
695         _ => None,
696     }
697 }
698
699 /// Gets the name of a `Pat`, if any.
700 pub fn get_pat_name(pat: &Pat<'_>) -> Option<Symbol> {
701     match pat.kind {
702         PatKind::Binding(.., ref spname, _) => Some(spname.name),
703         PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
704         PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p),
705         _ => None,
706     }
707 }
708
709 struct ContainsName {
710     name: Symbol,
711     result: bool,
712 }
713
714 impl<'tcx> Visitor<'tcx> for ContainsName {
715     type Map = Map<'tcx>;
716
717     fn visit_name(&mut self, _: Span, name: Symbol) {
718         if self.name == name {
719             self.result = true;
720         }
721     }
722     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
723         NestedVisitorMap::None
724     }
725 }
726
727 /// Checks if an `Expr` contains a certain name.
728 pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
729     let mut cn = ContainsName { name, result: false };
730     cn.visit_expr(expr);
731     cn.result
732 }
733
734 /// Returns `true` if `expr` contains a return expression
735 pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
736     struct RetCallFinder {
737         found: bool,
738     }
739
740     impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder {
741         type Map = Map<'tcx>;
742
743         fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
744             if self.found {
745                 return;
746             }
747             if let hir::ExprKind::Ret(..) = &expr.kind {
748                 self.found = true;
749             } else {
750                 hir::intravisit::walk_expr(self, expr);
751             }
752         }
753
754         fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
755             hir::intravisit::NestedVisitorMap::None
756         }
757     }
758
759     let mut visitor = RetCallFinder { found: false };
760     visitor.visit_expr(expr);
761     visitor.found
762 }
763
764 struct FindMacroCalls<'a, 'b> {
765     names: &'a [&'b str],
766     result: Vec<Span>,
767 }
768
769 impl<'a, 'b, 'tcx> Visitor<'tcx> for FindMacroCalls<'a, 'b> {
770     type Map = Map<'tcx>;
771
772     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
773         if self.names.iter().any(|fun| is_expn_of(expr.span, fun).is_some()) {
774             self.result.push(expr.span);
775         }
776         // and check sub-expressions
777         intravisit::walk_expr(self, expr);
778     }
779
780     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
781         NestedVisitorMap::None
782     }
783 }
784
785 /// Finds calls of the specified macros in a function body.
786 pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> {
787     let mut fmc = FindMacroCalls {
788         names,
789         result: Vec::new(),
790     };
791     fmc.visit_expr(&body.value);
792     fmc.result
793 }
794
795 /// Converts a span to a code snippet if available, otherwise use default.
796 ///
797 /// This is useful if you want to provide suggestions for your lint or more generally, if you want
798 /// to convert a given `Span` to a `str`.
799 ///
800 /// # Example
801 /// ```rust,ignore
802 /// snippet(cx, expr.span, "..")
803 /// ```
804 pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
805     snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
806 }
807
808 /// Same as `snippet`, but it adapts the applicability level by following rules:
809 ///
810 /// - Applicability level `Unspecified` will never be changed.
811 /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
812 /// - If the default value is used and the applicability level is `MachineApplicable`, change it to
813 /// `HasPlaceholders`
814 pub fn snippet_with_applicability<'a, T: LintContext>(
815     cx: &T,
816     span: Span,
817     default: &'a str,
818     applicability: &mut Applicability,
819 ) -> Cow<'a, str> {
820     if *applicability != Applicability::Unspecified && span.from_expansion() {
821         *applicability = Applicability::MaybeIncorrect;
822     }
823     snippet_opt(cx, span).map_or_else(
824         || {
825             if *applicability == Applicability::MachineApplicable {
826                 *applicability = Applicability::HasPlaceholders;
827             }
828             Cow::Borrowed(default)
829         },
830         From::from,
831     )
832 }
833
834 /// Same as `snippet`, but should only be used when it's clear that the input span is
835 /// not a macro argument.
836 pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
837     snippet(cx, span.source_callsite(), default)
838 }
839
840 /// Converts a span to a code snippet. Returns `None` if not available.
841 pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
842     cx.sess().source_map().span_to_snippet(span).ok()
843 }
844
845 /// Converts a span (from a block) to a code snippet if available, otherwise use default.
846 ///
847 /// This trims the code of indentation, except for the first line. Use it for blocks or block-like
848 /// things which need to be printed as such.
849 ///
850 /// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the
851 /// resulting snippet of the given span.
852 ///
853 /// # Example
854 ///
855 /// ```rust,ignore
856 /// snippet_block(cx, block.span, "..", None)
857 /// // where, `block` is the block of the if expr
858 ///     if x {
859 ///         y;
860 ///     }
861 /// // will return the snippet
862 /// {
863 ///     y;
864 /// }
865 /// ```
866 ///
867 /// ```rust,ignore
868 /// snippet_block(cx, block.span, "..", Some(if_expr.span))
869 /// // where, `block` is the block of the if expr
870 ///     if x {
871 ///         y;
872 ///     }
873 /// // will return the snippet
874 /// {
875 ///         y;
876 ///     } // aligned with `if`
877 /// ```
878 /// Note that the first line of the snippet always has 0 indentation.
879 pub fn snippet_block<'a, T: LintContext>(
880     cx: &T,
881     span: Span,
882     default: &'a str,
883     indent_relative_to: Option<Span>,
884 ) -> Cow<'a, str> {
885     let snip = snippet(cx, span, default);
886     let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
887     reindent_multiline(snip, true, indent)
888 }
889
890 /// Same as `snippet_block`, but adapts the applicability level by the rules of
891 /// `snippet_with_applicability`.
892 pub fn snippet_block_with_applicability<'a, T: LintContext>(
893     cx: &T,
894     span: Span,
895     default: &'a str,
896     indent_relative_to: Option<Span>,
897     applicability: &mut Applicability,
898 ) -> Cow<'a, str> {
899     let snip = snippet_with_applicability(cx, span, default, applicability);
900     let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
901     reindent_multiline(snip, true, indent)
902 }
903
904 /// Same as `snippet_with_applicability`, but first walks the span up to the given context. This
905 /// will result in the macro call, rather then the expansion, if the span is from a child context.
906 /// If the span is not from a child context, it will be used directly instead.
907 ///
908 /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node
909 /// would result in `box []`. If given the context of the address of expression, this function will
910 /// correctly get a snippet of `vec![]`.
911 ///
912 /// This will also return whether or not the snippet is a macro call.
913 pub fn snippet_with_context(
914     cx: &LateContext<'_>,
915     span: Span,
916     outer: SyntaxContext,
917     default: &'a str,
918     applicability: &mut Applicability,
919 ) -> (Cow<'a, str>, bool) {
920     let outer_span = hygiene::walk_chain(span, outer);
921     let (span, is_macro_call) = if outer_span.ctxt() == outer {
922         (outer_span, span.ctxt() != outer)
923     } else {
924         // The span is from a macro argument, and the outer context is the macro using the argument
925         if *applicability != Applicability::Unspecified {
926             *applicability = Applicability::MaybeIncorrect;
927         }
928         // TODO: get the argument span.
929         (span, false)
930     };
931
932     (
933         snippet_with_applicability(cx, span, default, applicability),
934         is_macro_call,
935     )
936 }
937
938 /// Returns a new Span that extends the original Span to the first non-whitespace char of the first
939 /// line.
940 ///
941 /// ```rust,ignore
942 ///     let x = ();
943 /// //          ^^
944 /// // will be converted to
945 ///     let x = ();
946 /// //  ^^^^^^^^^^
947 /// ```
948 pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
949     first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
950 }
951
952 fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
953     let line_span = line_span(cx, span);
954     snippet_opt(cx, line_span).and_then(|snip| {
955         snip.find(|c: char| !c.is_whitespace())
956             .map(|pos| line_span.lo() + BytePos::from_usize(pos))
957     })
958 }
959
960 /// Returns the indentation of the line of a span
961 ///
962 /// ```rust,ignore
963 /// let x = ();
964 /// //      ^^ -- will return 0
965 ///     let x = ();
966 /// //          ^^ -- will return 4
967 /// ```
968 pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
969     snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
970 }
971
972 /// Returns the positon just before rarrow
973 ///
974 /// ```rust,ignore
975 /// fn into(self) -> () {}
976 ///              ^
977 /// // in case of unformatted code
978 /// fn into2(self)-> () {}
979 ///               ^
980 /// fn into3(self)   -> () {}
981 ///               ^
982 /// ```
983 pub fn position_before_rarrow(s: &str) -> Option<usize> {
984     s.rfind("->").map(|rpos| {
985         let mut rpos = rpos;
986         let chars: Vec<char> = s.chars().collect();
987         while rpos > 1 {
988             if let Some(c) = chars.get(rpos - 1) {
989                 if c.is_whitespace() {
990                     rpos -= 1;
991                     continue;
992                 }
993             }
994             break;
995         }
996         rpos
997     })
998 }
999
1000 /// Extends the span to the beginning of the spans line, incl. whitespaces.
1001 ///
1002 /// ```rust,ignore
1003 ///        let x = ();
1004 /// //             ^^
1005 /// // will be converted to
1006 ///        let x = ();
1007 /// // ^^^^^^^^^^^^^^
1008 /// ```
1009 fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
1010     let span = original_sp(span, DUMMY_SP);
1011     let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
1012     let line_no = source_map_and_line.line;
1013     let line_start = source_map_and_line.sf.lines[line_no];
1014     Span::new(line_start, span.hi(), span.ctxt())
1015 }
1016
1017 /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
1018 /// Also takes an `Option<String>` which can be put inside the braces.
1019 pub fn expr_block<'a, T: LintContext>(
1020     cx: &T,
1021     expr: &Expr<'_>,
1022     option: Option<String>,
1023     default: &'a str,
1024     indent_relative_to: Option<Span>,
1025 ) -> Cow<'a, str> {
1026     let code = snippet_block(cx, expr.span, default, indent_relative_to);
1027     let string = option.unwrap_or_default();
1028     if expr.span.from_expansion() {
1029         Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
1030     } else if let ExprKind::Block(_, _) = expr.kind {
1031         Cow::Owned(format!("{}{}", code, string))
1032     } else if string.is_empty() {
1033         Cow::Owned(format!("{{ {} }}", code))
1034     } else {
1035         Cow::Owned(format!("{{\n{};\n{}\n}}", code, string))
1036     }
1037 }
1038
1039 /// Reindent a multiline string with possibility of ignoring the first line.
1040 #[allow(clippy::needless_pass_by_value)]
1041 pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> {
1042     let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' ');
1043     let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t');
1044     reindent_multiline_inner(&s_tab, ignore_first, indent, ' ').into()
1045 }
1046
1047 fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>, ch: char) -> String {
1048     let x = s
1049         .lines()
1050         .skip(ignore_first as usize)
1051         .filter_map(|l| {
1052             if l.is_empty() {
1053                 None
1054             } else {
1055                 // ignore empty lines
1056                 Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0)
1057             }
1058         })
1059         .min()
1060         .unwrap_or(0);
1061     let indent = indent.unwrap_or(0);
1062     s.lines()
1063         .enumerate()
1064         .map(|(i, l)| {
1065             if (ignore_first && i == 0) || l.is_empty() {
1066                 l.to_owned()
1067             } else if x > indent {
1068                 l.split_at(x - indent).1.to_owned()
1069             } else {
1070                 " ".repeat(indent - x) + l
1071             }
1072         })
1073         .collect::<Vec<String>>()
1074         .join("\n")
1075 }
1076
1077 /// Gets the span of the node, if there is one.
1078 pub fn get_node_span(node: Node<'_>) -> Option<Span> {
1079     match node {
1080         Node::Param(Param { span, .. })
1081         | Node::Item(Item { span, .. })
1082         | Node::ForeignItem(ForeignItem { span, .. })
1083         | Node::TraitItem(TraitItem { span, .. })
1084         | Node::ImplItem(ImplItem { span, .. })
1085         | Node::Variant(Variant { span, .. })
1086         | Node::Field(StructField { span, .. })
1087         | Node::Expr(Expr { span, .. })
1088         | Node::Stmt(Stmt { span, .. })
1089         | Node::PathSegment(PathSegment {
1090             ident: Ident { span, .. },
1091             ..
1092         })
1093         | Node::Ty(hir::Ty { span, .. })
1094         | Node::TraitRef(TraitRef {
1095             path: Path { span, .. },
1096             ..
1097         })
1098         | Node::Binding(Pat { span, .. })
1099         | Node::Pat(Pat { span, .. })
1100         | Node::Arm(Arm { span, .. })
1101         | Node::Block(Block { span, .. })
1102         | Node::Local(Local { span, .. })
1103         | Node::MacroDef(MacroDef { span, .. })
1104         | Node::Lifetime(Lifetime { span, .. })
1105         | Node::GenericParam(GenericParam { span, .. })
1106         | Node::Visibility(Visibility { span, .. })
1107         | Node::Crate(CrateItem { span, .. }) => Some(*span),
1108         Node::Ctor(_) | Node::AnonConst(_) => None,
1109     }
1110 }
1111
1112 /// Gets the parent node, if any.
1113 pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
1114     tcx.hir().parent_iter(id).next().map(|(_, node)| node)
1115 }
1116
1117 /// Gets the parent expression, if any â€“- this is useful to constrain a lint.
1118 pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1119     match get_parent_node(cx.tcx, e.hir_id) {
1120         Some(Node::Expr(parent)) => Some(parent),
1121         _ => None,
1122     }
1123 }
1124
1125 pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
1126     let map = &cx.tcx.hir();
1127     let enclosing_node = map
1128         .get_enclosing_scope(hir_id)
1129         .and_then(|enclosing_id| map.find(enclosing_id));
1130     enclosing_node.and_then(|node| match node {
1131         Node::Block(block) => Some(block),
1132         Node::Item(&Item {
1133             kind: ItemKind::Fn(_, _, eid),
1134             ..
1135         })
1136         | Node::ImplItem(&ImplItem {
1137             kind: ImplItemKind::Fn(_, eid),
1138             ..
1139         }) => match cx.tcx.hir().body(eid).value.kind {
1140             ExprKind::Block(ref block, _) => Some(block),
1141             _ => None,
1142         },
1143         _ => None,
1144     })
1145 }
1146
1147 /// Gets the parent node if it's an impl block.
1148 pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
1149     let map = tcx.hir();
1150     match map.parent_iter(id).next() {
1151         Some((
1152             _,
1153             Node::Item(Item {
1154                 kind: ItemKind::Impl(imp),
1155                 ..
1156             }),
1157         )) => Some(imp),
1158         _ => None,
1159     }
1160 }
1161
1162 /// Returns the base type for HIR references and pointers.
1163 pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
1164     match ty.kind {
1165         TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty),
1166         _ => ty,
1167     }
1168 }
1169
1170 /// Returns the base type for references and raw pointers, and count reference
1171 /// depth.
1172 pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) {
1173     fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) {
1174         match ty.kind() {
1175             ty::Ref(_, ty, _) => inner(ty, depth + 1),
1176             _ => (ty, depth),
1177         }
1178     }
1179     inner(ty, 0)
1180 }
1181
1182 /// Checks whether the given expression is a constant integer of the given value.
1183 /// unlike `is_integer_literal`, this version does const folding
1184 pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
1185     if is_integer_literal(e, value) {
1186         return true;
1187     }
1188     let map = cx.tcx.hir();
1189     let parent_item = map.get_parent_item(e.hir_id);
1190     if let Some((Constant::Int(v), _)) = map
1191         .maybe_body_owned_by(parent_item)
1192         .and_then(|body_id| constant(cx, cx.tcx.typeck_body(body_id), e))
1193     {
1194         value == v
1195     } else {
1196         false
1197     }
1198 }
1199
1200 /// Checks whether the given expression is a constant literal of the given value.
1201 pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
1202     // FIXME: use constant folding
1203     if let ExprKind::Lit(ref spanned) = expr.kind {
1204         if let LitKind::Int(v, _) = spanned.node {
1205             return v == value;
1206         }
1207     }
1208     false
1209 }
1210
1211 /// Returns `true` if the given `Expr` has been coerced before.
1212 ///
1213 /// Examples of coercions can be found in the Nomicon at
1214 /// <https://doc.rust-lang.org/nomicon/coercions.html>.
1215 ///
1216 /// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
1217 /// information on adjustments and coercions.
1218 pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
1219     cx.typeck_results().adjustments().get(e.hir_id).is_some()
1220 }
1221
1222 /// Returns the pre-expansion span if is this comes from an expansion of the
1223 /// macro `name`.
1224 /// See also `is_direct_expn_of`.
1225 #[must_use]
1226 pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
1227     loop {
1228         if span.from_expansion() {
1229             let data = span.ctxt().outer_expn_data();
1230             let new_span = data.call_site;
1231
1232             if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1233                 if mac_name.as_str() == name {
1234                     return Some(new_span);
1235                 }
1236             }
1237
1238             span = new_span;
1239         } else {
1240             return None;
1241         }
1242     }
1243 }
1244
1245 /// Returns the pre-expansion span if the span directly comes from an expansion
1246 /// of the macro `name`.
1247 /// The difference with `is_expn_of` is that in
1248 /// ```rust,ignore
1249 /// foo!(bar!(42));
1250 /// ```
1251 /// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
1252 /// `bar!` by
1253 /// `is_direct_expn_of`.
1254 #[must_use]
1255 pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
1256     if span.from_expansion() {
1257         let data = span.ctxt().outer_expn_data();
1258         let new_span = data.call_site;
1259
1260         if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1261             if mac_name.as_str() == name {
1262                 return Some(new_span);
1263             }
1264         }
1265     }
1266
1267     None
1268 }
1269
1270 /// Convenience function to get the return type of a function.
1271 pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
1272     let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
1273     let ret_ty = cx.tcx.fn_sig(fn_def_id).output();
1274     cx.tcx.erase_late_bound_regions(ret_ty)
1275 }
1276
1277 /// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
1278 pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
1279     ty.walk().any(|inner| match inner.unpack() {
1280         GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty),
1281         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
1282     })
1283 }
1284
1285 /// Returns `true` if the given type is an `unsafe` function.
1286 pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
1287     match ty.kind() {
1288         ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe,
1289         _ => false,
1290     }
1291 }
1292
1293 pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
1294     ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
1295 }
1296
1297 /// Checks if an expression is constructing a tuple-like enum variant or struct
1298 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1299     if let ExprKind::Call(ref fun, _) = expr.kind {
1300         if let ExprKind::Path(ref qp) = fun.kind {
1301             let res = cx.qpath_res(qp, fun.hir_id);
1302             return match res {
1303                 def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
1304                 def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
1305                 _ => false,
1306             };
1307         }
1308     }
1309     false
1310 }
1311
1312 /// Returns `true` if a pattern is refutable.
1313 // TODO: should be implemented using rustc/mir_build/thir machinery
1314 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
1315     fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
1316         matches!(
1317             cx.qpath_res(qpath, id),
1318             def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
1319         )
1320     }
1321
1322     fn are_refutable<'a, I: Iterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, mut i: I) -> bool {
1323         i.any(|pat| is_refutable(cx, pat))
1324     }
1325
1326     match pat.kind {
1327         PatKind::Wild => false,
1328         PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
1329         PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat),
1330         PatKind::Lit(..) | PatKind::Range(..) => true,
1331         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
1332         PatKind::Or(ref pats) => {
1333             // TODO: should be the honest check, that pats is exhaustive set
1334             are_refutable(cx, pats.iter().map(|pat| &**pat))
1335         },
1336         PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
1337         PatKind::Struct(ref qpath, ref fields, _) => {
1338             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
1339         },
1340         PatKind::TupleStruct(ref qpath, ref pats, _) => {
1341             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat))
1342         },
1343         PatKind::Slice(ref head, ref middle, ref tail) => {
1344             match &cx.typeck_results().node_type(pat.hir_id).kind() {
1345                 ty::Slice(..) => {
1346                     // [..] is the only irrefutable slice pattern.
1347                     !head.is_empty() || middle.is_none() || !tail.is_empty()
1348                 },
1349                 ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)),
1350                 _ => {
1351                     // unreachable!()
1352                     true
1353                 },
1354             }
1355         },
1356     }
1357 }
1358
1359 /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
1360 /// implementations have.
1361 pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
1362     attrs.iter().any(|attr| attr.has_name(sym::automatically_derived))
1363 }
1364
1365 /// Remove blocks around an expression.
1366 ///
1367 /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return
1368 /// themselves.
1369 pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
1370     while let ExprKind::Block(ref block, ..) = expr.kind {
1371         match (block.stmts.is_empty(), block.expr.as_ref()) {
1372             (true, Some(e)) => expr = e,
1373             _ => break,
1374         }
1375     }
1376     expr
1377 }
1378
1379 pub fn is_self(slf: &Param<'_>) -> bool {
1380     if let PatKind::Binding(.., name, _) = slf.pat.kind {
1381         name.name == kw::SelfLower
1382     } else {
1383         false
1384     }
1385 }
1386
1387 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
1388     if_chain! {
1389         if let TyKind::Path(QPath::Resolved(None, ref path)) = slf.kind;
1390         if let Res::SelfTy(..) = path.res;
1391         then {
1392             return true
1393         }
1394     }
1395     false
1396 }
1397
1398 pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator<Item = &'tcx Param<'tcx>> {
1399     (0..decl.inputs.len()).map(move |i| &body.params[i])
1400 }
1401
1402 /// Checks if a given expression is a match expression expanded from the `?`
1403 /// operator or the `try` macro.
1404 pub fn is_try<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
1405     fn is_ok(arm: &Arm<'_>) -> bool {
1406         if_chain! {
1407             if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pat.kind;
1408             if match_qpath(path, &paths::RESULT_OK[1..]);
1409             if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
1410             if path_to_local_id(arm.body, hir_id);
1411             then {
1412                 return true;
1413             }
1414         }
1415         false
1416     }
1417
1418     fn is_err(arm: &Arm<'_>) -> bool {
1419         if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
1420             match_qpath(path, &paths::RESULT_ERR[1..])
1421         } else {
1422             false
1423         }
1424     }
1425
1426     if let ExprKind::Match(_, ref arms, ref source) = expr.kind {
1427         // desugared from a `?` operator
1428         if let MatchSource::TryDesugar = *source {
1429             return Some(expr);
1430         }
1431
1432         if_chain! {
1433             if arms.len() == 2;
1434             if arms[0].guard.is_none();
1435             if arms[1].guard.is_none();
1436             if (is_ok(&arms[0]) && is_err(&arms[1])) ||
1437                 (is_ok(&arms[1]) && is_err(&arms[0]));
1438             then {
1439                 return Some(expr);
1440             }
1441         }
1442     }
1443
1444     None
1445 }
1446
1447 /// Returns `true` if the lint is allowed in the current context
1448 ///
1449 /// Useful for skipping long running code when it's unnecessary
1450 pub fn is_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
1451     cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
1452 }
1453
1454 pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
1455     while let PatKind::Ref(subpat, _) = pat.kind {
1456         pat = subpat;
1457     }
1458     pat
1459 }
1460
1461 pub fn int_bits(tcx: TyCtxt<'_>, ity: ty::IntTy) -> u64 {
1462     Integer::from_int_ty(&tcx, ity).size().bits()
1463 }
1464
1465 #[allow(clippy::cast_possible_wrap)]
1466 /// Turn a constant int byte representation into an i128
1467 pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: ty::IntTy) -> i128 {
1468     let amt = 128 - int_bits(tcx, ity);
1469     ((u as i128) << amt) >> amt
1470 }
1471
1472 #[allow(clippy::cast_sign_loss)]
1473 /// clip unused bytes
1474 pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ty::IntTy) -> u128 {
1475     let amt = 128 - int_bits(tcx, ity);
1476     ((u as u128) << amt) >> amt
1477 }
1478
1479 /// clip unused bytes
1480 pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: ty::UintTy) -> u128 {
1481     let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
1482     let amt = 128 - bits;
1483     (u << amt) >> amt
1484 }
1485
1486 /// Removes block comments from the given `Vec` of lines.
1487 ///
1488 /// # Examples
1489 ///
1490 /// ```rust,ignore
1491 /// without_block_comments(vec!["/*", "foo", "*/"]);
1492 /// // => vec![]
1493 ///
1494 /// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
1495 /// // => vec!["bar"]
1496 /// ```
1497 pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
1498     let mut without = vec![];
1499
1500     let mut nest_level = 0;
1501
1502     for line in lines {
1503         if line.contains("/*") {
1504             nest_level += 1;
1505             continue;
1506         } else if line.contains("*/") {
1507             nest_level -= 1;
1508             continue;
1509         }
1510
1511         if nest_level == 0 {
1512             without.push(line);
1513         }
1514     }
1515
1516     without
1517 }
1518
1519 pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
1520     let map = &tcx.hir();
1521     let mut prev_enclosing_node = None;
1522     let mut enclosing_node = node;
1523     while Some(enclosing_node) != prev_enclosing_node {
1524         if is_automatically_derived(map.attrs(enclosing_node)) {
1525             return true;
1526         }
1527         prev_enclosing_node = Some(enclosing_node);
1528         enclosing_node = map.get_parent_item(enclosing_node);
1529     }
1530     false
1531 }
1532
1533 /// Returns true if ty has `iter` or `iter_mut` methods
1534 pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> {
1535     // FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
1536     // exists and has the desired signature. Unfortunately FnCtxt is not exported
1537     // so we can't use its `lookup_method` method.
1538     let into_iter_collections: &[Symbol] = &[
1539         sym::vec_type,
1540         sym::option_type,
1541         sym::result_type,
1542         sym::BTreeMap,
1543         sym::BTreeSet,
1544         sym::vecdeque_type,
1545         sym::LinkedList,
1546         sym::BinaryHeap,
1547         sym::hashset_type,
1548         sym::hashmap_type,
1549         sym::PathBuf,
1550         sym::Path,
1551         sym::Receiver,
1552     ];
1553
1554     let ty_to_check = match probably_ref_ty.kind() {
1555         ty::Ref(_, ty_to_check, _) => ty_to_check,
1556         _ => probably_ref_ty,
1557     };
1558
1559     let def_id = match ty_to_check.kind() {
1560         ty::Array(..) => return Some(sym::array),
1561         ty::Slice(..) => return Some(sym::slice),
1562         ty::Adt(adt, _) => adt.did,
1563         _ => return None,
1564     };
1565
1566     for &name in into_iter_collections {
1567         if cx.tcx.is_diagnostic_item(name, def_id) {
1568             return Some(cx.tcx.item_name(def_id));
1569         }
1570     }
1571     None
1572 }
1573
1574 /// Matches a function call with the given path and returns the arguments.
1575 ///
1576 /// Usage:
1577 ///
1578 /// ```rust,ignore
1579 /// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
1580 /// ```
1581 pub fn match_function_call<'tcx>(
1582     cx: &LateContext<'tcx>,
1583     expr: &'tcx Expr<'_>,
1584     path: &[&str],
1585 ) -> Option<&'tcx [Expr<'tcx>]> {
1586     if_chain! {
1587         if let ExprKind::Call(ref fun, ref args) = expr.kind;
1588         if let ExprKind::Path(ref qpath) = fun.kind;
1589         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
1590         if match_def_path(cx, fun_def_id, path);
1591         then {
1592             return Some(&args)
1593         }
1594     };
1595     None
1596 }
1597
1598 // FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize
1599 // this function can be removed once the `normalizie` method does not panic when normalization does
1600 // not succeed
1601 /// Checks if `Ty` is normalizable. This function is useful
1602 /// to avoid crashes on `layout_of`.
1603 pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
1604     is_normalizable_helper(cx, param_env, ty, &mut HashMap::new())
1605 }
1606
1607 fn is_normalizable_helper<'tcx>(
1608     cx: &LateContext<'tcx>,
1609     param_env: ty::ParamEnv<'tcx>,
1610     ty: Ty<'tcx>,
1611     cache: &mut HashMap<Ty<'tcx>, bool>,
1612 ) -> bool {
1613     if let Some(&cached_result) = cache.get(ty) {
1614         return cached_result;
1615     }
1616     // prevent recursive loops, false-negative is better than endless loop leading to stack overflow
1617     cache.insert(ty, false);
1618     let result = cx.tcx.infer_ctxt().enter(|infcx| {
1619         let cause = rustc_middle::traits::ObligationCause::dummy();
1620         if infcx.at(&cause, param_env).normalize(ty).is_ok() {
1621             match ty.kind() {
1622                 ty::Adt(def, substs) => def.variants.iter().all(|variant| {
1623                     variant
1624                         .fields
1625                         .iter()
1626                         .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
1627                 }),
1628                 _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
1629                     GenericArgKind::Type(inner_ty) if inner_ty != ty => {
1630                         is_normalizable_helper(cx, param_env, inner_ty, cache)
1631                     },
1632                     _ => true, // if inner_ty == ty, we've already checked it
1633                 }),
1634             }
1635         } else {
1636             false
1637         }
1638     });
1639     cache.insert(ty, result);
1640     result
1641 }
1642
1643 pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool {
1644     // We have to convert `syms` to `&[Symbol]` here because rustc's `match_def_path`
1645     // accepts only that. We should probably move to Symbols in Clippy as well.
1646     let syms = syms.iter().map(|p| Symbol::intern(p)).collect::<Vec<Symbol>>();
1647     cx.match_def_path(did, &syms)
1648 }
1649
1650 pub fn match_panic_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx [Expr<'tcx>]> {
1651     match_function_call(cx, expr, &paths::BEGIN_PANIC)
1652         .or_else(|| match_function_call(cx, expr, &paths::BEGIN_PANIC_FMT))
1653         .or_else(|| match_function_call(cx, expr, &paths::PANIC_ANY))
1654         .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC))
1655         .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC_FMT))
1656         .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC_STR))
1657 }
1658
1659 pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool {
1660     match_def_path(cx, did, &paths::BEGIN_PANIC)
1661         || match_def_path(cx, did, &paths::BEGIN_PANIC_FMT)
1662         || match_def_path(cx, did, &paths::PANIC_ANY)
1663         || match_def_path(cx, did, &paths::PANICKING_PANIC)
1664         || match_def_path(cx, did, &paths::PANICKING_PANIC_FMT)
1665         || match_def_path(cx, did, &paths::PANICKING_PANIC_STR)
1666 }
1667
1668 /// Returns the list of condition expressions and the list of blocks in a
1669 /// sequence of `if/else`.
1670 /// E.g., this returns `([a, b], [c, d, e])` for the expression
1671 /// `if a { c } else if b { d } else { e }`.
1672 pub fn if_sequence<'tcx>(
1673     mut expr: &'tcx Expr<'tcx>,
1674 ) -> (SmallVec<[&'tcx Expr<'tcx>; 1]>, SmallVec<[&'tcx Block<'tcx>; 1]>) {
1675     let mut conds = SmallVec::new();
1676     let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new();
1677
1678     while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind {
1679         conds.push(&**cond);
1680         if let ExprKind::Block(ref block, _) = then_expr.kind {
1681             blocks.push(block);
1682         } else {
1683             panic!("ExprKind::If node is not an ExprKind::Block");
1684         }
1685
1686         if let Some(ref else_expr) = *else_expr {
1687             expr = else_expr;
1688         } else {
1689             break;
1690         }
1691     }
1692
1693     // final `else {..}`
1694     if !blocks.is_empty() {
1695         if let ExprKind::Block(ref block, _) = expr.kind {
1696             blocks.push(&**block);
1697         }
1698     }
1699
1700     (conds, blocks)
1701 }
1702
1703 pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
1704     let map = cx.tcx.hir();
1705     let parent_id = map.get_parent_node(expr.hir_id);
1706     let parent_node = map.get(parent_id);
1707     matches!(
1708         parent_node,
1709         Node::Expr(Expr {
1710             kind: ExprKind::If(_, _, _),
1711             ..
1712         })
1713     )
1714 }
1715
1716 // Finds the attribute with the given name, if any
1717 pub fn attr_by_name<'a>(attrs: &'a [Attribute], name: &'_ str) -> Option<&'a Attribute> {
1718     attrs
1719         .iter()
1720         .find(|attr| attr.ident().map_or(false, |ident| ident.as_str() == name))
1721 }
1722
1723 // Finds the `#[must_use]` attribute, if any
1724 pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
1725     attr_by_name(attrs, "must_use")
1726 }
1727
1728 // Returns whether the type has #[must_use] attribute
1729 pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
1730     match ty.kind() {
1731         ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(),
1732         ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(),
1733         ty::Slice(ref ty)
1734         | ty::Array(ref ty, _)
1735         | ty::RawPtr(ty::TypeAndMut { ref ty, .. })
1736         | ty::Ref(_, ref ty, _) => {
1737             // for the Array case we don't need to care for the len == 0 case
1738             // because we don't want to lint functions returning empty arrays
1739             is_must_use_ty(cx, *ty)
1740         },
1741         ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
1742         ty::Opaque(ref def_id, _) => {
1743             for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
1744                 if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() {
1745                     if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
1746                         return true;
1747                     }
1748                 }
1749             }
1750             false
1751         },
1752         ty::Dynamic(binder, _) => {
1753             for predicate in binder.iter() {
1754                 if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
1755                     if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
1756                         return true;
1757                     }
1758                 }
1759             }
1760             false
1761         },
1762         _ => false,
1763     }
1764 }
1765
1766 // check if expr is calling method or function with #[must_use] attribute
1767 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1768     let did = match expr.kind {
1769         ExprKind::Call(ref path, _) => if_chain! {
1770             if let ExprKind::Path(ref qpath) = path.kind;
1771             if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
1772             then {
1773                 Some(did)
1774             } else {
1775                 None
1776             }
1777         },
1778         ExprKind::MethodCall(_, _, _, _) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1779         _ => None,
1780     };
1781
1782     did.map_or(false, |did| must_use_attr(&cx.tcx.get_attrs(did)).is_some())
1783 }
1784
1785 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
1786     cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
1787         if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
1788             attr.path == sym::no_std
1789         } else {
1790             false
1791         }
1792     })
1793 }
1794
1795 /// Check if parent of a hir node is a trait implementation block.
1796 /// For example, `f` in
1797 /// ```rust,ignore
1798 /// impl Trait for S {
1799 ///     fn f() {}
1800 /// }
1801 /// ```
1802 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
1803     if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
1804         matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
1805     } else {
1806         false
1807     }
1808 }
1809
1810 /// Check if it's even possible to satisfy the `where` clause for the item.
1811 ///
1812 /// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example:
1813 ///
1814 /// ```ignore
1815 /// fn foo() where i32: Iterator {
1816 ///     for _ in 2i32 {}
1817 /// }
1818 /// ```
1819 pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
1820     use rustc_trait_selection::traits;
1821     let predicates = cx
1822         .tcx
1823         .predicates_of(did)
1824         .predicates
1825         .iter()
1826         .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
1827     traits::impossible_predicates(
1828         cx.tcx,
1829         traits::elaborate_predicates(cx.tcx, predicates)
1830             .map(|o| o.predicate)
1831             .collect::<Vec<_>>(),
1832     )
1833 }
1834
1835 /// Returns the `DefId` of the callee if the given expression is a function or method call.
1836 pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
1837     match &expr.kind {
1838         ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1839         ExprKind::Call(
1840             Expr {
1841                 kind: ExprKind::Path(qpath),
1842                 hir_id: path_hir_id,
1843                 ..
1844             },
1845             ..,
1846         ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
1847         _ => None,
1848     }
1849 }
1850
1851 pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bool {
1852     lints.iter().any(|lint| {
1853         matches!(
1854             cx.tcx.lint_level_at_node(lint, id),
1855             (Level::Forbid | Level::Deny | Level::Warn, _)
1856         )
1857     })
1858 }
1859
1860 /// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point
1861 /// number type, a str, or an array, slice, or tuple of those types).
1862 pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
1863     match ty.kind() {
1864         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
1865         ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true,
1866         ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type),
1867         ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type),
1868         _ => false,
1869     }
1870 }
1871
1872 /// Returns Option<String> where String is a textual representation of the type encapsulated in the
1873 /// slice iff the given expression is a slice of primitives (as defined in the
1874 /// `is_recursively_primitive_type` function) and None otherwise.
1875 pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
1876     let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
1877     let expr_kind = expr_type.kind();
1878     let is_primitive = match expr_kind {
1879         ty::Slice(element_type) => is_recursively_primitive_type(element_type),
1880         ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &ty::Slice(_)) => {
1881             if let ty::Slice(element_type) = inner_ty.kind() {
1882                 is_recursively_primitive_type(element_type)
1883             } else {
1884                 unreachable!()
1885             }
1886         },
1887         _ => false,
1888     };
1889
1890     if is_primitive {
1891         // if we have wrappers like Array, Slice or Tuple, print these
1892         // and get the type enclosed in the slice ref
1893         match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
1894             ty::Slice(..) => return Some("slice".into()),
1895             ty::Array(..) => return Some("array".into()),
1896             ty::Tuple(..) => return Some("tuple".into()),
1897             _ => {
1898                 // is_recursively_primitive_type() should have taken care
1899                 // of the rest and we can rely on the type that is found
1900                 let refs_peeled = expr_type.peel_refs();
1901                 return Some(refs_peeled.walk().last().unwrap().to_string());
1902             },
1903         }
1904     }
1905     None
1906 }
1907
1908 /// returns list of all pairs (a, b) from `exprs` such that `eq(a, b)`
1909 /// `hash` must be comformed with `eq`
1910 pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
1911 where
1912     Hash: Fn(&T) -> u64,
1913     Eq: Fn(&T, &T) -> bool,
1914 {
1915     if exprs.len() == 2 && eq(&exprs[0], &exprs[1]) {
1916         return vec![(&exprs[0], &exprs[1])];
1917     }
1918
1919     let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
1920
1921     let mut map: FxHashMap<_, Vec<&_>> =
1922         FxHashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
1923
1924     for expr in exprs {
1925         match map.entry(hash(expr)) {
1926             Entry::Occupied(mut o) => {
1927                 for o in o.get() {
1928                     if eq(o, expr) {
1929                         match_expr_list.push((o, expr));
1930                     }
1931                 }
1932                 o.get_mut().push(expr);
1933             },
1934             Entry::Vacant(v) => {
1935                 v.insert(vec![expr]);
1936             },
1937         }
1938     }
1939
1940     match_expr_list
1941 }
1942
1943 /// Peels off all references on the pattern. Returns the underlying pattern and the number of
1944 /// references removed.
1945 pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
1946     fn peel(pat: &'a Pat<'a>, count: usize) -> (&'a Pat<'a>, usize) {
1947         if let PatKind::Ref(pat, _) = pat.kind {
1948             peel(pat, count + 1)
1949         } else {
1950             (pat, count)
1951         }
1952     }
1953     peel(pat, 0)
1954 }
1955
1956 /// Peels off up to the given number of references on the expression. Returns the underlying
1957 /// expression and the number of references removed.
1958 pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
1959     fn f(expr: &'a Expr<'a>, count: usize, target: usize) -> (&'a Expr<'a>, usize) {
1960         match expr.kind {
1961             ExprKind::AddrOf(_, _, expr) if count != target => f(expr, count + 1, target),
1962             _ => (expr, count),
1963         }
1964     }
1965     f(expr, 0, count)
1966 }
1967
1968 /// Peels off all references on the expression. Returns the underlying expression and the number of
1969 /// references removed.
1970 pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
1971     fn f(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
1972         match expr.kind {
1973             ExprKind::AddrOf(BorrowKind::Ref, _, expr) => f(expr, count + 1),
1974             _ => (expr, count),
1975         }
1976     }
1977     f(expr, 0)
1978 }
1979
1980 /// Peels off all references on the type. Returns the underlying type and the number of references
1981 /// removed.
1982 pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) {
1983     fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) {
1984         if let ty::Ref(_, ty, _) = ty.kind() {
1985             peel(ty, count + 1)
1986         } else {
1987             (ty, count)
1988         }
1989     }
1990     peel(ty, 0)
1991 }
1992
1993 /// Peels off all references on the type.Returns the underlying type, the number of references
1994 /// removed, and whether the pointer is ultimately mutable or not.
1995 pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) {
1996     fn f(ty: Ty<'_>, count: usize, mutability: Mutability) -> (Ty<'_>, usize, Mutability) {
1997         match ty.kind() {
1998             ty::Ref(_, ty, Mutability::Mut) => f(ty, count + 1, mutability),
1999             ty::Ref(_, ty, Mutability::Not) => f(ty, count + 1, Mutability::Not),
2000             _ => (ty, count, mutability),
2001         }
2002     }
2003     f(ty, 0, Mutability::Mut)
2004 }
2005
2006 #[macro_export]
2007 macro_rules! unwrap_cargo_metadata {
2008     ($cx: ident, $lint: ident, $deps: expr) => {{
2009         let mut command = cargo_metadata::MetadataCommand::new();
2010         if !$deps {
2011             command.no_deps();
2012         }
2013
2014         match command.exec() {
2015             Ok(metadata) => metadata,
2016             Err(err) => {
2017                 span_lint($cx, $lint, DUMMY_SP, &format!("could not read cargo metadata: {}", err));
2018                 return;
2019             },
2020         }
2021     }};
2022 }
2023
2024 pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
2025     if_chain! {
2026         if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
2027         if let Res::Def(_, def_id) = path.res;
2028         then {
2029             cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr)
2030         } else {
2031             false
2032         }
2033     }
2034 }
2035
2036 /// Check if the resolution of a given path is an `Ok` variant of `Result`.
2037 pub fn is_ok_ctor(cx: &LateContext<'_>, res: Res) -> bool {
2038     if let Some(ok_id) = cx.tcx.lang_items().result_ok_variant() {
2039         if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
2040             if let Some(variant_id) = cx.tcx.parent(id) {
2041                 return variant_id == ok_id;
2042             }
2043         }
2044     }
2045     false
2046 }
2047
2048 /// Check if the resolution of a given path is a `Some` variant of `Option`.
2049 pub fn is_some_ctor(cx: &LateContext<'_>, res: Res) -> bool {
2050     if let Some(some_id) = cx.tcx.lang_items().option_some_variant() {
2051         if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
2052             if let Some(variant_id) = cx.tcx.parent(id) {
2053                 return variant_id == some_id;
2054             }
2055         }
2056     }
2057     false
2058 }
2059
2060 #[cfg(test)]
2061 mod test {
2062     use super::{reindent_multiline, without_block_comments};
2063
2064     #[test]
2065     fn test_reindent_multiline_single_line() {
2066         assert_eq!("", reindent_multiline("".into(), false, None));
2067         assert_eq!("...", reindent_multiline("...".into(), false, None));
2068         assert_eq!("...", reindent_multiline("    ...".into(), false, None));
2069         assert_eq!("...", reindent_multiline("\t...".into(), false, None));
2070         assert_eq!("...", reindent_multiline("\t\t...".into(), false, None));
2071     }
2072
2073     #[test]
2074     #[rustfmt::skip]
2075     fn test_reindent_multiline_block() {
2076         assert_eq!("\
2077     if x {
2078         y
2079     } else {
2080         z
2081     }", reindent_multiline("    if x {
2082             y
2083         } else {
2084             z
2085         }".into(), false, None));
2086         assert_eq!("\
2087     if x {
2088     \ty
2089     } else {
2090     \tz
2091     }", reindent_multiline("    if x {
2092         \ty
2093         } else {
2094         \tz
2095         }".into(), false, None));
2096     }
2097
2098     #[test]
2099     #[rustfmt::skip]
2100     fn test_reindent_multiline_empty_line() {
2101         assert_eq!("\
2102     if x {
2103         y
2104
2105     } else {
2106         z
2107     }", reindent_multiline("    if x {
2108             y
2109
2110         } else {
2111             z
2112         }".into(), false, None));
2113     }
2114
2115     #[test]
2116     #[rustfmt::skip]
2117     fn test_reindent_multiline_lines_deeper() {
2118         assert_eq!("\
2119         if x {
2120             y
2121         } else {
2122             z
2123         }", reindent_multiline("\
2124     if x {
2125         y
2126     } else {
2127         z
2128     }".into(), true, Some(8)));
2129     }
2130
2131     #[test]
2132     fn test_without_block_comments_lines_without_block_comments() {
2133         let result = without_block_comments(vec!["/*", "", "*/"]);
2134         println!("result: {:?}", result);
2135         assert!(result.is_empty());
2136
2137         let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
2138         assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
2139
2140         let result = without_block_comments(vec!["/* rust", "", "*/"]);
2141         assert!(result.is_empty());
2142
2143         let result = without_block_comments(vec!["/* one-line comment */"]);
2144         assert!(result.is_empty());
2145
2146         let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
2147         assert!(result.is_empty());
2148
2149         let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
2150         assert!(result.is_empty());
2151
2152         let result = without_block_comments(vec!["foo", "bar", "baz"]);
2153         assert_eq!(result, vec!["foo", "bar", "baz"]);
2154     }
2155 }