]> git.lizzy.rs Git - rust.git/blob - clippy_utils/src/lib.rs
Merge commit '7bfc26ec8e7a454786668e7e52ffe527fc649735' into clippyup
[rust.git] / clippy_utils / src / lib.rs
1 #![feature(box_patterns)]
2 #![feature(in_band_lifetimes)]
3 #![feature(iter_zip)]
4 #![feature(rustc_private)]
5 #![recursion_limit = "512"]
6 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
7 #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
8 // warn on the same lints as `clippy_lints`
9 #![warn(trivial_casts, trivial_numeric_casts)]
10 // warn on lints, that are included in `rust-lang/rust`s bootstrap
11 #![warn(rust_2018_idioms, unused_lifetimes)]
12 // warn on rustc internal lints
13 #![warn(rustc::internal)]
14
15 // FIXME: switch to something more ergonomic here, once available.
16 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
17 extern crate rustc_ast;
18 extern crate rustc_ast_pretty;
19 extern crate rustc_attr;
20 extern crate rustc_data_structures;
21 extern crate rustc_errors;
22 extern crate rustc_hir;
23 extern crate rustc_infer;
24 extern crate rustc_lexer;
25 extern crate rustc_lint;
26 extern crate rustc_middle;
27 extern crate rustc_mir;
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 camel_case;
41 pub mod comparisons;
42 pub mod consts;
43 pub mod diagnostics;
44 pub mod eager_or_lazy;
45 pub mod higher;
46 mod hir_utils;
47 pub mod 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 sugg;
54 pub mod ty;
55 pub mod usage;
56 pub mod visitors;
57
58 pub use self::attrs::*;
59 pub use self::hir_utils::{both, count_eq, eq_expr_value, over, SpanlessEq, SpanlessHash};
60
61 use std::collections::hash_map::Entry;
62 use std::hash::BuildHasherDefault;
63
64 use if_chain::if_chain;
65 use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind};
66 use rustc_data_structures::unhash::UnhashMap;
67 use rustc_hir as hir;
68 use rustc_hir::def::{DefKind, Res};
69 use rustc_hir::def_id::DefId;
70 use rustc_hir::intravisit::{self, walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visitor};
71 use rustc_hir::LangItem::{ResultErr, ResultOk};
72 use rustc_hir::{
73     def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl,
74     ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path,
75     PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
76 };
77 use rustc_lint::{LateContext, Level, Lint, LintContext};
78 use rustc_middle::hir::exports::Export;
79 use rustc_middle::hir::map::Map;
80 use rustc_middle::ty as rustc_ty;
81 use rustc_middle::ty::{layout::IntegerExt, DefIdTree, Ty, TyCtxt, TypeFoldable};
82 use rustc_semver::RustcVersion;
83 use rustc_session::Session;
84 use rustc_span::hygiene::{ExpnKind, MacroKind};
85 use rustc_span::source_map::original_sp;
86 use rustc_span::sym;
87 use rustc_span::symbol::{kw, Symbol};
88 use rustc_span::{Span, DUMMY_SP};
89 use rustc_target::abi::Integer;
90
91 use crate::consts::{constant, Constant};
92 use crate::ty::{can_partially_move_ty, is_recursively_primitive_type};
93
94 pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
95     if let Ok(version) = RustcVersion::parse(msrv) {
96         return Some(version);
97     } else if let Some(sess) = sess {
98         if let Some(span) = span {
99             sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
100         }
101     }
102     None
103 }
104
105 pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool {
106     msrv.map_or(true, |msrv| msrv.meets(*lint_msrv))
107 }
108
109 #[macro_export]
110 macro_rules! extract_msrv_attr {
111     (LateContext) => {
112         extract_msrv_attr!(@LateContext, ());
113     };
114     (EarlyContext) => {
115         extract_msrv_attr!(@EarlyContext);
116     };
117     (@$context:ident$(, $call:tt)?) => {
118         fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'tcx>, attrs: &'tcx [rustc_ast::ast::Attribute]) {
119             use $crate::get_unique_inner_attr;
120             match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") {
121                 Some(msrv_attr) => {
122                     if let Some(msrv) = msrv_attr.value_str() {
123                         self.msrv = $crate::parse_msrv(
124                             &msrv.to_string(),
125                             Some(cx.sess$($call)?),
126                             Some(msrv_attr.span),
127                         );
128                     } else {
129                         cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute");
130                     }
131                 },
132                 _ => (),
133             }
134         }
135     };
136 }
137
138 /// Returns `true` if the two spans come from differing expansions (i.e., one is
139 /// from a macro and one isn't).
140 #[must_use]
141 pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
142     rhs.ctxt() != lhs.ctxt()
143 }
144
145 /// If the given expression is a local binding, find the initializer expression.
146 /// If that initializer expression is another local binding, find its initializer again.
147 /// This process repeats as long as possible (but usually no more than once). Initializer
148 /// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
149 /// instead.
150 ///
151 /// Examples:
152 /// ```ignore
153 /// let abc = 1;
154 /// //        ^ output
155 /// let def = abc;
156 /// dbg!(def)
157 /// //   ^^^ input
158 ///
159 /// // or...
160 /// let abc = 1;
161 /// let def = abc + 2;
162 /// //        ^^^^^^^ output
163 /// dbg!(def)
164 /// //   ^^^ input
165 /// ```
166 pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
167     while let Some(init) = path_to_local(expr)
168         .and_then(|id| find_binding_init(cx, id))
169         .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
170     {
171         expr = init;
172     }
173     expr
174 }
175
176 /// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
177 /// By only considering immutable bindings, we guarantee that the returned expression represents the
178 /// value of the binding wherever it is referenced.
179 ///
180 /// Example: For `let x = 1`, if the `HirId` of `x` is provided, the `Expr` `1` is returned.
181 /// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the
182 /// canonical binding `HirId`.
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 /// Checks if a `QPath` resolves to a constructor of a `LangItem`.
235 /// For example, use this to check whether a function call or a pattern is `Some(..)`.
236 pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem) -> bool {
237     if let QPath::Resolved(_, path) = qpath {
238         if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
239             if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) {
240                 return cx.tcx.parent(ctor_id) == Some(item_id);
241             }
242         }
243     }
244     false
245 }
246
247 /// Returns `true` if this `span` was expanded by any macro.
248 #[must_use]
249 pub fn in_macro(span: Span) -> bool {
250     if span.from_expansion() {
251         !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
252     } else {
253         false
254     }
255 }
256
257 /// Checks if given pattern is a wildcard (`_`)
258 pub fn is_wild(pat: &Pat<'_>) -> bool {
259     matches!(pat.kind, PatKind::Wild)
260 }
261
262 /// Checks if the first type parameter is a lang item.
263 pub fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> {
264     let ty = get_qpath_generic_tys(qpath).next()?;
265
266     if let TyKind::Path(qpath) = &ty.kind {
267         cx.qpath_res(qpath, ty.hir_id)
268             .opt_def_id()
269             .map_or(false, |id| {
270                 cx.tcx.lang_items().require(item).map_or(false, |lang_id| id == lang_id)
271             })
272             .then(|| ty)
273     } else {
274         None
275     }
276 }
277
278 /// Checks if the first type parameter is a diagnostic item.
279 pub fn is_ty_param_diagnostic_item(
280     cx: &LateContext<'_>,
281     qpath: &QPath<'tcx>,
282     item: Symbol,
283 ) -> Option<&'tcx hir::Ty<'tcx>> {
284     let ty = get_qpath_generic_tys(qpath).next()?;
285
286     if let TyKind::Path(qpath) = &ty.kind {
287         cx.qpath_res(qpath, ty.hir_id)
288             .opt_def_id()
289             .map_or(false, |id| cx.tcx.is_diagnostic_item(item, id))
290             .then(|| ty)
291     } else {
292         None
293     }
294 }
295
296 /// Checks if the method call given in `expr` belongs to the given trait.
297 /// This is a deprecated function, consider using [`is_trait_method`].
298 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
299     let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
300     let trt_id = cx.tcx.trait_of_item(def_id);
301     trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path))
302 }
303
304 /// Checks if a method is defined in an impl of a diagnostic item
305 pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
306     if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
307         if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
308             return cx.tcx.is_diagnostic_item(diag_item, adt.did);
309         }
310     }
311     false
312 }
313
314 /// Checks if a method is in a diagnostic item trait
315 pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
316     if let Some(trait_did) = cx.tcx.trait_of_item(def_id) {
317         return cx.tcx.is_diagnostic_item(diag_item, trait_did);
318     }
319     false
320 }
321
322 /// Checks if the method call given in `expr` belongs to the given trait.
323 pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
324     cx.typeck_results()
325         .type_dependent_def_id(expr.hir_id)
326         .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
327 }
328
329 /// Checks if the given expression is a path referring an item on the trait
330 /// that is marked with the given diagnostic item.
331 ///
332 /// For checking method call expressions instead of path expressions, use
333 /// [`is_trait_method`].
334 ///
335 /// For example, this can be used to find if an expression like `u64::default`
336 /// refers to an item of the trait `Default`, which is associated with the
337 /// `diag_item` of `sym::Default`.
338 pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
339     if let hir::ExprKind::Path(ref qpath) = expr.kind {
340         cx.qpath_res(qpath, expr.hir_id)
341             .opt_def_id()
342             .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
343     } else {
344         false
345     }
346 }
347
348 pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
349     match *path {
350         QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
351         QPath::TypeRelative(_, seg) => seg,
352         QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
353     }
354 }
355
356 pub fn get_qpath_generics(path: &QPath<'tcx>) -> Option<&'tcx GenericArgs<'tcx>> {
357     match path {
358         QPath::Resolved(_, p) => p.segments.last().and_then(|s| s.args),
359         QPath::TypeRelative(_, s) => s.args,
360         QPath::LangItem(..) => None,
361     }
362 }
363
364 pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
365     get_qpath_generics(path)
366         .map_or([].as_ref(), |a| a.args)
367         .iter()
368         .filter_map(|a| {
369             if let hir::GenericArg::Type(ty) = a {
370                 Some(ty)
371             } else {
372                 None
373             }
374         })
375 }
376
377 pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
378     match *path {
379         QPath::Resolved(_, path) => path.segments.get(0),
380         QPath::TypeRelative(_, seg) => Some(seg),
381         QPath::LangItem(..) => None,
382     }
383 }
384
385 /// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
386 /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
387 /// `QPath::Resolved.1.res.opt_def_id()`.
388 ///
389 /// Matches a `QPath` against a slice of segment string literals.
390 ///
391 /// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a
392 /// `rustc_hir::QPath`.
393 ///
394 /// # Examples
395 /// ```rust,ignore
396 /// match_qpath(path, &["std", "rt", "begin_unwind"])
397 /// ```
398 pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
399     match *path {
400         QPath::Resolved(_, path) => match_path(path, segments),
401         QPath::TypeRelative(ty, segment) => match ty.kind {
402             TyKind::Path(ref inner_path) => {
403                 if let [prefix @ .., end] = segments {
404                     if match_qpath(inner_path, prefix) {
405                         return segment.ident.name.as_str() == *end;
406                     }
407                 }
408                 false
409             },
410             _ => false,
411         },
412         QPath::LangItem(..) => false,
413     }
414 }
415
416 /// If the expression is a path, resolve it. Otherwise, return `Res::Err`.
417 pub fn expr_path_res(cx: &LateContext<'_>, expr: &Expr<'_>) -> Res {
418     if let ExprKind::Path(p) = &expr.kind {
419         cx.qpath_res(p, expr.hir_id)
420     } else {
421         Res::Err
422     }
423 }
424
425 /// Resolves the path to a `DefId` and checks if it matches the given path.
426 pub fn is_qpath_def_path(cx: &LateContext<'_>, path: &QPath<'_>, hir_id: HirId, segments: &[&str]) -> bool {
427     cx.qpath_res(path, hir_id)
428         .opt_def_id()
429         .map_or(false, |id| match_def_path(cx, id, segments))
430 }
431
432 /// If the expression is a path, resolves it to a `DefId` and checks if it matches the given path.
433 ///
434 /// Please use `is_expr_diagnostic_item` if the target is a diagnostic item.
435 pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool {
436     expr_path_res(cx, expr)
437         .opt_def_id()
438         .map_or(false, |id| match_def_path(cx, id, segments))
439 }
440
441 /// If the expression is a path, resolves it to a `DefId` and checks if it matches the given
442 /// diagnostic item.
443 pub fn is_expr_diagnostic_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
444     expr_path_res(cx, expr)
445         .opt_def_id()
446         .map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id))
447 }
448
449 /// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
450 /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
451 /// `QPath::Resolved.1.res.opt_def_id()`.
452 ///
453 /// Matches a `Path` against a slice of segment string literals.
454 ///
455 /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a
456 /// `rustc_hir::Path`.
457 ///
458 /// # Examples
459 ///
460 /// ```rust,ignore
461 /// if match_path(&trait_ref.path, &paths::HASH) {
462 ///     // This is the `std::hash::Hash` trait.
463 /// }
464 ///
465 /// if match_path(ty_path, &["rustc", "lint", "Lint"]) {
466 ///     // This is a `rustc_middle::lint::Lint`.
467 /// }
468 /// ```
469 pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
470     path.segments
471         .iter()
472         .rev()
473         .zip(segments.iter().rev())
474         .all(|(a, b)| a.ident.name.as_str() == *b)
475 }
476
477 /// If the expression is a path to a local, returns the canonical `HirId` of the local.
478 pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
479     if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
480         if let Res::Local(id) = path.res {
481             return Some(id);
482         }
483     }
484     None
485 }
486
487 /// Returns true if the expression is a path to a local with the specified `HirId`.
488 /// Use this function to see if an expression matches a function argument or a match binding.
489 pub fn path_to_local_id(expr: &Expr<'_>, id: HirId) -> bool {
490     path_to_local(expr) == Some(id)
491 }
492
493 /// Gets the definition associated to a path.
494 #[allow(clippy::shadow_unrelated)] // false positive #6563
495 pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
496     macro_rules! try_res {
497         ($e:expr) => {
498             match $e {
499                 Some(e) => e,
500                 None => return Res::Err,
501             }
502         };
503     }
504     fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
505         tcx.item_children(def_id)
506             .iter()
507             .find(|item| item.ident.name.as_str() == name)
508     }
509
510     let (krate, first, path) = match *path {
511         [krate, first, ref path @ ..] => (krate, first, path),
512         [primitive] => {
513             return PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy);
514         },
515         _ => return Res::Err,
516     };
517     let tcx = cx.tcx;
518     let crates = tcx.crates(());
519     let krate = try_res!(crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate));
520     let first = try_res!(item_child_by_name(tcx, krate.as_def_id(), first));
521     let last = path
522         .iter()
523         .copied()
524         // `get_def_path` seems to generate these empty segments for extern blocks.
525         // We can just ignore them.
526         .filter(|segment| !segment.is_empty())
527         // for each segment, find the child item
528         .try_fold(first, |item, segment| {
529             let def_id = item.res.def_id();
530             if let Some(item) = item_child_by_name(tcx, def_id, segment) {
531                 Some(item)
532             } else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
533                 // it is not a child item so check inherent impl items
534                 tcx.inherent_impls(def_id)
535                     .iter()
536                     .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
537             } else {
538                 None
539             }
540         });
541     try_res!(last).res
542 }
543
544 /// Convenience function to get the `DefId` of a trait by path.
545 /// It could be a trait or trait alias.
546 pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
547     match path_to_res(cx, path) {
548         Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
549         _ => None,
550     }
551 }
552
553 /// Gets the `hir::TraitRef` of the trait the given method is implemented for.
554 ///
555 /// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
556 ///
557 /// ```rust
558 /// struct Point(isize, isize);
559 ///
560 /// impl std::ops::Add for Point {
561 ///     type Output = Self;
562 ///
563 ///     fn add(self, other: Self) -> Self {
564 ///         Point(0, 0)
565 ///     }
566 /// }
567 /// ```
568 pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> {
569     // Get the implemented trait for the current function
570     let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
571     if_chain! {
572         if parent_impl != hir::CRATE_HIR_ID;
573         if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
574         if let hir::ItemKind::Impl(impl_) = &item.kind;
575         then { return impl_.of_trait.as_ref(); }
576     }
577     None
578 }
579
580 /// This method will return tuple of projection stack and root of the expression,
581 /// used in `can_mut_borrow_both`.
582 ///
583 /// For example, if `e` represents the `v[0].a.b[x]`
584 /// this method will return a tuple, composed of a `Vec`
585 /// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
586 /// and a `Expr` for root of them, `v`
587 fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
588     let mut result = vec![];
589     let root = loop {
590         match e.kind {
591             ExprKind::Index(ep, _) | ExprKind::Field(ep, _) => {
592                 result.push(e);
593                 e = ep;
594             },
595             _ => break e,
596         };
597     };
598     result.reverse();
599     (result, root)
600 }
601
602 /// Checks if two expressions can be mutably borrowed simultaneously
603 /// and they aren't dependent on borrowing same thing twice
604 pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool {
605     let (s1, r1) = projection_stack(e1);
606     let (s2, r2) = projection_stack(e2);
607     if !eq_expr_value(cx, r1, r2) {
608         return true;
609     }
610     for (x1, x2) in s1.iter().zip(s2.iter()) {
611         match (&x1.kind, &x2.kind) {
612             (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => {
613                 if i1 != i2 {
614                     return true;
615                 }
616             },
617             (ExprKind::Index(_, i1), ExprKind::Index(_, i2)) => {
618                 if !eq_expr_value(cx, i1, i2) {
619                     return false;
620                 }
621             },
622             _ => return false,
623         }
624     }
625     false
626 }
627
628 /// Checks if the top level expression can be moved into a closure as is.
629 pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, jump_targets: &[HirId]) -> bool {
630     match expr.kind {
631         ExprKind::Break(Destination { target_id: Ok(id), .. }, _)
632         | ExprKind::Continue(Destination { target_id: Ok(id), .. })
633             if jump_targets.contains(&id) =>
634         {
635             true
636         },
637         ExprKind::Break(..)
638         | ExprKind::Continue(_)
639         | ExprKind::Ret(_)
640         | ExprKind::Yield(..)
641         | ExprKind::InlineAsm(_)
642         | ExprKind::LlvmInlineAsm(_) => false,
643         // Accessing a field of a local value can only be done if the type isn't
644         // partially moved.
645         ExprKind::Field(base_expr, _)
646             if matches!(
647                 base_expr.kind,
648                 ExprKind::Path(QPath::Resolved(_, Path { res: Res::Local(_), .. }))
649             ) && can_partially_move_ty(cx, cx.typeck_results().expr_ty(base_expr)) =>
650         {
651             // TODO: check if the local has been partially moved. Assume it has for now.
652             false
653         }
654         _ => true,
655     }
656 }
657
658 /// Checks if the expression can be moved into a closure as is.
659 pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
660     struct V<'cx, 'tcx> {
661         cx: &'cx LateContext<'tcx>,
662         loops: Vec<HirId>,
663         allow_closure: bool,
664     }
665     impl Visitor<'tcx> for V<'_, 'tcx> {
666         type Map = ErasedMap<'tcx>;
667         fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
668             NestedVisitorMap::None
669         }
670
671         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
672             if !self.allow_closure {
673                 return;
674             }
675             if let ExprKind::Loop(b, ..) = e.kind {
676                 self.loops.push(e.hir_id);
677                 self.visit_block(b);
678                 self.loops.pop();
679             } else {
680                 self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops);
681                 walk_expr(self, e);
682             }
683         }
684     }
685
686     let mut v = V {
687         cx,
688         allow_closure: true,
689         loops: Vec::new(),
690     };
691     v.visit_expr(expr);
692     v.allow_closure
693 }
694
695 /// Returns the method names and argument list of nested method call expressions that make up
696 /// `expr`. method/span lists are sorted with the most recent call first.
697 pub fn method_calls<'tcx>(
698     expr: &'tcx Expr<'tcx>,
699     max_depth: usize,
700 ) -> (Vec<Symbol>, Vec<&'tcx [Expr<'tcx>]>, Vec<Span>) {
701     let mut method_names = Vec::with_capacity(max_depth);
702     let mut arg_lists = Vec::with_capacity(max_depth);
703     let mut spans = Vec::with_capacity(max_depth);
704
705     let mut current = expr;
706     for _ in 0..max_depth {
707         if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
708             if args.iter().any(|e| e.span.from_expansion()) {
709                 break;
710             }
711             method_names.push(path.ident.name);
712             arg_lists.push(&**args);
713             spans.push(*span);
714             current = &args[0];
715         } else {
716             break;
717         }
718     }
719
720     (method_names, arg_lists, spans)
721 }
722
723 /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
724 ///
725 /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
726 /// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
727 /// containing the `Expr`s for
728 /// `.bar()` and `.baz()`
729 pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
730     let mut current = expr;
731     let mut matched = Vec::with_capacity(methods.len());
732     for method_name in methods.iter().rev() {
733         // method chains are stored last -> first
734         if let ExprKind::MethodCall(path, _, args, _) = current.kind {
735             if path.ident.name.as_str() == *method_name {
736                 if args.iter().any(|e| e.span.from_expansion()) {
737                     return None;
738                 }
739                 matched.push(args); // build up `matched` backwards
740                 current = &args[0]; // go to parent expression
741             } else {
742                 return None;
743             }
744         } else {
745             return None;
746         }
747     }
748     // Reverse `matched` so that it is in the same order as `methods`.
749     matched.reverse();
750     Some(matched)
751 }
752
753 /// Returns `true` if the provided `def_id` is an entrypoint to a program.
754 pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
755     cx.tcx
756         .entry_fn(())
757         .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id)
758 }
759
760 /// Returns `true` if the expression is in the program's `#[panic_handler]`.
761 pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
762     let parent = cx.tcx.hir().get_parent_item(e.hir_id);
763     let def_id = cx.tcx.hir().local_def_id(parent).to_def_id();
764     Some(def_id) == cx.tcx.lang_items().panic_impl()
765 }
766
767 /// Gets the name of the item the expression is in, if available.
768 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
769     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
770     match cx.tcx.hir().find(parent_id) {
771         Some(
772             Node::Item(Item { ident, .. })
773             | Node::TraitItem(TraitItem { ident, .. })
774             | Node::ImplItem(ImplItem { ident, .. }),
775         ) => Some(ident.name),
776         _ => None,
777     }
778 }
779
780 pub struct ContainsName {
781     pub name: Symbol,
782     pub result: bool,
783 }
784
785 impl<'tcx> Visitor<'tcx> for ContainsName {
786     type Map = Map<'tcx>;
787
788     fn visit_name(&mut self, _: Span, name: Symbol) {
789         if self.name == name {
790             self.result = true;
791         }
792     }
793     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
794         NestedVisitorMap::None
795     }
796 }
797
798 /// Checks if an `Expr` contains a certain name.
799 pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
800     let mut cn = ContainsName { name, result: false };
801     cn.visit_expr(expr);
802     cn.result
803 }
804
805 /// Returns `true` if `expr` contains a return expression
806 pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
807     struct RetCallFinder {
808         found: bool,
809     }
810
811     impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder {
812         type Map = Map<'tcx>;
813
814         fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
815             if self.found {
816                 return;
817             }
818             if let hir::ExprKind::Ret(..) = &expr.kind {
819                 self.found = true;
820             } else {
821                 hir::intravisit::walk_expr(self, expr);
822             }
823         }
824
825         fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
826             hir::intravisit::NestedVisitorMap::None
827         }
828     }
829
830     let mut visitor = RetCallFinder { found: false };
831     visitor.visit_expr(expr);
832     visitor.found
833 }
834
835 struct FindMacroCalls<'a, 'b> {
836     names: &'a [&'b str],
837     result: Vec<Span>,
838 }
839
840 impl<'a, 'b, 'tcx> Visitor<'tcx> for FindMacroCalls<'a, 'b> {
841     type Map = Map<'tcx>;
842
843     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
844         if self.names.iter().any(|fun| is_expn_of(expr.span, fun).is_some()) {
845             self.result.push(expr.span);
846         }
847         // and check sub-expressions
848         intravisit::walk_expr(self, expr);
849     }
850
851     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
852         NestedVisitorMap::None
853     }
854 }
855
856 /// Finds calls of the specified macros in a function body.
857 pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> {
858     let mut fmc = FindMacroCalls {
859         names,
860         result: Vec::new(),
861     };
862     fmc.visit_expr(&body.value);
863     fmc.result
864 }
865
866 /// Extends the span to the beginning of the spans line, incl. whitespaces.
867 ///
868 /// ```rust,ignore
869 ///        let x = ();
870 /// //             ^^
871 /// // will be converted to
872 ///        let x = ();
873 /// // ^^^^^^^^^^^^^^
874 /// ```
875 fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
876     let span = original_sp(span, DUMMY_SP);
877     let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
878     let line_no = source_map_and_line.line;
879     let line_start = source_map_and_line.sf.lines[line_no];
880     Span::new(line_start, span.hi(), span.ctxt())
881 }
882
883 /// Gets the parent node, if any.
884 pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
885     tcx.hir().parent_iter(id).next().map(|(_, node)| node)
886 }
887
888 /// Gets the parent expression, if any â€“- this is useful to constrain a lint.
889 pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
890     get_parent_expr_for_hir(cx, e.hir_id)
891 }
892
893 /// This retrieves the parent for the given `HirId` if it's an expression. This is useful for
894 /// constraint lints
895 pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> {
896     match get_parent_node(cx.tcx, hir_id) {
897         Some(Node::Expr(parent)) => Some(parent),
898         _ => None,
899     }
900 }
901
902 pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
903     let map = &cx.tcx.hir();
904     let enclosing_node = map
905         .get_enclosing_scope(hir_id)
906         .and_then(|enclosing_id| map.find(enclosing_id));
907     enclosing_node.and_then(|node| match node {
908         Node::Block(block) => Some(block),
909         Node::Item(&Item {
910             kind: ItemKind::Fn(_, _, eid),
911             ..
912         })
913         | Node::ImplItem(&ImplItem {
914             kind: ImplItemKind::Fn(_, eid),
915             ..
916         }) => match cx.tcx.hir().body(eid).value.kind {
917             ExprKind::Block(block, _) => Some(block),
918             _ => None,
919         },
920         _ => None,
921     })
922 }
923
924 /// Gets the loop or closure enclosing the given expression, if any.
925 pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
926     let map = tcx.hir();
927     for (_, node) in map.parent_iter(expr.hir_id) {
928         match node {
929             Node::Expr(
930                 e
931                 @
932                 Expr {
933                     kind: ExprKind::Loop(..) | ExprKind::Closure(..),
934                     ..
935                 },
936             ) => return Some(e),
937             Node::Expr(_) | Node::Stmt(_) | Node::Block(_) | Node::Local(_) | Node::Arm(_) => (),
938             _ => break,
939         }
940     }
941     None
942 }
943
944 /// Gets the parent node if it's an impl block.
945 pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
946     let map = tcx.hir();
947     match map.parent_iter(id).next() {
948         Some((
949             _,
950             Node::Item(Item {
951                 kind: ItemKind::Impl(imp),
952                 ..
953             }),
954         )) => Some(imp),
955         _ => None,
956     }
957 }
958
959 /// Checks if the given expression is the else clause of either an `if` or `if let` expression.
960 pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
961     let map = tcx.hir();
962     let mut iter = map.parent_iter(expr.hir_id);
963     match iter.next() {
964         Some((arm_id, Node::Arm(..))) => matches!(
965             iter.next(),
966             Some((
967                 _,
968                 Node::Expr(Expr {
969                     kind: ExprKind::Match(_, [_, else_arm], MatchSource::IfLetDesugar { .. }),
970                     ..
971                 })
972             ))
973             if else_arm.hir_id == arm_id
974         ),
975         Some((
976             _,
977             Node::Expr(Expr {
978                 kind: ExprKind::If(_, _, Some(else_expr)),
979                 ..
980             }),
981         )) => else_expr.hir_id == expr.hir_id,
982         _ => false,
983     }
984 }
985
986 /// Checks whether the given expression is a constant integer of the given value.
987 /// unlike `is_integer_literal`, this version does const folding
988 pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
989     if is_integer_literal(e, value) {
990         return true;
991     }
992     let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id));
993     if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
994         value == v
995     } else {
996         false
997     }
998 }
999
1000 /// Checks whether the given expression is a constant literal of the given value.
1001 pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
1002     // FIXME: use constant folding
1003     if let ExprKind::Lit(ref spanned) = expr.kind {
1004         if let LitKind::Int(v, _) = spanned.node {
1005             return v == value;
1006         }
1007     }
1008     false
1009 }
1010
1011 /// Returns `true` if the given `Expr` has been coerced before.
1012 ///
1013 /// Examples of coercions can be found in the Nomicon at
1014 /// <https://doc.rust-lang.org/nomicon/coercions.html>.
1015 ///
1016 /// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
1017 /// information on adjustments and coercions.
1018 pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
1019     cx.typeck_results().adjustments().get(e.hir_id).is_some()
1020 }
1021
1022 /// Returns the pre-expansion span if is this comes from an expansion of the
1023 /// macro `name`.
1024 /// See also `is_direct_expn_of`.
1025 #[must_use]
1026 pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
1027     loop {
1028         if span.from_expansion() {
1029             let data = span.ctxt().outer_expn_data();
1030             let new_span = data.call_site;
1031
1032             if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1033                 if mac_name.as_str() == name {
1034                     return Some(new_span);
1035                 }
1036             }
1037
1038             span = new_span;
1039         } else {
1040             return None;
1041         }
1042     }
1043 }
1044
1045 /// Returns the pre-expansion span if the span directly comes from an expansion
1046 /// of the macro `name`.
1047 /// The difference with `is_expn_of` is that in
1048 /// ```rust,ignore
1049 /// foo!(bar!(42));
1050 /// ```
1051 /// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
1052 /// `bar!` by
1053 /// `is_direct_expn_of`.
1054 #[must_use]
1055 pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
1056     if span.from_expansion() {
1057         let data = span.ctxt().outer_expn_data();
1058         let new_span = data.call_site;
1059
1060         if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
1061             if mac_name.as_str() == name {
1062                 return Some(new_span);
1063             }
1064         }
1065     }
1066
1067     None
1068 }
1069
1070 /// Convenience function to get the return type of a function.
1071 pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
1072     let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
1073     let ret_ty = cx.tcx.fn_sig(fn_def_id).output();
1074     cx.tcx.erase_late_bound_regions(ret_ty)
1075 }
1076
1077 /// Checks if an expression is constructing a tuple-like enum variant or struct
1078 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1079     if let ExprKind::Call(fun, _) = expr.kind {
1080         if let ExprKind::Path(ref qp) = fun.kind {
1081             let res = cx.qpath_res(qp, fun.hir_id);
1082             return match res {
1083                 def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
1084                 def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
1085                 _ => false,
1086             };
1087         }
1088     }
1089     false
1090 }
1091
1092 /// Returns `true` if a pattern is refutable.
1093 // TODO: should be implemented using rustc/mir_build/thir machinery
1094 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
1095     fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
1096         matches!(
1097             cx.qpath_res(qpath, id),
1098             def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
1099         )
1100     }
1101
1102     fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
1103         i.into_iter().any(|pat| is_refutable(cx, pat))
1104     }
1105
1106     match pat.kind {
1107         PatKind::Wild => false,
1108         PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
1109         PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
1110         PatKind::Lit(..) | PatKind::Range(..) => true,
1111         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
1112         PatKind::Or(pats) => {
1113             // TODO: should be the honest check, that pats is exhaustive set
1114             are_refutable(cx, pats)
1115         },
1116         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
1117         PatKind::Struct(ref qpath, fields, _) => {
1118             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
1119         },
1120         PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
1121         PatKind::Slice(head, middle, tail) => {
1122             match &cx.typeck_results().node_type(pat.hir_id).kind() {
1123                 rustc_ty::Slice(..) => {
1124                     // [..] is the only irrefutable slice pattern.
1125                     !head.is_empty() || middle.is_none() || !tail.is_empty()
1126                 },
1127                 rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
1128                 _ => {
1129                     // unreachable!()
1130                     true
1131                 },
1132             }
1133         },
1134     }
1135 }
1136
1137 /// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call
1138 /// the function once on the given pattern.
1139 pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
1140     if let PatKind::Or(pats) = pat.kind {
1141         pats.iter().for_each(f);
1142     } else {
1143         f(pat);
1144     }
1145 }
1146
1147 /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
1148 /// implementations have.
1149 pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
1150     attrs.iter().any(|attr| attr.has_name(sym::automatically_derived))
1151 }
1152
1153 /// Remove blocks around an expression.
1154 ///
1155 /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return
1156 /// themselves.
1157 pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
1158     while let ExprKind::Block(block, ..) = expr.kind {
1159         match (block.stmts.is_empty(), block.expr.as_ref()) {
1160             (true, Some(e)) => expr = e,
1161             _ => break,
1162         }
1163     }
1164     expr
1165 }
1166
1167 pub fn is_self(slf: &Param<'_>) -> bool {
1168     if let PatKind::Binding(.., name, _) = slf.pat.kind {
1169         name.name == kw::SelfLower
1170     } else {
1171         false
1172     }
1173 }
1174
1175 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
1176     if_chain! {
1177         if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind;
1178         if let Res::SelfTy(..) = path.res;
1179         then {
1180             return true
1181         }
1182     }
1183     false
1184 }
1185
1186 pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator<Item = &'tcx Param<'tcx>> {
1187     (0..decl.inputs.len()).map(move |i| &body.params[i])
1188 }
1189
1190 /// Checks if a given expression is a match expression expanded from the `?`
1191 /// operator or the `try` macro.
1192 pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
1193     fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1194         if_chain! {
1195             if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind;
1196             if is_lang_ctor(cx, path, ResultOk);
1197             if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
1198             if path_to_local_id(arm.body, hir_id);
1199             then {
1200                 return true;
1201             }
1202         }
1203         false
1204     }
1205
1206     fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
1207         if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
1208             is_lang_ctor(cx, path, ResultErr)
1209         } else {
1210             false
1211         }
1212     }
1213
1214     if let ExprKind::Match(_, arms, ref source) = expr.kind {
1215         // desugared from a `?` operator
1216         if let MatchSource::TryDesugar = *source {
1217             return Some(expr);
1218         }
1219
1220         if_chain! {
1221             if arms.len() == 2;
1222             if arms[0].guard.is_none();
1223             if arms[1].guard.is_none();
1224             if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) ||
1225                 (is_ok(cx, &arms[1]) && is_err(cx, &arms[0]));
1226             then {
1227                 return Some(expr);
1228             }
1229         }
1230     }
1231
1232     None
1233 }
1234
1235 /// Returns `true` if the lint is allowed in the current context
1236 ///
1237 /// Useful for skipping long running code when it's unnecessary
1238 pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
1239     cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
1240 }
1241
1242 pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
1243     while let PatKind::Ref(subpat, _) = pat.kind {
1244         pat = subpat;
1245     }
1246     pat
1247 }
1248
1249 pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 {
1250     Integer::from_int_ty(&tcx, ity).size().bits()
1251 }
1252
1253 #[allow(clippy::cast_possible_wrap)]
1254 /// Turn a constant int byte representation into an i128
1255 pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 {
1256     let amt = 128 - int_bits(tcx, ity);
1257     ((u as i128) << amt) >> amt
1258 }
1259
1260 #[allow(clippy::cast_sign_loss)]
1261 /// clip unused bytes
1262 pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 {
1263     let amt = 128 - int_bits(tcx, ity);
1264     ((u as u128) << amt) >> amt
1265 }
1266
1267 /// clip unused bytes
1268 pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 {
1269     let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
1270     let amt = 128 - bits;
1271     (u << amt) >> amt
1272 }
1273
1274 pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
1275     let map = &tcx.hir();
1276     let mut prev_enclosing_node = None;
1277     let mut enclosing_node = node;
1278     while Some(enclosing_node) != prev_enclosing_node {
1279         if is_automatically_derived(map.attrs(enclosing_node)) {
1280             return true;
1281         }
1282         prev_enclosing_node = Some(enclosing_node);
1283         enclosing_node = map.get_parent_item(enclosing_node);
1284     }
1285     false
1286 }
1287
1288 /// Matches a function call with the given path and returns the arguments.
1289 ///
1290 /// Usage:
1291 ///
1292 /// ```rust,ignore
1293 /// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
1294 /// ```
1295 pub fn match_function_call<'tcx>(
1296     cx: &LateContext<'tcx>,
1297     expr: &'tcx Expr<'_>,
1298     path: &[&str],
1299 ) -> Option<&'tcx [Expr<'tcx>]> {
1300     if_chain! {
1301         if let ExprKind::Call(fun, args) = expr.kind;
1302         if let ExprKind::Path(ref qpath) = fun.kind;
1303         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
1304         if match_def_path(cx, fun_def_id, path);
1305         then {
1306             return Some(args)
1307         }
1308     };
1309     None
1310 }
1311
1312 /// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
1313 /// any.
1314 ///
1315 /// Please use `match_any_diagnostic_items` if the targets are all diagnostic items.
1316 pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]]) -> Option<usize> {
1317     let search_path = cx.get_def_path(did);
1318     paths
1319         .iter()
1320         .position(|p| p.iter().map(|x| Symbol::intern(x)).eq(search_path.iter().copied()))
1321 }
1322
1323 /// Checks if the given `DefId` matches any of provided diagnostic items. Returns the index of
1324 /// matching path, if any.
1325 pub fn match_any_diagnostic_items(cx: &LateContext<'_>, def_id: DefId, diag_items: &[Symbol]) -> Option<usize> {
1326     diag_items
1327         .iter()
1328         .position(|item| cx.tcx.is_diagnostic_item(*item, def_id))
1329 }
1330
1331 /// Checks if the given `DefId` matches the path.
1332 pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool {
1333     // We should probably move to Symbols in Clippy as well rather than interning every time.
1334     let path = cx.get_def_path(did);
1335     syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied())
1336 }
1337
1338 pub fn match_panic_call(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
1339     if let ExprKind::Call(func, [arg]) = expr.kind {
1340         expr_path_res(cx, func)
1341             .opt_def_id()
1342             .map_or(false, |id| match_panic_def_id(cx, id))
1343             .then(|| arg)
1344     } else {
1345         None
1346     }
1347 }
1348
1349 pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool {
1350     match_any_def_paths(
1351         cx,
1352         did,
1353         &[
1354             &paths::BEGIN_PANIC,
1355             &paths::BEGIN_PANIC_FMT,
1356             &paths::PANIC_ANY,
1357             &paths::PANICKING_PANIC,
1358             &paths::PANICKING_PANIC_FMT,
1359             &paths::PANICKING_PANIC_STR,
1360         ],
1361     )
1362     .is_some()
1363 }
1364
1365 /// Returns the list of condition expressions and the list of blocks in a
1366 /// sequence of `if/else`.
1367 /// E.g., this returns `([a, b], [c, d, e])` for the expression
1368 /// `if a { c } else if b { d } else { e }`.
1369 pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) {
1370     let mut conds = Vec::new();
1371     let mut blocks: Vec<&Block<'_>> = Vec::new();
1372
1373     while let ExprKind::If(cond, then_expr, ref else_expr) = expr.kind {
1374         conds.push(cond);
1375         if let ExprKind::Block(block, _) = then_expr.kind {
1376             blocks.push(block);
1377         } else {
1378             panic!("ExprKind::If node is not an ExprKind::Block");
1379         }
1380
1381         if let Some(else_expr) = *else_expr {
1382             expr = else_expr;
1383         } else {
1384             break;
1385         }
1386     }
1387
1388     // final `else {..}`
1389     if !blocks.is_empty() {
1390         if let ExprKind::Block(block, _) = expr.kind {
1391             blocks.push(block);
1392         }
1393     }
1394
1395     (conds, blocks)
1396 }
1397
1398 /// Checks if the given function kind is an async function.
1399 pub fn is_async_fn(kind: FnKind<'_>) -> bool {
1400     matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
1401 }
1402
1403 /// Peels away all the compiler generated code surrounding the body of an async function,
1404 pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
1405     if let ExprKind::Call(
1406         _,
1407         &[Expr {
1408             kind: ExprKind::Closure(_, _, body, _, _),
1409             ..
1410         }],
1411     ) = body.value.kind
1412     {
1413         if let ExprKind::Block(
1414             Block {
1415                 stmts: [],
1416                 expr:
1417                     Some(Expr {
1418                         kind: ExprKind::DropTemps(expr),
1419                         ..
1420                     }),
1421                 ..
1422             },
1423             _,
1424         ) = tcx.hir().body(body).value.kind
1425         {
1426             return Some(expr);
1427         }
1428     };
1429     None
1430 }
1431
1432 // Finds the `#[must_use]` attribute, if any
1433 pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
1434     attrs.iter().find(|a| a.has_name(sym::must_use))
1435 }
1436
1437 // check if expr is calling method or function with #[must_use] attribute
1438 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1439     let did = match expr.kind {
1440         ExprKind::Call(path, _) => if_chain! {
1441             if let ExprKind::Path(ref qpath) = path.kind;
1442             if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
1443             then {
1444                 Some(did)
1445             } else {
1446                 None
1447             }
1448         },
1449         ExprKind::MethodCall(_, _, _, _) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1450         _ => None,
1451     };
1452
1453     did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some())
1454 }
1455
1456 /// Checks if an expression represents the identity function
1457 /// Only examines closures and `std::convert::identity`
1458 pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
1459     /// Checks if a function's body represents the identity function. Looks for bodies of the form:
1460     /// * `|x| x`
1461     /// * `|x| return x`
1462     /// * `|x| { return x }`
1463     /// * `|x| { return x; }`
1464     fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
1465         let id = if_chain! {
1466             if let [param] = func.params;
1467             if let PatKind::Binding(_, id, _, _) = param.pat.kind;
1468             then {
1469                 id
1470             } else {
1471                 return false;
1472             }
1473         };
1474
1475         let mut expr = &func.value;
1476         loop {
1477             match expr.kind {
1478                 #[rustfmt::skip]
1479                 ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, )
1480                 | ExprKind::Ret(Some(e)) => expr = e,
1481                 #[rustfmt::skip]
1482                 ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => {
1483                     if_chain! {
1484                         if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
1485                         if let ExprKind::Ret(Some(ret_val)) = e.kind;
1486                         then {
1487                             expr = ret_val;
1488                         } else {
1489                             return false;
1490                         }
1491                     }
1492                 },
1493                 _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
1494             }
1495         }
1496     }
1497
1498     match expr.kind {
1499         ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
1500         ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY),
1501         _ => false,
1502     }
1503 }
1504
1505 /// Gets the node where an expression is either used, or it's type is unified with another branch.
1506 pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
1507     let map = tcx.hir();
1508     let mut child_id = expr.hir_id;
1509     let mut iter = map.parent_iter(child_id);
1510     loop {
1511         match iter.next() {
1512             None => break None,
1513             Some((id, Node::Block(_))) => child_id = id,
1514             Some((id, Node::Arm(arm))) if arm.body.hir_id == child_id => child_id = id,
1515             Some((_, Node::Expr(expr))) => match expr.kind {
1516                 ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id,
1517                 ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id,
1518                 ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None,
1519                 _ => break Some(Node::Expr(expr)),
1520             },
1521             Some((_, node)) => break Some(node),
1522         }
1523     }
1524 }
1525
1526 /// Checks if the result of an expression is used, or it's type is unified with another branch.
1527 pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1528     !matches!(
1529         get_expr_use_or_unification_node(tcx, expr),
1530         None | Some(Node::Stmt(Stmt {
1531             kind: StmtKind::Expr(_)
1532                 | StmtKind::Semi(_)
1533                 | StmtKind::Local(Local {
1534                     pat: Pat {
1535                         kind: PatKind::Wild,
1536                         ..
1537                     },
1538                     ..
1539                 }),
1540             ..
1541         }))
1542     )
1543 }
1544
1545 /// Checks if the expression is the final expression returned from a block.
1546 pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
1547     matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..)))
1548 }
1549
1550 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
1551     cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
1552         if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
1553             attr.path == sym::no_std
1554         } else {
1555             false
1556         }
1557     })
1558 }
1559
1560 /// Check if parent of a hir node is a trait implementation block.
1561 /// For example, `f` in
1562 /// ```rust,ignore
1563 /// impl Trait for S {
1564 ///     fn f() {}
1565 /// }
1566 /// ```
1567 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
1568     if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
1569         matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
1570     } else {
1571         false
1572     }
1573 }
1574
1575 /// Check if it's even possible to satisfy the `where` clause for the item.
1576 ///
1577 /// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example:
1578 ///
1579 /// ```ignore
1580 /// fn foo() where i32: Iterator {
1581 ///     for _ in 2i32 {}
1582 /// }
1583 /// ```
1584 pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
1585     use rustc_trait_selection::traits;
1586     let predicates = cx
1587         .tcx
1588         .predicates_of(did)
1589         .predicates
1590         .iter()
1591         .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
1592     traits::impossible_predicates(
1593         cx.tcx,
1594         traits::elaborate_predicates(cx.tcx, predicates)
1595             .map(|o| o.predicate)
1596             .collect::<Vec<_>>(),
1597     )
1598 }
1599
1600 /// Returns the `DefId` of the callee if the given expression is a function or method call.
1601 pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
1602     match &expr.kind {
1603         ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
1604         ExprKind::Call(
1605             Expr {
1606                 kind: ExprKind::Path(qpath),
1607                 hir_id: path_hir_id,
1608                 ..
1609             },
1610             ..,
1611         ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
1612         _ => None,
1613     }
1614 }
1615
1616 /// Returns Option<String> where String is a textual representation of the type encapsulated in the
1617 /// slice iff the given expression is a slice of primitives (as defined in the
1618 /// `is_recursively_primitive_type` function) and None otherwise.
1619 pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
1620     let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
1621     let expr_kind = expr_type.kind();
1622     let is_primitive = match expr_kind {
1623         rustc_ty::Slice(element_type) => is_recursively_primitive_type(element_type),
1624         rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => {
1625             if let rustc_ty::Slice(element_type) = inner_ty.kind() {
1626                 is_recursively_primitive_type(element_type)
1627             } else {
1628                 unreachable!()
1629             }
1630         },
1631         _ => false,
1632     };
1633
1634     if is_primitive {
1635         // if we have wrappers like Array, Slice or Tuple, print these
1636         // and get the type enclosed in the slice ref
1637         match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
1638             rustc_ty::Slice(..) => return Some("slice".into()),
1639             rustc_ty::Array(..) => return Some("array".into()),
1640             rustc_ty::Tuple(..) => return Some("tuple".into()),
1641             _ => {
1642                 // is_recursively_primitive_type() should have taken care
1643                 // of the rest and we can rely on the type that is found
1644                 let refs_peeled = expr_type.peel_refs();
1645                 return Some(refs_peeled.walk().last().unwrap().to_string());
1646             },
1647         }
1648     }
1649     None
1650 }
1651
1652 /// returns list of all pairs (a, b) from `exprs` such that `eq(a, b)`
1653 /// `hash` must be comformed with `eq`
1654 pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
1655 where
1656     Hash: Fn(&T) -> u64,
1657     Eq: Fn(&T, &T) -> bool,
1658 {
1659     match exprs {
1660         [a, b] if eq(a, b) => return vec![(a, b)],
1661         _ if exprs.len() <= 2 => return vec![],
1662         _ => {},
1663     }
1664
1665     let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
1666
1667     let mut map: UnhashMap<u64, Vec<&_>> =
1668         UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
1669
1670     for expr in exprs {
1671         match map.entry(hash(expr)) {
1672             Entry::Occupied(mut o) => {
1673                 for o in o.get() {
1674                     if eq(o, expr) {
1675                         match_expr_list.push((o, expr));
1676                     }
1677                 }
1678                 o.get_mut().push(expr);
1679             },
1680             Entry::Vacant(v) => {
1681                 v.insert(vec![expr]);
1682             },
1683         }
1684     }
1685
1686     match_expr_list
1687 }
1688
1689 /// Peels off all references on the pattern. Returns the underlying pattern and the number of
1690 /// references removed.
1691 pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
1692     fn peel(pat: &'a Pat<'a>, count: usize) -> (&'a Pat<'a>, usize) {
1693         if let PatKind::Ref(pat, _) = pat.kind {
1694             peel(pat, count + 1)
1695         } else {
1696             (pat, count)
1697         }
1698     }
1699     peel(pat, 0)
1700 }
1701
1702 /// Peels of expressions while the given closure returns `Some`.
1703 pub fn peel_hir_expr_while<'tcx>(
1704     mut expr: &'tcx Expr<'tcx>,
1705     mut f: impl FnMut(&'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>>,
1706 ) -> &'tcx Expr<'tcx> {
1707     while let Some(e) = f(expr) {
1708         expr = e;
1709     }
1710     expr
1711 }
1712
1713 /// Peels off up to the given number of references on the expression. Returns the underlying
1714 /// expression and the number of references removed.
1715 pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
1716     let mut remaining = count;
1717     let e = peel_hir_expr_while(expr, |e| match e.kind {
1718         ExprKind::AddrOf(BorrowKind::Ref, _, e) if remaining != 0 => {
1719             remaining -= 1;
1720             Some(e)
1721         },
1722         _ => None,
1723     });
1724     (e, count - remaining)
1725 }
1726
1727 /// Peels off all references on the expression. Returns the underlying expression and the number of
1728 /// references removed.
1729 pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
1730     let mut count = 0;
1731     let e = peel_hir_expr_while(expr, |e| match e.kind {
1732         ExprKind::AddrOf(BorrowKind::Ref, _, e) => {
1733             count += 1;
1734             Some(e)
1735         },
1736         _ => None,
1737     });
1738     (e, count)
1739 }
1740
1741 /// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
1742 /// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
1743 pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
1744     loop {
1745         match expr.kind {
1746             ExprKind::AddrOf(_, _, e) => expr = e,
1747             ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
1748             _ => break,
1749         }
1750     }
1751     expr
1752 }
1753
1754 #[macro_export]
1755 macro_rules! unwrap_cargo_metadata {
1756     ($cx: ident, $lint: ident, $deps: expr) => {{
1757         let mut command = cargo_metadata::MetadataCommand::new();
1758         if !$deps {
1759             command.no_deps();
1760         }
1761
1762         match command.exec() {
1763             Ok(metadata) => metadata,
1764             Err(err) => {
1765                 span_lint($cx, $lint, DUMMY_SP, &format!("could not read cargo metadata: {}", err));
1766                 return;
1767             },
1768         }
1769     }};
1770 }
1771
1772 pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
1773     if_chain! {
1774         if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
1775         if let Res::Def(_, def_id) = path.res;
1776         then {
1777             cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr)
1778         } else {
1779             false
1780         }
1781     }
1782 }
1783
1784 /// Checks whether item either has `test` attribute applied, or
1785 /// is a module with `test` in its name.
1786 pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
1787     if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) {
1788         if tcx.has_attr(def_id.to_def_id(), sym::test) {
1789             return true;
1790         }
1791     }
1792
1793     matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
1794 }
1795
1796 macro_rules! op_utils {
1797     ($($name:ident $assign:ident)*) => {
1798         /// Binary operation traits like `LangItem::Add`
1799         pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
1800
1801         /// Operator-Assign traits like `LangItem::AddAssign`
1802         pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
1803
1804         /// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
1805         pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
1806             match kind {
1807                 $(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
1808                 _ => None,
1809             }
1810         }
1811     };
1812 }
1813
1814 op_utils! {
1815     Add    AddAssign
1816     Sub    SubAssign
1817     Mul    MulAssign
1818     Div    DivAssign
1819     Rem    RemAssign
1820     BitXor BitXorAssign
1821     BitAnd BitAndAssign
1822     BitOr  BitOrAssign
1823     Shl    ShlAssign
1824     Shr    ShrAssign
1825 }