about summary refs log tree commit diff
path: root/clippy_lints/src
diff options
context:
space:
mode:
authorflip1995 <philipp.krones@embecosm.com>2021-04-08 17:18:19 +0200
committerflip1995 <philipp.krones@embecosm.com>2021-04-08 17:36:41 +0200
commitffa2b7da2942a4dd27375a339582d78b7bb154e7 (patch)
tree69c13cbb6464322e4ed4e7ba09de08edcac85e01 /clippy_lints/src
parentcde58f7174cd83752b3c0a00a970dcc07c511077 (diff)
parentdb6ea84f8790e9e8488ee917ab72af28a4eccf61 (diff)
downloadrust-ffa2b7da2942a4dd27375a339582d78b7bb154e7.tar.gz
rust-ffa2b7da2942a4dd27375a339582d78b7bb154e7.zip
Merge remote-tracking branch 'upstream/master' into rustup
Diffstat (limited to 'clippy_lints/src')
-rw-r--r--clippy_lints/src/absurd_extreme_comparisons.rs173
-rw-r--r--clippy_lints/src/assertions_on_constants.rs12
-rw-r--r--clippy_lints/src/atomic_ordering.rs6
-rw-r--r--clippy_lints/src/attrs.rs118
-rw-r--r--clippy_lints/src/await_holding_invalid.rs2
-rw-r--r--clippy_lints/src/bytecount.rs90
-rw-r--r--clippy_lints/src/cargo_common_metadata.rs10
-rw-r--r--clippy_lints/src/casts/cast_ptr_alignment.rs2
-rw-r--r--clippy_lints/src/casts/cast_sign_loss.rs6
-rw-r--r--clippy_lints/src/casts/mod.rs2
-rw-r--r--clippy_lints/src/checked_conversions.rs22
-rw-r--r--clippy_lints/src/cognitive_complexity.rs2
-rw-r--r--clippy_lints/src/collapsible_match.rs2
-rw-r--r--clippy_lints/src/comparison_chain.rs6
-rw-r--r--clippy_lints/src/copies.rs488
-rw-r--r--clippy_lints/src/create_dir.rs2
-rw-r--r--clippy_lints/src/default.rs53
-rw-r--r--clippy_lints/src/default_numeric_fallback.rs2
-rw-r--r--clippy_lints/src/derive.rs91
-rw-r--r--clippy_lints/src/doc.rs20
-rw-r--r--clippy_lints/src/double_comparison.rs4
-rw-r--r--clippy_lints/src/double_parens.rs6
-rw-r--r--clippy_lints/src/drop_forget_ref.rs2
-rw-r--r--clippy_lints/src/duration_subsec.rs4
-rw-r--r--clippy_lints/src/entry.rs16
-rw-r--r--clippy_lints/src/eq_op.rs14
-rw-r--r--clippy_lints/src/erasing_op.rs2
-rw-r--r--clippy_lints/src/eta_reduction.rs18
-rw-r--r--clippy_lints/src/eval_order_dependence.rs18
-rw-r--r--clippy_lints/src/excessive_bools.rs6
-rw-r--r--clippy_lints/src/exit.rs18
-rw-r--r--clippy_lints/src/explicit_write.rs10
-rw-r--r--clippy_lints/src/fallible_impl_from.rs4
-rw-r--r--clippy_lints/src/float_equality_without_abs.rs6
-rw-r--r--clippy_lints/src/float_literal.rs2
-rw-r--r--clippy_lints/src/floating_point_arithmetic.rs42
-rw-r--r--clippy_lints/src/format.rs38
-rw-r--r--clippy_lints/src/formatting.rs3
-rw-r--r--clippy_lints/src/functions.rs738
-rw-r--r--clippy_lints/src/functions/mod.rs267
-rw-r--r--clippy_lints/src/functions/must_use.rs272
-rw-r--r--clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs124
-rw-r--r--clippy_lints/src/functions/result_unit_err.rs66
-rw-r--r--clippy_lints/src/functions/too_many_arguments.rs73
-rw-r--r--clippy_lints/src/functions/too_many_lines.rs68
-rw-r--r--clippy_lints/src/get_last_with_len.rs2
-rw-r--r--clippy_lints/src/identity_op.rs2
-rw-r--r--clippy_lints/src/if_let_mutex.rs28
-rw-r--r--clippy_lints/src/if_let_some_result.rs6
-rw-r--r--clippy_lints/src/if_then_some_else_none.rs12
-rw-r--r--clippy_lints/src/implicit_hasher.rs377
-rw-r--r--clippy_lints/src/implicit_return.rs4
-rw-r--r--clippy_lints/src/implicit_saturating_sub.rs16
-rw-r--r--clippy_lints/src/indexing_slicing.rs2
-rw-r--r--clippy_lints/src/infinite_iter.rs12
-rw-r--r--clippy_lints/src/inherent_impl.rs4
-rw-r--r--clippy_lints/src/invalid_upcast_comparisons.rs221
-rw-r--r--clippy_lints/src/large_enum_variant.rs2
-rw-r--r--clippy_lints/src/len_zero.rs99
-rw-r--r--clippy_lints/src/let_if_seq.rs24
-rw-r--r--clippy_lints/src/let_underscore.rs2
-rw-r--r--clippy_lints/src/lib.rs2463
-rw-r--r--clippy_lints/src/lifetimes.rs20
-rw-r--r--clippy_lints/src/literal_representation.rs4
-rw-r--r--clippy_lints/src/loops/explicit_counter_loop.rs2
-rw-r--r--clippy_lints/src/loops/for_kv_map.rs4
-rw-r--r--clippy_lints/src/loops/manual_flatten.rs7
-rw-r--r--clippy_lints/src/loops/manual_memcpy.rs21
-rw-r--r--clippy_lints/src/loops/mod.rs6
-rw-r--r--clippy_lints/src/loops/needless_collect.rs126
-rw-r--r--clippy_lints/src/loops/needless_range_loop.rs92
-rw-r--r--clippy_lints/src/loops/never_loop.rs46
-rw-r--r--clippy_lints/src/loops/same_item_push.rs139
-rw-r--r--clippy_lints/src/loops/single_element_loop.rs4
-rw-r--r--clippy_lints/src/loops/utils.rs26
-rw-r--r--clippy_lints/src/loops/while_immutable_condition.rs17
-rw-r--r--clippy_lints/src/loops/while_let_loop.rs12
-rw-r--r--clippy_lints/src/loops/while_let_on_iterator.rs12
-rw-r--r--clippy_lints/src/macro_use.rs6
-rw-r--r--clippy_lints/src/manual_map.rs13
-rw-r--r--clippy_lints/src/manual_non_exhaustive.rs16
-rw-r--r--clippy_lints/src/manual_strip.rs4
-rw-r--r--clippy_lints/src/map_clone.rs14
-rw-r--r--clippy_lints/src/map_err_ignore.rs2
-rw-r--r--clippy_lints/src/map_identity.rs12
-rw-r--r--clippy_lints/src/map_unit_fn.rs24
-rw-r--r--clippy_lints/src/match_on_vec_items.rs4
-rw-r--r--clippy_lints/src/matches.rs126
-rw-r--r--clippy_lints/src/mem_discriminant.rs4
-rw-r--r--clippy_lints/src/mem_forget.rs2
-rw-r--r--clippy_lints/src/mem_replace.rs63
-rw-r--r--clippy_lints/src/methods/bind_instead_of_map.rs169
-rw-r--r--clippy_lints/src/methods/bytes_nth.rs55
-rw-r--r--clippy_lints/src/methods/chars_cmp.rs2
-rw-r--r--clippy_lints/src/methods/clone_on_copy.rs118
-rw-r--r--clippy_lints/src/methods/expect_fun_call.rs8
-rw-r--r--clippy_lints/src/methods/expect_used.rs4
-rw-r--r--clippy_lints/src/methods/filetype_is_file.rs4
-rw-r--r--clippy_lints/src/methods/filter_map.rs223
-rw-r--r--clippy_lints/src/methods/filter_map_identity.rs15
-rw-r--r--clippy_lints/src/methods/filter_map_next.rs7
-rw-r--r--clippy_lints/src/methods/filter_next.rs11
-rw-r--r--clippy_lints/src/methods/flat_map_identity.rs6
-rw-r--r--clippy_lints/src/methods/from_iter_instead_of_collect.rs2
-rw-r--r--clippy_lints/src/methods/get_unwrap.rs20
-rw-r--r--clippy_lints/src/methods/implicit_clone.rs2
-rw-r--r--clippy_lints/src/methods/iter_cloned_collect.rs4
-rw-r--r--clippy_lints/src/methods/iter_count.rs8
-rw-r--r--clippy_lints/src/methods/iter_next_slice.rs6
-rw-r--r--clippy_lints/src/methods/iter_nth.rs14
-rw-r--r--clippy_lints/src/methods/iter_nth_zero.rs6
-rw-r--r--clippy_lints/src/methods/iter_skip_next.rs22
-rw-r--r--clippy_lints/src/methods/iterator_step_by_zero.rs4
-rw-r--r--clippy_lints/src/methods/manual_saturating_arithmetic.rs61
-rw-r--r--clippy_lints/src/methods/map_collect_result_unit.rs9
-rw-r--r--clippy_lints/src/methods/map_flatten.rs19
-rw-r--r--clippy_lints/src/methods/map_unwrap_or.rs21
-rw-r--r--clippy_lints/src/methods/mod.rs345
-rw-r--r--clippy_lints/src/methods/ok_expect.rs6
-rw-r--r--clippy_lints/src/methods/option_as_ref_deref.rs22
-rw-r--r--clippy_lints/src/methods/option_map_or_none.rs22
-rw-r--r--clippy_lints/src/methods/option_map_unwrap_or.rs22
-rw-r--r--clippy_lints/src/methods/or_fun_call.rs12
-rw-r--r--clippy_lints/src/methods/search_is_some.rs90
-rw-r--r--clippy_lints/src/methods/skip_while_next.rs2
-rw-r--r--clippy_lints/src/methods/string_extend_chars.rs7
-rw-r--r--clippy_lints/src/methods/suspicious_map.rs9
-rw-r--r--clippy_lints/src/methods/uninit_assumed_init.rs14
-rw-r--r--clippy_lints/src/methods/unnecessary_filter_map.rs36
-rw-r--r--clippy_lints/src/methods/unnecessary_fold.rs39
-rw-r--r--clippy_lints/src/methods/unnecessary_lazy_eval.rs11
-rw-r--r--clippy_lints/src/methods/unwrap_used.rs4
-rw-r--r--clippy_lints/src/methods/useless_asref.rs3
-rw-r--r--clippy_lints/src/methods/utils.rs2
-rw-r--r--clippy_lints/src/methods/wrong_self_convention.rs32
-rw-r--r--clippy_lints/src/methods/zst_offset.rs5
-rw-r--r--clippy_lints/src/minmax.rs4
-rw-r--r--clippy_lints/src/misc.rs126
-rw-r--r--clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--clippy_lints/src/missing_doc.rs17
-rw-r--r--clippy_lints/src/missing_inline.rs2
-rw-r--r--clippy_lints/src/mut_key.rs6
-rw-r--r--clippy_lints/src/mut_mut.rs4
-rw-r--r--clippy_lints/src/mut_reference.rs4
-rw-r--r--clippy_lints/src/mutable_debug_assertion.rs4
-rw-r--r--clippy_lints/src/needless_bool.rs18
-rw-r--r--clippy_lints/src/needless_borrow.rs2
-rw-r--r--clippy_lints/src/needless_borrowed_ref.rs2
-rw-r--r--clippy_lints/src/needless_for_each.rs167
-rw-r--r--clippy_lints/src/needless_pass_by_value.rs9
-rw-r--r--clippy_lints/src/needless_update.rs2
-rw-r--r--clippy_lints/src/neg_cmp_op_on_partial_ord.rs4
-rw-r--r--clippy_lints/src/neg_multiply.rs6
-rw-r--r--clippy_lints/src/new_without_default.rs96
-rw-r--r--clippy_lints/src/no_effect.rs58
-rw-r--r--clippy_lints/src/non_copy_const.rs22
-rw-r--r--clippy_lints/src/non_expressive_names.rs3
-rw-r--r--clippy_lints/src/non_octal_unix_permissions.rs106
-rw-r--r--clippy_lints/src/open_options.rs4
-rw-r--r--clippy_lints/src/option_env_unwrap.rs4
-rw-r--r--clippy_lints/src/option_if_let_else.rs8
-rw-r--r--clippy_lints/src/overflow_check_conditional.rs20
-rw-r--r--clippy_lints/src/panic_unimplemented.rs7
-rw-r--r--clippy_lints/src/pass_by_ref_or_value.rs4
-rw-r--r--clippy_lints/src/path_buf_push_overwrite.rs2
-rw-r--r--clippy_lints/src/pattern_type_mismatch.rs18
-rw-r--r--clippy_lints/src/ptr.rs45
-rw-r--r--clippy_lints/src/ptr_eq.rs8
-rw-r--r--clippy_lints/src/ptr_offset_with_cast.rs6
-rw-r--r--clippy_lints/src/question_mark.rs8
-rw-r--r--clippy_lints/src/ranges.rs63
-rw-r--r--clippy_lints/src/redundant_clone.rs260
-rw-r--r--clippy_lints/src/redundant_closure_call.rs20
-rw-r--r--clippy_lints/src/redundant_slicing.rs37
-rw-r--r--clippy_lints/src/ref_option_ref.rs2
-rw-r--r--clippy_lints/src/regex.rs4
-rw-r--r--clippy_lints/src/repeat_once.rs4
-rw-r--r--clippy_lints/src/returns.rs16
-rw-r--r--clippy_lints/src/semicolon_if_nothing_returned.rs2
-rw-r--r--clippy_lints/src/shadow.rs69
-rw-r--r--clippy_lints/src/slow_vector_initialization.rs42
-rw-r--r--clippy_lints/src/strings.rs14
-rw-r--r--clippy_lints/src/suspicious_operation_groupings.rs16
-rw-r--r--clippy_lints/src/suspicious_trait_impl.rs7
-rw-r--r--clippy_lints/src/swap.rs30
-rw-r--r--clippy_lints/src/tabs_in_doc_comments.rs2
-rw-r--r--clippy_lints/src/to_string_in_display.rs2
-rw-r--r--clippy_lints/src/trait_bounds.rs4
-rw-r--r--clippy_lints/src/transmute/mod.rs2
-rw-r--r--clippy_lints/src/transmute/transmute_float_to_int.rs4
-rw-r--r--clippy_lints/src/transmute/utils.rs2
-rw-r--r--clippy_lints/src/transmuting_null.rs6
-rw-r--r--clippy_lints/src/try_err.rs25
-rw-r--r--clippy_lints/src/types/borrowed_box.rs8
-rw-r--r--clippy_lints/src/types/mod.rs1075
-rw-r--r--clippy_lints/src/types/type_complexity.rs79
-rw-r--r--clippy_lints/src/types/utils.rs2
-rw-r--r--clippy_lints/src/types/vec_box.rs4
-rw-r--r--clippy_lints/src/undropped_manually_drops.rs2
-rw-r--r--clippy_lints/src/unit_return_expecting_ord.rs4
-rw-r--r--clippy_lints/src/unit_types/let_unit_value.rs4
-rw-r--r--clippy_lints/src/unit_types/unit_arg.rs6
-rw-r--r--clippy_lints/src/unit_types/unit_cmp.rs4
-rw-r--r--clippy_lints/src/unit_types/utils.rs2
-rw-r--r--clippy_lints/src/unnamed_address.rs10
-rw-r--r--clippy_lints/src/unnecessary_sort_by.rs31
-rw-r--r--clippy_lints/src/unnecessary_wraps.rs2
-rw-r--r--clippy_lints/src/unnested_or_patterns.rs44
-rw-r--r--clippy_lints/src/unused_io_amount.rs10
-rw-r--r--clippy_lints/src/unused_self.rs25
-rw-r--r--clippy_lints/src/unused_unit.rs2
-rw-r--r--clippy_lints/src/unwrap.rs4
-rw-r--r--clippy_lints/src/unwrap_in_result.rs44
-rw-r--r--clippy_lints/src/upper_case_acronyms.rs25
-rw-r--r--clippy_lints/src/use_self.rs6
-rw-r--r--clippy_lints/src/useless_conversion.rs53
-rw-r--r--clippy_lints/src/utils/author.rs96
-rw-r--r--clippy_lints/src/utils/conf.rs2
-rw-r--r--clippy_lints/src/utils/inspector.rs92
-rw-r--r--clippy_lints/src/utils/internal_lints.rs199
-rw-r--r--clippy_lints/src/vec.rs54
-rw-r--r--clippy_lints/src/vec_init_then_push.rs31
-rw-r--r--clippy_lints/src/vec_resize_to_zero.rs2
-rw-r--r--clippy_lints/src/zero_div_zero.rs2
-rw-r--r--clippy_lints/src/zero_sized_map_values.rs2
225 files changed, 6577 insertions, 5317 deletions
diff --git a/clippy_lints/src/absurd_extreme_comparisons.rs b/clippy_lints/src/absurd_extreme_comparisons.rs
new file mode 100644
index 00000000000..5fbf4bdbd18
--- /dev/null
+++ b/clippy_lints/src/absurd_extreme_comparisons.rs
@@ -0,0 +1,173 @@
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+use crate::consts::{constant, Constant};
+
+use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_isize_or_usize;
+use clippy_utils::{clip, int_bits, unsext};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for comparisons where one side of the relation is
+    /// either the minimum or maximum value for its type and warns if it involves a
+    /// case that is always true or always false. Only integer and boolean types are
+    /// checked.
+    ///
+    /// **Why is this bad?** An expression like `min <= x` may misleadingly imply
+    /// that it is possible for `x` to be less than the minimum. Expressions like
+    /// `max < x` are probably mistakes.
+    ///
+    /// **Known problems:** For `usize` the size of the current compile target will
+    /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
+    /// a comparison to detect target pointer width will trigger this lint. One can
+    /// use `mem::sizeof` and compare its value or conditional compilation
+    /// attributes
+    /// like `#[cfg(target_pointer_width = "64")] ..` instead.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// let vec: Vec<isize> = Vec::new();
+    /// if vec.len() <= 0 {}
+    /// if 100 > i32::MAX {}
+    /// ```
+    pub ABSURD_EXTREME_COMPARISONS,
+    correctness,
+    "a comparison with a maximum or minimum value that is always true or false"
+}
+
+declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]);
+
+impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if let ExprKind::Binary(ref cmp, lhs, rhs) = expr.kind {
+            if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) {
+                if !expr.span.from_expansion() {
+                    let msg = "this comparison involving the minimum or maximum element for this \
+                               type contains a case that is always true or always false";
+
+                    let conclusion = match result {
+                        AbsurdComparisonResult::AlwaysFalse => "this comparison is always false".to_owned(),
+                        AbsurdComparisonResult::AlwaysTrue => "this comparison is always true".to_owned(),
+                        AbsurdComparisonResult::InequalityImpossible => format!(
+                            "the case where the two sides are not equal never occurs, consider using `{} == {}` \
+                             instead",
+                            snippet(cx, lhs.span, "lhs"),
+                            snippet(cx, rhs.span, "rhs")
+                        ),
+                    };
+
+                    let help = format!(
+                        "because `{}` is the {} value for this type, {}",
+                        snippet(cx, culprit.expr.span, "x"),
+                        match culprit.which {
+                            ExtremeType::Minimum => "minimum",
+                            ExtremeType::Maximum => "maximum",
+                        },
+                        conclusion
+                    );
+
+                    span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help);
+                }
+            }
+        }
+    }
+}
+
+enum ExtremeType {
+    Minimum,
+    Maximum,
+}
+
+struct ExtremeExpr<'a> {
+    which: ExtremeType,
+    expr: &'a Expr<'a>,
+}
+
+enum AbsurdComparisonResult {
+    AlwaysFalse,
+    AlwaysTrue,
+    InequalityImpossible,
+}
+
+fn is_cast_between_fixed_and_target<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
+    if let ExprKind::Cast(cast_exp, _) = expr.kind {
+        let precast_ty = cx.typeck_results().expr_ty(cast_exp);
+        let cast_ty = cx.typeck_results().expr_ty(expr);
+
+        return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty);
+    }
+
+    false
+}
+
+fn detect_absurd_comparison<'tcx>(
+    cx: &LateContext<'tcx>,
+    op: BinOpKind,
+    lhs: &'tcx Expr<'_>,
+    rhs: &'tcx Expr<'_>,
+) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> {
+    use AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible};
+    use ExtremeType::{Maximum, Minimum};
+    // absurd comparison only makes sense on primitive types
+    // primitive types don't implement comparison operators with each other
+    if cx.typeck_results().expr_ty(lhs) != cx.typeck_results().expr_ty(rhs) {
+        return None;
+    }
+
+    // comparisons between fix sized types and target sized types are considered unanalyzable
+    if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) {
+        return None;
+    }
+
+    let (rel, normalized_lhs, normalized_rhs) = normalize_comparison(op, lhs, rhs)?;
+
+    let lx = detect_extreme_expr(cx, normalized_lhs);
+    let rx = detect_extreme_expr(cx, normalized_rhs);
+
+    Some(match rel {
+        Rel::Lt => {
+            match (lx, rx) {
+                (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x
+                (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min
+                _ => return None,
+            }
+        },
+        Rel::Le => {
+            match (lx, rx) {
+                (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x
+                (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x
+                (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min
+                (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max
+                _ => return None,
+            }
+        },
+        Rel::Ne | Rel::Eq => return None,
+    })
+}
+
+fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
+    let ty = cx.typeck_results().expr_ty(expr);
+
+    let cv = constant(cx, cx.typeck_results(), expr)?.0;
+
+    let which = match (ty.kind(), cv) {
+        (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
+        (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => {
+            ExtremeType::Minimum
+        },
+
+        (&ty::Bool, Constant::Bool(true)) => ExtremeType::Maximum,
+        (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => {
+            ExtremeType::Maximum
+        },
+        (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => ExtremeType::Maximum,
+
+        _ => return None,
+    };
+    Some(ExtremeExpr { which, expr })
+}
diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs
index 16905781c56..a0993bb6913 100644
--- a/clippy_lints/src/assertions_on_constants.rs
+++ b/clippy_lints/src/assertions_on_constants.rs
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
                 return;
             }
             if_chain! {
-                if let ExprKind::Unary(_, ref lit) = e.kind;
+                if let ExprKind::Unary(_, lit) = e.kind;
                 if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), lit);
                 if is_true;
                 then {
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
             if assert_span.from_expansion() {
                 return;
             }
-            if let Some(assert_match) = match_assert_with_message(&cx, e) {
+            if let Some(assert_match) = match_assert_with_message(cx, e) {
                 match assert_match {
                     // matched assert but not message
                     AssertKind::WithoutMessage(false) => lint_false_without_message(),
@@ -113,17 +113,17 @@ enum AssertKind {
 /// where `message` is any expression and `c` is a constant bool.
 fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> {
     if_chain! {
-        if let ExprKind::If(ref cond, ref then, _) = expr.kind;
-        if let ExprKind::Unary(UnOp::Not, ref expr) = cond.kind;
+        if let ExprKind::If(cond, then, _) = expr.kind;
+        if let ExprKind::Unary(UnOp::Not, expr) = cond.kind;
         // bind the first argument of the `assert!` macro
         if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr);
         // block
-        if let ExprKind::Block(ref block, _) = then.kind;
+        if let ExprKind::Block(block, _) = then.kind;
         if block.stmts.is_empty();
         if let Some(block_expr) = &block.expr;
         // inner block is optional. unwrap it if it exists, or use the expression as is otherwise.
         if let Some(begin_panic_call) = match block_expr.kind {
-            ExprKind::Block(ref inner_block, _) => &inner_block.expr,
+            ExprKind::Block(inner_block, _) => &inner_block.expr,
             _ => &block.expr,
         };
         // function call
diff --git a/clippy_lints/src/atomic_ordering.rs b/clippy_lints/src/atomic_ordering.rs
index dfb18199325..7ceb01f5590 100644
--- a/clippy_lints/src/atomic_ordering.rs
+++ b/clippy_lints/src/atomic_ordering.rs
@@ -85,7 +85,7 @@ fn match_ordering_def_path(cx: &LateContext<'_>, did: DefId, orderings: &[&str])
 
 fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind;
+        if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind;
         let method = method_path.ident.name.as_str();
         if type_is_atomic(cx, &args[0]);
         if method == "load" || method == "store";
@@ -120,7 +120,7 @@ fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
 fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let ExprKind::Call(ref func, ref args) = expr.kind;
+        if let ExprKind::Call(func, args) = expr.kind;
         if let ExprKind::Path(ref func_qpath) = func.kind;
         if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
         if ["fence", "compiler_fence"]
@@ -152,7 +152,7 @@ fn opt_ordering_defid(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<DefId>
 
 fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind;
+        if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind;
         let method = method_path.ident.name.as_str();
         if type_is_atomic(cx, &args[0]);
         if method == "compare_exchange" || method == "compare_exchange_weak" || method == "fetch_update";
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index 3cef8d2a78b..c5b01461c1c 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -250,12 +250,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
     fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
         if let Some(items) = &attr.meta_item_list() {
             if let Some(ident) = attr.ident() {
-                let ident = &*ident.as_str();
-                match ident {
-                    "allow" | "warn" | "deny" | "forbid" => {
-                        check_clippy_lint_names(cx, ident, items);
-                    },
-                    _ => {},
+                if is_lint_level(ident.name) {
+                    check_clippy_lint_names(cx, ident.name, items);
                 }
                 if items.is_empty() || !attr.has_name(sym::deprecated) {
                     return;
@@ -288,60 +284,54 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
                         return;
                     }
                     if let Some(lint_list) = &attr.meta_item_list() {
-                        if let Some(ident) = attr.ident() {
-                            match &*ident.as_str() {
-                                "allow" | "warn" | "deny" | "forbid" => {
-                                    // permit `unused_imports`, `deprecated`, `unreachable_pub`,
-                                    // `clippy::wildcard_imports`, and `clippy::enum_glob_use` for `use` items
-                                    // and `unused_imports` for `extern crate` items with `macro_use`
-                                    for lint in lint_list {
-                                        match item.kind {
-                                            ItemKind::Use(..) => {
-                                                if is_word(lint, sym!(unused_imports))
-                                                    || is_word(lint, sym::deprecated)
-                                                    || is_word(lint, sym!(unreachable_pub))
-                                                    || is_word(lint, sym!(unused))
-                                                    || extract_clippy_lint(lint)
-                                                        .map_or(false, |s| s == "wildcard_imports")
-                                                    || extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use")
-                                                {
-                                                    return;
-                                                }
-                                            },
-                                            ItemKind::ExternCrate(..) => {
-                                                if is_word(lint, sym!(unused_imports)) && skip_unused_imports {
-                                                    return;
-                                                }
-                                                if is_word(lint, sym!(unused_extern_crates)) {
-                                                    return;
-                                                }
-                                            },
-                                            _ => {},
+                        if attr.ident().map_or(false, |ident| is_lint_level(ident.name)) {
+                            // permit `unused_imports`, `deprecated`, `unreachable_pub`,
+                            // `clippy::wildcard_imports`, and `clippy::enum_glob_use` for `use` items
+                            // and `unused_imports` for `extern crate` items with `macro_use`
+                            for lint in lint_list {
+                                match item.kind {
+                                    ItemKind::Use(..) => {
+                                        if is_word(lint, sym!(unused_imports))
+                                            || is_word(lint, sym::deprecated)
+                                            || is_word(lint, sym!(unreachable_pub))
+                                            || is_word(lint, sym!(unused))
+                                            || extract_clippy_lint(lint).map_or(false, |s| s == "wildcard_imports")
+                                            || extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use")
+                                        {
+                                            return;
+                                        }
+                                    },
+                                    ItemKind::ExternCrate(..) => {
+                                        if is_word(lint, sym!(unused_imports)) && skip_unused_imports {
+                                            return;
                                         }
-                                    }
-                                    let line_span = first_line_of_span(cx, attr.span);
-
-                                    if let Some(mut sugg) = snippet_opt(cx, line_span) {
-                                        if sugg.contains("#[") {
-                                            span_lint_and_then(
-                                                cx,
-                                                USELESS_ATTRIBUTE,
+                                        if is_word(lint, sym!(unused_extern_crates)) {
+                                            return;
+                                        }
+                                    },
+                                    _ => {},
+                                }
+                            }
+                            let line_span = first_line_of_span(cx, attr.span);
+
+                            if let Some(mut sugg) = snippet_opt(cx, line_span) {
+                                if sugg.contains("#[") {
+                                    span_lint_and_then(
+                                        cx,
+                                        USELESS_ATTRIBUTE,
+                                        line_span,
+                                        "useless lint attribute",
+                                        |diag| {
+                                            sugg = sugg.replacen("#[", "#![", 1);
+                                            diag.span_suggestion(
                                                 line_span,
-                                                "useless lint attribute",
-                                                |diag| {
-                                                    sugg = sugg.replacen("#[", "#![", 1);
-                                                    diag.span_suggestion(
-                                                        line_span,
-                                                        "if you just forgot a `!`, use",
-                                                        sugg,
-                                                        Applicability::MaybeIncorrect,
-                                                    );
-                                                },
+                                                "if you just forgot a `!`, use",
+                                                sugg,
+                                                Applicability::MaybeIncorrect,
                                             );
-                                        }
-                                    }
-                                },
-                                _ => {},
+                                        },
+                                    );
+                                }
                             }
                         }
                     }
@@ -371,18 +361,18 @@ fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<SymbolStr> {
         if meta_item.path.segments.len() > 1;
         if let tool_name = meta_item.path.segments[0].ident;
         if tool_name.name == sym::clippy;
-        let lint_name = meta_item.path.segments.last().unwrap().ident.name;
         then {
+            let lint_name = meta_item.path.segments.last().unwrap().ident.name;
             return Some(lint_name.as_str());
         }
     }
     None
 }
 
-fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) {
+fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
     for lint in items {
         if let Some(lint_name) = extract_clippy_lint(lint) {
-            if lint_name == "restriction" && ident != "allow" {
+            if lint_name == "restriction" && name != sym::allow {
                 span_lint_and_help(
                     cx,
                     BLANKET_CLIPPY_RESTRICTION_LINTS,
@@ -602,7 +592,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
             if let NestedMetaItem::MetaItem(meta) = item {
                 match &meta.kind {
                     MetaItemKind::List(list) => {
-                        mismatched.extend(find_mismatched_target_os(&list));
+                        mismatched.extend(find_mismatched_target_os(list));
                     },
                     MetaItemKind::Word => {
                         if_chain! {
@@ -629,7 +619,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
         then {
             let mess = "operating system used in target family position";
 
-            span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, &mess, |diag| {
+            span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| {
                 // Avoid showing the unix suggestion multiple times in case
                 // we have more than one mismatch for unix-like systems
                 let mut unix_suggested = false;
@@ -647,3 +637,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
         }
     }
 }
+
+fn is_lint_level(symbol: Symbol) -> bool {
+    matches!(symbol, sym::allow | sym::warn | sym::deny | sym::forbid)
+}
diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs
index 68eee0520b3..1739a57a240 100644
--- a/clippy_lints/src/await_holding_invalid.rs
+++ b/clippy_lints/src/await_holding_invalid.rs
@@ -101,7 +101,7 @@ impl LateLintPass<'_> for AwaitHolding {
             let typeck_results = cx.tcx.typeck_body(body_id);
             check_interior_types(
                 cx,
-                &typeck_results.generator_interior_types.as_ref().skip_binder(),
+                typeck_results.generator_interior_types.as_ref().skip_binder(),
                 body.value.span,
             );
         }
diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs
index 846ac08e93a..877ae002d36 100644
--- a/clippy_lints/src/bytecount.rs
+++ b/clippy_lints/src/bytecount.rs
@@ -38,59 +38,55 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);
 impl<'tcx> LateLintPass<'tcx> for ByteCount {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(ref count, _, ref count_args, _) = expr.kind;
+            if let ExprKind::MethodCall(count, _, count_args, _) = expr.kind;
             if count.ident.name == sym!(count);
             if count_args.len() == 1;
-            if let ExprKind::MethodCall(ref filter, _, ref filter_args, _) = count_args[0].kind;
+            if let ExprKind::MethodCall(filter, _, filter_args, _) = count_args[0].kind;
             if filter.ident.name == sym!(filter);
             if filter_args.len() == 2;
             if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind;
+            let body = cx.tcx.hir().body(body_id);
+            if body.params.len() == 1;
+            if let Some(argname) = get_pat_name(body.params[0].pat);
+            if let ExprKind::Binary(ref op, l, r) = body.value.kind;
+            if op.node == BinOpKind::Eq;
+            if match_type(cx,
+                       cx.typeck_results().expr_ty(&filter_args[0]).peel_refs(),
+                       &paths::SLICE_ITER);
             then {
-                let body = cx.tcx.hir().body(body_id);
-                if_chain! {
-                    if body.params.len() == 1;
-                    if let Some(argname) = get_pat_name(&body.params[0].pat);
-                    if let ExprKind::Binary(ref op, ref l, ref r) = body.value.kind;
-                    if op.node == BinOpKind::Eq;
-                    if match_type(cx,
-                               cx.typeck_results().expr_ty(&filter_args[0]).peel_refs(),
-                               &paths::SLICE_ITER);
-                    then {
-                        let needle = match get_path_name(l) {
-                            Some(name) if check_arg(name, argname, r) => r,
-                            _ => match get_path_name(r) {
-                                Some(name) if check_arg(name, argname, l) => l,
-                                _ => { return; }
-                            }
-                        };
-                        if ty::Uint(UintTy::U8) != *cx.typeck_results().expr_ty(needle).peel_refs().kind() {
-                            return;
-                        }
-                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args, _) =
-                                filter_args[0].kind {
-                            let p = path.ident.name;
-                            if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 {
-                                &args[0]
-                            } else {
-                                &filter_args[0]
-                            }
-                        } else {
-                            &filter_args[0]
-                        };
-                        let mut applicability = Applicability::MaybeIncorrect;
-                        span_lint_and_sugg(
-                            cx,
-                            NAIVE_BYTECOUNT,
-                            expr.span,
-                            "you appear to be counting bytes the naive way",
-                            "consider using the bytecount crate",
-                            format!("bytecount::count({}, {})",
-                                    snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
-                                    snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
-                            applicability,
-                        );
+                let needle = match get_path_name(l) {
+                    Some(name) if check_arg(name, argname, r) => r,
+                    _ => match get_path_name(r) {
+                        Some(name) if check_arg(name, argname, l) => l,
+                        _ => { return; }
                     }
                 };
+                if ty::Uint(UintTy::U8) != *cx.typeck_results().expr_ty(needle).peel_refs().kind() {
+                    return;
+                }
+                let haystack = if let ExprKind::MethodCall(path, _, args, _) =
+                        filter_args[0].kind {
+                    let p = path.ident.name;
+                    if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 {
+                        &args[0]
+                    } else {
+                        &filter_args[0]
+                    }
+                } else {
+                    &filter_args[0]
+                };
+                let mut applicability = Applicability::MaybeIncorrect;
+                span_lint_and_sugg(
+                    cx,
+                    NAIVE_BYTECOUNT,
+                    expr.span,
+                    "you appear to be counting bytes the naive way",
+                    "consider using the bytecount crate",
+                    format!("bytecount::count({}, {})",
+                            snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
+                            snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
+                    applicability,
+                );
             }
         };
     }
@@ -102,10 +98,10 @@ fn check_arg(name: Symbol, arg: Symbol, needle: &Expr<'_>) -> bool {
 
 fn get_path_name(expr: &Expr<'_>) -> Option<Symbol> {
     match expr.kind {
-        ExprKind::Box(ref e) | ExprKind::AddrOf(BorrowKind::Ref, _, ref e) | ExprKind::Unary(UnOp::Deref, ref e) => {
+        ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) | ExprKind::Unary(UnOp::Deref, e) => {
             get_path_name(e)
         },
-        ExprKind::Block(ref b, _) => {
+        ExprKind::Block(b, _) => {
             if b.stmts.is_empty() {
                 b.expr.as_ref().and_then(|p| get_path_name(p))
             } else {
diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs
index fce5c559672..8097a1c8326 100644
--- a/clippy_lints/src/cargo_common_metadata.rs
+++ b/clippy_lints/src/cargo_common_metadata.rs
@@ -20,11 +20,10 @@ declare_clippy_lint! {
     ///
     /// **Example:**
     /// ```toml
-    /// # This `Cargo.toml` is missing an authors field:
+    /// # This `Cargo.toml` is missing a description field:
     /// [package]
     /// name = "clippy"
     /// version = "0.0.212"
-    /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
     /// repository = "https://github.com/rust-lang/rust-clippy"
     /// readme = "README.md"
     /// license = "MIT OR Apache-2.0"
@@ -32,14 +31,13 @@ declare_clippy_lint! {
     /// categories = ["development-tools", "development-tools::cargo-plugins"]
     /// ```
     ///
-    /// Should include an authors field like:
+    /// Should include a description field like:
     ///
     /// ```toml
     /// # This `Cargo.toml` includes all common metadata
     /// [package]
     /// name = "clippy"
     /// version = "0.0.212"
-    /// authors = ["Someone <someone@rust-lang.org>"]
     /// description = "A bunch of helpful lints to avoid common pitfalls in Rust"
     /// repository = "https://github.com/rust-lang/rust-clippy"
     /// readme = "README.md"
@@ -97,10 +95,6 @@ impl LateLintPass<'_> for CargoCommonMetadata {
             // only run the lint if publish is `None` (`publish = true` or skipped entirely)
             // or if the vector isn't empty (`publish = ["something"]`)
             if package.publish.as_ref().filter(|publish| publish.is_empty()).is_none() || self.ignore_publish {
-                if is_empty_vec(&package.authors) {
-                    missing_warning(cx, &package, "package.authors");
-                }
-
                 if is_empty_str(&package.description) {
                     missing_warning(cx, &package, "package.description");
                 }
diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs
index 5208156ffd2..62a119d662b 100644
--- a/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -10,7 +10,7 @@ use rustc_target::abi::LayoutOf;
 use super::CAST_PTR_ALIGNMENT;
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    if let ExprKind::Cast(ref cast_expr, cast_to) = expr.kind {
+    if let ExprKind::Cast(cast_expr, cast_to) = expr.kind {
         if is_hir_ty_cfg_dependant(cx, cast_to) {
             return;
         }
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs
index bf722d0a3f4..040e0ca8864 100644
--- a/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/clippy_lints/src/casts/cast_sign_loss.rs
@@ -30,7 +30,7 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
             }
 
             // Don't lint for positive constants.
-            let const_val = constant(cx, &cx.typeck_results(), cast_op);
+            let const_val = constant(cx, cx.typeck_results(), cast_op);
             if_chain! {
                 if let Some((Constant::Int(n), _)) = const_val;
                 if let ty::Int(ity) = *cast_from.kind();
@@ -41,14 +41,14 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
             }
 
             // Don't lint for the result of methods that always return non-negative values.
-            if let ExprKind::MethodCall(ref path, _, _, _) = cast_op.kind {
+            if let ExprKind::MethodCall(path, _, _, _) = cast_op.kind {
                 let mut method_name = path.ident.name.as_str();
                 let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
 
                 if_chain! {
                     if method_name == "unwrap";
                     if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]);
-                    if let ExprKind::MethodCall(ref inner_path, _, _, _) = &arglist[0][0].kind;
+                    if let ExprKind::MethodCall(inner_path, _, _, _) = &arglist[0][0].kind;
                     then {
                         method_name = inner_path.ident.name.as_str();
                     }
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index d9e172c01a7..ae4fdd12c41 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -372,7 +372,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             return;
         }
 
-        if let ExprKind::Cast(ref cast_expr, cast_to) = expr.kind {
+        if let ExprKind::Cast(cast_expr, cast_to) = expr.kind {
             if is_hir_ty_cfg_dependant(cx, cast_to) {
                 return;
             }
diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs
index ed46cac493a..d7136f84cc3 100644
--- a/clippy_lints/src/checked_conversions.rs
+++ b/clippy_lints/src/checked_conversions.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
 
         let result = if_chain! {
             if !in_external_macro(cx.sess(), item.span);
-            if let ExprKind::Binary(op, ref left, ref right) = &item.kind;
+            if let ExprKind::Binary(op, left, right) = &item.kind;
 
             then {
                 match op.node {
@@ -200,7 +200,7 @@ impl ConversionType {
 /// Check for `expr <= (to_type::MAX as from_type)`
 fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
     if_chain! {
-         if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind;
+         if let ExprKind::Binary(ref op, left, right) = &expr.kind;
          if let Some((candidate, check)) = normalize_le_ge(op, left, right);
          if let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX");
 
@@ -219,7 +219,7 @@ fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
     }
 
     // First of we need a binary containing the expression & the cast
-    if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind {
+    if let ExprKind::Binary(ref op, left, right) = &expr.kind {
         normalize_le_ge(op, right, left).and_then(|(l, r)| check_function(l, r))
     } else {
         None
@@ -260,7 +260,7 @@ fn get_types_from_cast<'a>(
     // or `to_type::MAX as from_type`
     let call_from_cast: Option<(&Expr<'_>, &str)> = if_chain! {
         // to_type::max_value(), from_type
-        if let ExprKind::Cast(ref limit, ref from_type) = &expr.kind;
+        if let ExprKind::Cast(limit, from_type) = &expr.kind;
         if let TyKind::Path(ref from_type_path) = &from_type.kind;
         if let Some(from_sym) = int_ty_to_sym(from_type_path);
 
@@ -275,7 +275,7 @@ fn get_types_from_cast<'a>(
     let limit_from: Option<(&Expr<'_>, &str)> = call_from_cast.or_else(|| {
         if_chain! {
             // `from_type::from, to_type::max_value()`
-            if let ExprKind::Call(ref from_func, ref args) = &expr.kind;
+            if let ExprKind::Call(from_func, args) = &expr.kind;
             // `to_type::max_value()`
             if args.len() == 1;
             if let limit = &args[0];
@@ -317,13 +317,12 @@ fn get_types_from_cast<'a>(
 /// Gets the type which implements the called function
 fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function: &str) -> Option<&'a str> {
     if_chain! {
-        if let QPath::TypeRelative(ref ty, ref path) = &path;
+        if let QPath::TypeRelative(ty, path) = &path;
         if path.ident.name.as_str() == function;
-        if let TyKind::Path(QPath::Resolved(None, ref tp)) = &ty.kind;
+        if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind;
         if let [int] = &*tp.segments;
-        let name = &int.ident.name.as_str();
-
         then {
+            let name = &int.ident.name.as_str();
             candidates.iter().find(|c| name == *c).cloned()
         } else {
             None
@@ -334,11 +333,10 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function:
 /// Gets the type as a string, if it is a supported integer
 fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
     if_chain! {
-        if let QPath::Resolved(_, ref path) = *path;
+        if let QPath::Resolved(_, path) = *path;
         if let [ty] = &*path.segments;
-        let name = &ty.ident.name.as_str();
-
         then {
+            let name = &ty.ident.name.as_str();
             INTS.iter().find(|c| name == *c).cloned()
         } else {
             None
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 4cc542f723c..f62c6a9c325 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -152,7 +152,7 @@ impl<'tcx> Visitor<'tcx> for CcHelper {
             ExprKind::If(_, _, _) => {
                 self.cc += 1;
             },
-            ExprKind::Match(_, ref arms, _) => {
+            ExprKind::Match(_, arms, _) => {
                 if arms.len() > 1 {
                     self.cc += 1;
                 }
diff --git a/clippy_lints/src/collapsible_match.rs b/clippy_lints/src/collapsible_match.rs
index e2b3686ddf0..04fff237bb4 100644
--- a/clippy_lints/src/collapsible_match.rs
+++ b/clippy_lints/src/collapsible_match.rs
@@ -62,8 +62,8 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch {
 }
 
 fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext<'tcx>) {
+    let expr = strip_singleton_blocks(arm.body);
     if_chain! {
-        let expr = strip_singleton_blocks(arm.body);
         if let ExprKind::Match(expr_in, arms_inner, _) = expr.kind;
         // the outer arm pattern and the inner match
         if expr_in.span.ctxt() == arm.pat.span.ctxt();
diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs
index d601cb7c224..31ae63b5184 100644
--- a/clippy_lints/src/comparison_chain.rs
+++ b/clippy_lints/src/comparison_chain.rs
@@ -71,10 +71,8 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
         }
 
         for cond in conds.windows(2) {
-            if let (
-                &ExprKind::Binary(ref kind1, ref lhs1, ref rhs1),
-                &ExprKind::Binary(ref kind2, ref lhs2, ref rhs2),
-            ) = (&cond[0].kind, &cond[1].kind)
+            if let (&ExprKind::Binary(ref kind1, lhs1, rhs1), &ExprKind::Binary(ref kind2, lhs2, rhs2)) =
+                (&cond[0].kind, &cond[1].kind)
             {
                 if !kind_is_cmp(kind1.node) || !kind_is_cmp(kind2.node) {
                     return;
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 46093a16571..8b503c9a030 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -1,9 +1,19 @@
-use clippy_utils::diagnostics::span_lint_and_note;
-use clippy_utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
-use clippy_utils::{get_parent_expr, if_sequence};
-use rustc_hir::{Block, Expr, ExprKind};
+use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
+use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
+use clippy_utils::{
+    both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, in_macro, parent_node_is_if_expr,
+    run_lints, search_same, ContainsName, SpanlessEq, SpanlessHash,
+};
+use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{Block, Expr, ExprKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{source_map::Span, symbol::Symbol, BytePos};
+use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for consecutive `if`s with the same condition.
@@ -104,47 +114,457 @@ declare_clippy_lint! {
     "`if` with the same `then` and `else` blocks"
 }
 
-declare_lint_pass!(CopyAndPaste => [IFS_SAME_COND, SAME_FUNCTIONS_IN_IF_CONDITION, IF_SAME_THEN_ELSE]);
+declare_clippy_lint! {
+    /// **What it does:** Checks if the `if` and `else` block contain shared code that can be
+    /// moved out of the blocks.
+    ///
+    /// **Why is this bad?** Duplicate code is less maintainable.
+    ///
+    /// **Known problems:** Hopefully none.
+    ///
+    /// **Example:**
+    /// ```ignore
+    /// let foo = if … {
+    ///     println!("Hello World");
+    ///     13
+    /// } else {
+    ///     println!("Hello World");
+    ///     42
+    /// };
+    /// ```
+    ///
+    /// Could be written as:
+    /// ```ignore
+    /// println!("Hello World");
+    /// let foo = if … {
+    ///     13
+    /// } else {
+    ///     42
+    /// };
+    /// ```
+    pub BRANCHES_SHARING_CODE,
+    complexity,
+    "`if` statement with shared code in all blocks"
+}
+
+declare_lint_pass!(CopyAndPaste => [
+    IFS_SAME_COND,
+    SAME_FUNCTIONS_IN_IF_CONDITION,
+    IF_SAME_THEN_ELSE,
+    BRANCHES_SHARING_CODE
+]);
 
 impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if !expr.span.from_expansion() {
-            // skip ifs directly in else, it will be checked in the parent if
-            if let Some(&Expr {
-                kind: ExprKind::If(_, _, Some(ref else_expr)),
-                ..
-            }) = get_parent_expr(cx, expr)
-            {
-                if else_expr.hir_id == expr.hir_id {
-                    return;
+            if let ExprKind::If(_, _, _) = expr.kind {
+                // skip ifs directly in else, it will be checked in the parent if
+                if let Some(&Expr {
+                    kind: ExprKind::If(_, _, Some(else_expr)),
+                    ..
+                }) = get_parent_expr(cx, expr)
+                {
+                    if else_expr.hir_id == expr.hir_id {
+                        return;
+                    }
                 }
+
+                let (conds, blocks) = if_sequence(expr);
+                // Conditions
+                lint_same_cond(cx, &conds);
+                lint_same_fns_in_if_cond(cx, &conds);
+                // Block duplication
+                lint_same_then_else(cx, &blocks, conds.len() == blocks.len(), expr);
             }
+        }
+    }
+}
 
-            let (conds, blocks) = if_sequence(expr);
-            lint_same_then_else(cx, &blocks);
-            lint_same_cond(cx, &conds);
-            lint_same_fns_in_if_cond(cx, &conds);
+/// Implementation of `BRANCHES_SHARING_CODE` and `IF_SAME_THEN_ELSE` if the blocks are equal.
+fn lint_same_then_else<'tcx>(
+    cx: &LateContext<'tcx>,
+    blocks: &[&Block<'tcx>],
+    has_conditional_else: bool,
+    expr: &'tcx Expr<'_>,
+) {
+    // We only lint ifs with multiple blocks
+    if blocks.len() < 2 || parent_node_is_if_expr(expr, cx) {
+        return;
+    }
+
+    // Check if each block has shared code
+    let has_expr = blocks[0].expr.is_some();
+    let (start_eq, mut end_eq, expr_eq) = scan_block_for_eq(cx, blocks);
+
+    // BRANCHES_SHARING_CODE prerequisites
+    if has_conditional_else || (start_eq == 0 && end_eq == 0 && (has_expr && !expr_eq)) {
+        return;
+    }
+
+    // Only the start is the same
+    if start_eq != 0 && end_eq == 0 && (!has_expr || !expr_eq) {
+        let block = blocks[0];
+        let start_stmts = block.stmts.split_at(start_eq).0;
+
+        let mut start_walker = UsedValueFinderVisitor::new(cx);
+        for stmt in start_stmts {
+            intravisit::walk_stmt(&mut start_walker, stmt);
         }
+
+        emit_branches_sharing_code_lint(
+            cx,
+            start_eq,
+            0,
+            false,
+            check_for_warn_of_moved_symbol(cx, &start_walker.def_symbols, expr),
+            blocks,
+            expr,
+        );
+    } else if end_eq != 0 || (has_expr && expr_eq) {
+        let block = blocks[blocks.len() - 1];
+        let (start_stmts, block_stmts) = block.stmts.split_at(start_eq);
+        let (block_stmts, end_stmts) = block_stmts.split_at(block_stmts.len() - end_eq);
+
+        // Scan start
+        let mut start_walker = UsedValueFinderVisitor::new(cx);
+        for stmt in start_stmts {
+            intravisit::walk_stmt(&mut start_walker, stmt);
+        }
+        let mut moved_syms = start_walker.def_symbols;
+
+        // Scan block
+        let mut block_walker = UsedValueFinderVisitor::new(cx);
+        for stmt in block_stmts {
+            intravisit::walk_stmt(&mut block_walker, stmt);
+        }
+        let mut block_defs = block_walker.defs;
+
+        // Scan moved stmts
+        let mut moved_start: Option<usize> = None;
+        let mut end_walker = UsedValueFinderVisitor::new(cx);
+        for (index, stmt) in end_stmts.iter().enumerate() {
+            intravisit::walk_stmt(&mut end_walker, stmt);
+
+            for value in &end_walker.uses {
+                // Well we can't move this and all prev statements. So reset
+                if block_defs.contains(value) {
+                    moved_start = Some(index + 1);
+                    end_walker.defs.drain().for_each(|x| {
+                        block_defs.insert(x);
+                    });
+
+                    end_walker.def_symbols.clear();
+                }
+            }
+
+            end_walker.uses.clear();
+        }
+
+        if let Some(moved_start) = moved_start {
+            end_eq -= moved_start;
+        }
+
+        let end_linable = block.expr.map_or_else(
+            || end_eq != 0,
+            |expr| {
+                intravisit::walk_expr(&mut end_walker, expr);
+                end_walker.uses.iter().any(|x| !block_defs.contains(x))
+            },
+        );
+
+        if end_linable {
+            end_walker.def_symbols.drain().for_each(|x| {
+                moved_syms.insert(x);
+            });
+        }
+
+        emit_branches_sharing_code_lint(
+            cx,
+            start_eq,
+            end_eq,
+            end_linable,
+            check_for_warn_of_moved_symbol(cx, &moved_syms, expr),
+            blocks,
+            expr,
+        );
     }
 }
 
-/// Implementation of `IF_SAME_THEN_ELSE`.
-fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>]) {
-    let eq: &dyn Fn(&&Block<'_>, &&Block<'_>) -> bool =
-        &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) };
+fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> (usize, usize, bool) {
+    let mut start_eq = usize::MAX;
+    let mut end_eq = usize::MAX;
+    let mut expr_eq = true;
+    for win in blocks.windows(2) {
+        let l_stmts = win[0].stmts;
+        let r_stmts = win[1].stmts;
 
-    if let Some((i, j)) = search_same_sequenced(blocks, eq) {
-        span_lint_and_note(
+        // `SpanlessEq` now keeps track of the locals and is therefore context sensitive clippy#6752.
+        // The comparison therefore needs to be done in a way that builds the correct context.
+        let mut evaluator = SpanlessEq::new(cx);
+        let mut evaluator = evaluator.inter_expr();
+
+        let current_start_eq = count_eq(&mut l_stmts.iter(), &mut r_stmts.iter(), |l, r| evaluator.eq_stmt(l, r));
+
+        let current_end_eq = {
+            // We skip the middle statements which can't be equal
+            let end_comparison_count = l_stmts.len().min(r_stmts.len()) - current_start_eq;
+            let it1 = l_stmts.iter().skip(l_stmts.len() - end_comparison_count);
+            let it2 = r_stmts.iter().skip(r_stmts.len() - end_comparison_count);
+            it1.zip(it2)
+                .fold(0, |acc, (l, r)| if evaluator.eq_stmt(l, r) { acc + 1 } else { 0 })
+        };
+        let block_expr_eq = both(&win[0].expr, &win[1].expr, |l, r| evaluator.eq_expr(l, r));
+
+        // IF_SAME_THEN_ELSE
+        if_chain! {
+            if block_expr_eq;
+            if l_stmts.len() == r_stmts.len();
+            if l_stmts.len() == current_start_eq;
+            if run_lints(cx, &[IF_SAME_THEN_ELSE], win[0].hir_id);
+            if run_lints(cx, &[IF_SAME_THEN_ELSE], win[1].hir_id);
+            then {
+                span_lint_and_note(
+                    cx,
+                    IF_SAME_THEN_ELSE,
+                    win[0].span,
+                    "this `if` has identical blocks",
+                    Some(win[1].span),
+                    "same as this",
+                );
+
+                return (0, 0, false);
+            }
+        }
+
+        start_eq = start_eq.min(current_start_eq);
+        end_eq = end_eq.min(current_end_eq);
+        expr_eq &= block_expr_eq;
+    }
+
+    let has_expr = blocks[0].expr.is_some();
+    if has_expr && !expr_eq {
+        end_eq = 0;
+    }
+
+    // Check if the regions are overlapping. Set `end_eq` to prevent the overlap
+    let min_block_size = blocks.iter().map(|x| x.stmts.len()).min().unwrap();
+    if (start_eq + end_eq) > min_block_size {
+        end_eq = min_block_size - start_eq;
+    }
+
+    (start_eq, end_eq, expr_eq)
+}
+
+fn check_for_warn_of_moved_symbol(
+    cx: &LateContext<'tcx>,
+    symbols: &FxHashSet<Symbol>,
+    if_expr: &'tcx Expr<'_>,
+) -> bool {
+    get_enclosing_block(cx, if_expr.hir_id).map_or(false, |block| {
+        let ignore_span = block.span.shrink_to_lo().to(if_expr.span);
+
+        symbols
+            .iter()
+            .filter(|sym| !sym.as_str().starts_with('_'))
+            .any(move |sym| {
+                let mut walker = ContainsName {
+                    name: *sym,
+                    result: false,
+                };
+
+                // Scan block
+                block
+                    .stmts
+                    .iter()
+                    .filter(|stmt| !ignore_span.overlaps(stmt.span))
+                    .for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt));
+
+                if let Some(expr) = block.expr {
+                    intravisit::walk_expr(&mut walker, expr);
+                }
+
+                walker.result
+            })
+    })
+}
+
+fn emit_branches_sharing_code_lint(
+    cx: &LateContext<'tcx>,
+    start_stmts: usize,
+    end_stmts: usize,
+    lint_end: bool,
+    warn_about_moved_symbol: bool,
+    blocks: &[&Block<'tcx>],
+    if_expr: &'tcx Expr<'_>,
+) {
+    if start_stmts == 0 && !lint_end {
+        return;
+    }
+
+    // (help, span, suggestion)
+    let mut suggestions: Vec<(&str, Span, String)> = vec![];
+    let mut add_expr_note = false;
+
+    // Construct suggestions
+    if start_stmts > 0 {
+        let block = blocks[0];
+        let span_start = first_line_of_span(cx, if_expr.span).shrink_to_lo();
+        let span_end = block.stmts[start_stmts - 1].span.source_callsite();
+
+        let cond_span = first_line_of_span(cx, if_expr.span).until(block.span);
+        let cond_snippet = reindent_multiline(snippet(cx, cond_span, "_"), false, None);
+        let cond_indent = indent_of(cx, cond_span);
+        let moved_span = block.stmts[0].span.source_callsite().to(span_end);
+        let moved_snippet = reindent_multiline(snippet(cx, moved_span, "_"), true, None);
+        let suggestion = moved_snippet.to_string() + "\n" + &cond_snippet + "{";
+        let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, cond_indent);
+
+        let span = span_start.to(span_end);
+        suggestions.push(("start", span, suggestion.to_string()));
+    }
+
+    if lint_end {
+        let block = blocks[blocks.len() - 1];
+        let span_end = block.span.shrink_to_hi();
+
+        let moved_start = if end_stmts == 0 && block.expr.is_some() {
+            block.expr.unwrap().span
+        } else {
+            block.stmts[block.stmts.len() - end_stmts].span
+        }
+        .source_callsite();
+        let moved_end = block
+            .expr
+            .map_or_else(|| block.stmts[block.stmts.len() - 1].span, |expr| expr.span)
+            .source_callsite();
+
+        let moved_span = moved_start.to(moved_end);
+        let moved_snipped = reindent_multiline(snippet(cx, moved_span, "_"), true, None);
+        let indent = indent_of(cx, if_expr.span.shrink_to_hi());
+        let suggestion = "}\n".to_string() + &moved_snipped;
+        let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, indent);
+
+        let mut span = moved_start.to(span_end);
+        // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
+        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt());
+        if snippet_opt(cx, test_span)
+            .map(|snip| snip == "    ")
+            .unwrap_or_default()
+        {
+            span = span.with_lo(test_span.lo());
+        }
+
+        suggestions.push(("end", span, suggestion.to_string()));
+        add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit()
+    }
+
+    let add_optional_msgs = |diag: &mut DiagnosticBuilder<'_>| {
+        if add_expr_note {
+            diag.note("The end suggestion probably needs some adjustments to use the expression result correctly");
+        }
+
+        if warn_about_moved_symbol {
+            diag.warn("Some moved values might need to be renamed to avoid wrong references");
+        }
+    };
+
+    // Emit lint
+    if suggestions.len() == 1 {
+        let (place_str, span, sugg) = suggestions.pop().unwrap();
+        let msg = format!("all if blocks contain the same code at the {}", place_str);
+        let help = format!("consider moving the {} statements out like this", place_str);
+        span_lint_and_then(cx, BRANCHES_SHARING_CODE, span, msg.as_str(), |diag| {
+            diag.span_suggestion(span, help.as_str(), sugg, Applicability::Unspecified);
+
+            add_optional_msgs(diag);
+        });
+    } else if suggestions.len() == 2 {
+        let (_, end_span, end_sugg) = suggestions.pop().unwrap();
+        let (_, start_span, start_sugg) = suggestions.pop().unwrap();
+        span_lint_and_then(
             cx,
-            IF_SAME_THEN_ELSE,
-            j.span,
-            "this `if` has identical blocks",
-            Some(i.span),
-            "same as this",
+            BRANCHES_SHARING_CODE,
+            start_span,
+            "all if blocks contain the same code at the start and the end. Here at the start",
+            move |diag| {
+                diag.span_note(end_span, "and here at the end");
+
+                diag.span_suggestion(
+                    start_span,
+                    "consider moving the start statements out like this",
+                    start_sugg,
+                    Applicability::Unspecified,
+                );
+
+                diag.span_suggestion(
+                    end_span,
+                    "and consider moving the end statements out like this",
+                    end_sugg,
+                    Applicability::Unspecified,
+                );
+
+                add_optional_msgs(diag);
+            },
         );
     }
 }
 
+/// This visitor collects `HirId`s and Symbols of defined symbols and `HirId`s of used values.
+struct UsedValueFinderVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+
+    /// The `HirId`s of defined values in the scanned statements
+    defs: FxHashSet<HirId>,
+
+    /// The Symbols of the defined symbols in the scanned statements
+    def_symbols: FxHashSet<Symbol>,
+
+    /// The `HirId`s of the used values
+    uses: FxHashSet<HirId>,
+}
+
+impl<'a, 'tcx> UsedValueFinderVisitor<'a, 'tcx> {
+    fn new(cx: &'a LateContext<'tcx>) -> Self {
+        UsedValueFinderVisitor {
+            cx,
+            defs: FxHashSet::default(),
+            def_symbols: FxHashSet::default(),
+            uses: FxHashSet::default(),
+        }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for UsedValueFinderVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.cx.tcx.hir())
+    }
+
+    fn visit_local(&mut self, l: &'tcx rustc_hir::Local<'tcx>) {
+        let local_id = l.pat.hir_id;
+        self.defs.insert(local_id);
+
+        if let Some(sym) = l.pat.simple_ident() {
+            self.def_symbols.insert(sym.name);
+        }
+
+        if let Some(expr) = l.init {
+            intravisit::walk_expr(self, expr);
+        }
+    }
+
+    fn visit_qpath(&mut self, qpath: &'tcx rustc_hir::QPath<'tcx>, id: HirId, _span: rustc_span::Span) {
+        if let rustc_hir::QPath::Resolved(_, path) = *qpath {
+            if path.segments.len() == 1 {
+                if let rustc_hir::def::Res::Local(var) = self.cx.qpath_res(qpath, id) {
+                    self.uses.insert(var);
+                }
+            }
+        }
+    }
+}
+
 /// Implementation of `IFS_SAME_COND`.
 fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) {
     let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
@@ -198,15 +618,3 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) {
         );
     }
 }
-
-fn search_same_sequenced<T, Eq>(exprs: &[T], eq: Eq) -> Option<(&T, &T)>
-where
-    Eq: Fn(&T, &T) -> bool,
-{
-    for win in exprs.windows(2) {
-        if eq(&win[0], &win[1]) {
-            return Some((&win[0], &win[1]));
-        }
-    }
-    None
-}
diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs
index ac890c90c97..7b5cce6462a 100644
--- a/clippy_lints/src/create_dir.rs
+++ b/clippy_lints/src/create_dir.rs
@@ -33,7 +33,7 @@ declare_lint_pass!(CreateDir => [CREATE_DIR]);
 impl LateLintPass<'_> for CreateDir {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::Call(ref func, ref args) = expr.kind;
+            if let ExprKind::Call(func, args) = expr.kind;
             if let ExprKind::Path(ref path) = func.kind;
             if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
             if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR);
diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs
index 568a174445c..710da8fe9e0 100644
--- a/clippy_lints/src/default.rs
+++ b/clippy_lints/src/default.rs
@@ -77,29 +77,28 @@ impl LateLintPass<'_> for Default {
         if_chain! {
             // Avoid cases already linted by `field_reassign_with_default`
             if !self.reassigned_linted.contains(&expr.span);
-            if let ExprKind::Call(ref path, ..) = expr.kind;
+            if let ExprKind::Call(path, ..) = expr.kind;
             if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
             if let ExprKind::Path(ref qpath) = path.kind;
             if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
             if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
             // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
             if let QPath::Resolved(None, _path) = qpath;
+            let expr_ty = cx.typeck_results().expr_ty(expr);
+            if let ty::Adt(def, ..) = expr_ty.kind();
             then {
-                let expr_ty = cx.typeck_results().expr_ty(expr);
-                if let ty::Adt(def, ..) = expr_ty.kind() {
-                    // TODO: Work out a way to put "whatever the imported way of referencing
-                    // this type in this file" rather than a fully-qualified type.
-                    let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
-                    span_lint_and_sugg(
-                        cx,
-                        DEFAULT_TRAIT_ACCESS,
-                        expr.span,
-                        &format!("calling `{}` is more clear than this expression", replacement),
-                        "try",
-                        replacement,
-                        Applicability::Unspecified, // First resolve the TODO above
-                    );
-                }
+                // TODO: Work out a way to put "whatever the imported way of referencing
+                // this type in this file" rather than a fully-qualified type.
+                let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
+                span_lint_and_sugg(
+                    cx,
+                    DEFAULT_TRAIT_ACCESS,
+                    expr.span,
+                    &format!("calling `{}` is more clear than this expression", replacement),
+                    "try",
+                    replacement,
+                    Applicability::Unspecified, // First resolve the TODO above
+                );
             }
         }
     }
@@ -202,14 +201,14 @@ impl LateLintPass<'_> for Default {
                 let binding_type = if_chain! {
                     if let ty::Adt(adt_def, substs) = binding_type.kind();
                     if !substs.is_empty();
-                    let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
-                    let generic_args = substs.iter().collect::<Vec<_>>();
-                    let tys_str = generic_args
-                        .iter()
-                        .map(ToString::to_string)
-                        .collect::<Vec<_>>()
-                        .join(", ");
                     then {
+                        let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
+                        let generic_args = substs.iter().collect::<Vec<_>>();
+                        let tys_str = generic_args
+                            .iter()
+                            .map(ToString::to_string)
+                            .collect::<Vec<_>>()
+                            .join(", ");
                         format!("{}::<{}>", adt_def_ty_name, &tys_str)
                     } else {
                         binding_type.to_string()
@@ -247,7 +246,7 @@ impl LateLintPass<'_> for Default {
 /// Checks if the given expression is the `default` method belonging to the `Default` trait.
 fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
     if_chain! {
-        if let ExprKind::Call(ref fn_expr, _) = &expr.kind;
+        if let ExprKind::Call(fn_expr, _) = &expr.kind;
         if let ExprKind::Path(qpath) = &fn_expr.kind;
         if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
         then {
@@ -263,11 +262,11 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool
 fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
     if_chain! {
         // only take assignments
-        if let StmtKind::Semi(ref later_expr) = this.kind;
-        if let ExprKind::Assign(ref assign_lhs, ref assign_rhs, _) = later_expr.kind;
+        if let StmtKind::Semi(later_expr) = this.kind;
+        if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind;
         // only take assignments to fields where the left-hand side field is a field of
         // the same binding as the previous statement
-        if let ExprKind::Field(ref binding, field_ident) = assign_lhs.kind;
+        if let ExprKind::Field(binding, field_ident) = assign_lhs.kind;
         if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind;
         if let Some(second_binding_name) = path.segments.last();
         if second_binding_name.ident.name == binding_name;
diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs
index 73f71d88b05..6e883942680 100644
--- a/clippy_lints/src/default_numeric_fallback.rs
+++ b/clippy_lints/src/default_numeric_fallback.rs
@@ -131,8 +131,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
             },
 
             ExprKind::Struct(_, fields, base) => {
+                let ty = self.cx.typeck_results().expr_ty(expr);
                 if_chain! {
-                    let ty = self.cx.typeck_results().expr_ty(expr);
                     if let Some(adt_def) = ty.ty_adt_def();
                     if adt_def.is_struct();
                     if let Some(variant) = adt_def.variants.iter().next();
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 834136f910d..647af3bdc04 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then};
 use clippy_utils::paths;
-use clippy_utils::ty::is_copy;
+use clippy_utils::ty::{implements_trait, is_copy};
 use clippy_utils::{get_trait_def_id, is_allowed, is_automatically_derived, match_def_path};
 use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
@@ -12,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Span;
+use rustc_span::{def_id::LOCAL_CRATE, source_map::Span};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
@@ -199,7 +199,7 @@ fn check_hash_peq<'tcx>(
         then {
             // Look for the PartialEq implementations for `ty`
             cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
-                let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));
+                let peq_is_automatically_derived = is_automatically_derived(cx.tcx.get_attrs(impl_id));
 
                 if peq_is_automatically_derived == hash_is_automatically_derived {
                     return;
@@ -253,7 +253,7 @@ fn check_ord_partial_ord<'tcx>(
         then {
             // Look for the PartialOrd implementations for `ty`
             cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| {
-                let partial_ord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));
+                let partial_ord_is_automatically_derived = is_automatically_derived(cx.tcx.get_attrs(impl_id));
 
                 if partial_ord_is_automatically_derived == ord_is_automatically_derived {
                     return;
@@ -293,48 +293,53 @@ fn check_ord_partial_ord<'tcx>(
 
 /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
 fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
-    if cx
-        .tcx
-        .lang_items()
-        .clone_trait()
-        .map_or(false, |id| Some(id) == trait_ref.trait_def_id())
-    {
-        if !is_copy(cx, ty) {
+    let clone_id = match cx.tcx.lang_items().clone_trait() {
+        Some(id) if trait_ref.trait_def_id() == Some(id) => id,
+        _ => return,
+    };
+    let copy_id = match cx.tcx.lang_items().copy_trait() {
+        Some(id) => id,
+        None => return,
+    };
+    let (ty_adt, ty_subs) = match *ty.kind() {
+        // Unions can't derive clone.
+        ty::Adt(adt, subs) if !adt.is_union() => (adt, subs),
+        _ => return,
+    };
+    // If the current self type doesn't implement Copy (due to generic constraints), search to see if
+    // there's a Copy impl for any instance of the adt.
+    if !is_copy(cx, ty) {
+        if ty_subs.non_erasable_generics().next().is_some() {
+            let has_copy_impl = cx
+                .tcx
+                .all_local_trait_impls(LOCAL_CRATE)
+                .get(&copy_id)
+                .map_or(false, |impls| {
+                    impls
+                        .iter()
+                        .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did == adt.did))
+                });
+            if !has_copy_impl {
+                return;
+            }
+        } else {
             return;
         }
-
-        match *ty.kind() {
-            ty::Adt(def, _) if def.is_union() => return,
-
-            // Some types are not Clone by default but could be cloned “by hand” if necessary
-            ty::Adt(def, substs) => {
-                for variant in &def.variants {
-                    for field in &variant.fields {
-                        if let ty::FnDef(..) = field.ty(cx.tcx, substs).kind() {
-                            return;
-                        }
-                    }
-                    for subst in substs {
-                        if let ty::subst::GenericArgKind::Type(subst) = subst.unpack() {
-                            if let ty::Param(_) = subst.kind() {
-                                return;
-                            }
-                        }
-                    }
-                }
-            },
-            _ => (),
-        }
-
-        span_lint_and_note(
-            cx,
-            EXPL_IMPL_CLONE_ON_COPY,
-            item.span,
-            "you are implementing `Clone` explicitly on a `Copy` type",
-            Some(item.span),
-            "consider deriving `Clone` or removing `Copy`",
-        );
     }
+    // Derive constrains all generic types to requiring Clone. Check if any type is not constrained for
+    // this impl.
+    if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) {
+        return;
+    }
+
+    span_lint_and_note(
+        cx,
+        EXPL_IMPL_CLONE_ON_COPY,
+        item.span,
+        "you are implementing `Clone` explicitly on a `Copy` type",
+        Some(item.span),
+        "consider deriving `Clone` or removing `Copy`",
+    );
 }
 
 /// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint.
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index 14338ac8faf..fb53b55ebd6 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -11,7 +11,7 @@ use rustc_errors::emitter::EmitterWriter;
 use rustc_errors::Handler;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{Expr, ExprKind, QPath};
+use rustc_hir::{AnonConst, Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
@@ -710,16 +710,22 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
 
         // check for `begin_panic`
         if_chain! {
-            if let ExprKind::Call(ref func_expr, _) = expr.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.kind;
+            if let ExprKind::Call(func_expr, _) = expr.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path)) = func_expr.kind;
             if let Some(path_def_id) = path.res.opt_def_id();
             if match_panic_def_id(self.cx, path_def_id);
             if is_expn_of(expr.span, "unreachable").is_none();
+            if !is_expn_of_debug_assertions(expr.span);
             then {
                 self.panic_span = Some(expr.span);
             }
         }
 
+        // check for `assert_eq` or `assert_ne`
+        if is_expn_of(expr.span, "assert_eq").is_some() || is_expn_of(expr.span, "assert_ne").is_some() {
+            self.panic_span = Some(expr.span);
+        }
+
         // check for `unwrap`
         if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
             let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
@@ -734,7 +740,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
         intravisit::walk_expr(self, expr);
     }
 
+    // Panics in const blocks will cause compilation to fail.
+    fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
+
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
     }
 }
+
+fn is_expn_of_debug_assertions(span: Span) -> bool {
+    const MACRO_NAMES: &[&str] = &["debug_assert", "debug_assert_eq", "debug_assert_ne"];
+    MACRO_NAMES.iter().any(|name| is_expn_of(span, name).is_some())
+}
diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs
index 1d291565ec1..58543ae6e4e 100644
--- a/clippy_lints/src/double_comparison.rs
+++ b/clippy_lints/src/double_comparison.rs
@@ -47,7 +47,7 @@ impl<'tcx> DoubleComparisons {
             },
             _ => return,
         };
-        if !(eq_expr_value(cx, &llhs, &rlhs) && eq_expr_value(cx, &lrhs, &rrhs)) {
+        if !(eq_expr_value(cx, llhs, rlhs) && eq_expr_value(cx, lrhs, rrhs)) {
             return;
         }
         macro_rules! lint_double_comparison {
@@ -88,7 +88,7 @@ impl<'tcx> DoubleComparisons {
 
 impl<'tcx> LateLintPass<'tcx> for DoubleComparisons {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.kind {
+        if let ExprKind::Binary(ref kind, lhs, rhs) = expr.kind {
             Self::check_binop(cx, kind.node, lhs, rhs, expr.span);
         }
     }
diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs
index 5afdcb3c09f..e4e4a93b011 100644
--- a/clippy_lints/src/double_parens.rs
+++ b/clippy_lints/src/double_parens.rs
@@ -50,7 +50,7 @@ impl EarlyLintPass for DoubleParens {
         match expr.kind {
             ExprKind::Paren(ref in_paren) => match in_paren.kind {
                 ExprKind::Paren(_) | ExprKind::Tup(_) => {
-                    span_lint(cx, DOUBLE_PARENS, expr.span, &msg);
+                    span_lint(cx, DOUBLE_PARENS, expr.span, msg);
                 },
                 _ => {},
             },
@@ -58,7 +58,7 @@ impl EarlyLintPass for DoubleParens {
                 if params.len() == 1 {
                     let param = &params[0];
                     if let ExprKind::Paren(_) = param.kind {
-                        span_lint(cx, DOUBLE_PARENS, param.span, &msg);
+                        span_lint(cx, DOUBLE_PARENS, param.span, msg);
                     }
                 }
             },
@@ -66,7 +66,7 @@ impl EarlyLintPass for DoubleParens {
                 if params.len() == 2 {
                     let param = &params[1];
                     if let ExprKind::Paren(_) = param.kind {
-                        span_lint(cx, DOUBLE_PARENS, param.span, &msg);
+                        span_lint(cx, DOUBLE_PARENS, param.span, msg);
                     }
                 }
             },
diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs
index 7e7ec017bbb..b5b29760636 100644
--- a/clippy_lints/src/drop_forget_ref.rs
+++ b/clippy_lints/src/drop_forget_ref.rs
@@ -113,7 +113,7 @@ declare_lint_pass!(DropForgetRef => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COP
 impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::Call(ref path, ref args) = expr.kind;
+            if let ExprKind::Call(path, args) = expr.kind;
             if let ExprKind::Path(ref qpath) = path.kind;
             if args.len() == 1;
             if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs
index 746c1f6df91..529807770f3 100644
--- a/clippy_lints/src/duration_subsec.rs
+++ b/clippy_lints/src/duration_subsec.rs
@@ -43,8 +43,8 @@ declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]);
 impl<'tcx> LateLintPass<'tcx> for DurationSubsec {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind;
-            if let ExprKind::MethodCall(ref method_path, _ , ref args, _) = left.kind;
+            if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, left, right) = expr.kind;
+            if let ExprKind::MethodCall(method_path, _ , args, _) = left.kind;
             if match_type(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), &paths::DURATION);
             if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right);
             then {
diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index 25eb048448c..a815df1691a 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -57,14 +57,14 @@ declare_lint_pass!(HashMapPass => [MAP_ENTRY]);
 
 impl<'tcx> LateLintPass<'tcx> for HashMapPass {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.kind {
-            if let ExprKind::Unary(UnOp::Not, ref check) = check.kind {
+        if let ExprKind::If(check, then_block, ref else_block) = expr.kind {
+            if let ExprKind::Unary(UnOp::Not, check) = check.kind {
                 if let Some((ty, map, key)) = check_cond(cx, check) {
                     // in case of `if !m.contains_key(&k) { m.insert(k, v); }`
                     // we can give a better error message
                     let sole_expr = {
                         else_block.is_none()
-                            && if let ExprKind::Block(ref then_block, _) = then_block.kind {
+                            && if let ExprKind::Block(then_block, _) = then_block.kind {
                                 (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1
                             } else {
                                 true
@@ -81,9 +81,9 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                         sole_expr,
                     };
 
-                    walk_expr(&mut visitor, &**then_block);
+                    walk_expr(&mut visitor, then_block);
                 }
-            } else if let Some(ref else_block) = *else_block {
+            } else if let Some(else_block) = *else_block {
                 if let Some((ty, map, key)) = check_cond(cx, check) {
                     let mut visitor = InsertVisitor {
                         cx,
@@ -103,10 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
 
 fn check_cond<'a>(cx: &LateContext<'_>, check: &'a Expr<'a>) -> Option<(&'static str, &'a Expr<'a>, &'a Expr<'a>)> {
     if_chain! {
-        if let ExprKind::MethodCall(ref path, _, ref params, _) = check.kind;
+        if let ExprKind::MethodCall(path, _, params, _) = check.kind;
         if params.len() >= 2;
         if path.ident.name == sym!(contains_key);
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref key) = params[1].kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, key) = params[1].kind;
         then {
             let map = &params[0];
             let obj_ty = cx.typeck_results().expr_ty(map).peel_refs();
@@ -140,7 +140,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(ref path, _, ref params, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, params, _) = expr.kind;
             if params.len() == 3;
             if path.ident.name == sym!(insert);
             if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);
diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs
index 6d7046ac8b7..90f391b5f5c 100644
--- a/clippy_lints/src/eq_op.rs
+++ b/clippy_lints/src/eq_op.rs
@@ -65,12 +65,12 @@ const ASSERT_MACRO_NAMES: [&str; 4] = ["assert_eq", "assert_ne", "debug_assert_e
 impl<'tcx> LateLintPass<'tcx> for EqOp {
     #[allow(clippy::similar_names, clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Block(ref block, _) = e.kind {
+        if let ExprKind::Block(block, _) = e.kind {
             for stmt in block.stmts {
                 for amn in &ASSERT_MACRO_NAMES {
                     if_chain! {
                         if is_expn_of(stmt.span, amn).is_some();
-                        if let StmtKind::Semi(ref matchexpr) = stmt.kind;
+                        if let StmtKind::Semi(matchexpr) = stmt.kind;
                         if let Some(macro_args) = higher::extract_assert_macro_args(matchexpr);
                         if macro_args.len() == 2;
                         let (lhs, rhs) = (macro_args[0], macro_args[1]);
@@ -88,12 +88,12 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                 }
             }
         }
-        if let ExprKind::Binary(op, ref left, ref right) = e.kind {
+        if let ExprKind::Binary(op, left, right) = e.kind {
             if e.span.from_expansion() {
                 return;
             }
             let macro_with_not_op = |expr_kind: &ExprKind<'_>| {
-                if let ExprKind::Unary(_, ref expr) = *expr_kind {
+                if let ExprKind::Unary(_, expr) = *expr_kind {
                     in_macro(expr.span)
                 } else {
                     false
@@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                     // do not suggest to dereference literals
                     (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {},
                     // &foo == &bar
-                    (&ExprKind::AddrOf(BorrowKind::Ref, _, ref l), &ExprKind::AddrOf(BorrowKind::Ref, _, ref r)) => {
+                    (&ExprKind::AddrOf(BorrowKind::Ref, _, l), &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => {
                         let lty = cx.typeck_results().expr_ty(l);
                         let rty = cx.typeck_results().expr_ty(r);
                         let lcpy = is_copy(cx, lty);
@@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                         }
                     },
                     // &foo == bar
-                    (&ExprKind::AddrOf(BorrowKind::Ref, _, ref l), _) => {
+                    (&ExprKind::AddrOf(BorrowKind::Ref, _, l), _) => {
                         let lty = cx.typeck_results().expr_ty(l);
                         let lcpy = is_copy(cx, lty);
                         if (requires_ref || lcpy)
@@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                         }
                     },
                     // foo == &bar
-                    (_, &ExprKind::AddrOf(BorrowKind::Ref, _, ref r)) => {
+                    (_, &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => {
                         let rty = cx.typeck_results().expr_ty(r);
                         let rcpy = is_copy(cx, rty);
                         if (requires_ref || rcpy)
diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs
index 59602616781..f95ca86a2d0 100644
--- a/clippy_lints/src/erasing_op.rs
+++ b/clippy_lints/src/erasing_op.rs
@@ -34,7 +34,7 @@ impl<'tcx> LateLintPass<'tcx> for ErasingOp {
         if e.span.from_expansion() {
             return;
         }
-        if let ExprKind::Binary(ref cmp, ref left, ref right) = e.kind {
+        if let ExprKind::Binary(ref cmp, left, right) = e.kind {
             match cmp.node {
                 BinOpKind::Mul | BinOpKind::BitAnd => {
                     check(cx, left, e.span);
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 99253555a95..2f1aa53236d 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
 }
 
 fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.kind {
+    if let ExprKind::Closure(_, decl, eid, _, _) = expr.kind {
         let body = cx.tcx.hir().body(eid);
         let ex = &body.value;
 
@@ -109,7 +109,7 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
         }
 
         if_chain!(
-            if let ExprKind::Call(ref caller, ref args) = ex.kind;
+            if let ExprKind::Call(caller, args) = ex.kind;
 
             if let ExprKind::Path(_) = caller.kind;
 
@@ -142,7 +142,7 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
         );
 
         if_chain!(
-            if let ExprKind::MethodCall(ref path, _, ref args, _) = ex.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = ex.kind;
 
             // Not the same number of arguments, there is no way the closure is the same as the function return;
             if args.len() == decl.inputs.len();
@@ -178,7 +178,7 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a
     let actual_type_of_self = &cx.typeck_results().node_type(self_arg.hir_id);
 
     if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) {
-        if match_borrow_depth(expected_type_of_self, &actual_type_of_self)
+        if match_borrow_depth(expected_type_of_self, actual_type_of_self)
             && implements_trait(cx, actual_type_of_self, trait_id, &[])
         {
             return Some(cx.tcx.def_path_str(trait_id));
@@ -187,8 +187,8 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a
 
     cx.tcx.impl_of_method(method_def_id).and_then(|_| {
         //a type may implicitly implement other type's methods (e.g. Deref)
-        if match_types(expected_type_of_self, &actual_type_of_self) {
-            return Some(get_type_name(cx, &actual_type_of_self));
+        if match_types(expected_type_of_self, actual_type_of_self) {
+            return Some(get_type_name(cx, actual_type_of_self));
         }
         None
     })
@@ -196,7 +196,7 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a
 
 fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
     match (&lhs.kind(), &rhs.kind()) {
-        (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(&t1, &t2),
+        (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(t1, t2),
         (l, r) => !matches!((l, r), (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _))),
     }
 }
@@ -218,7 +218,7 @@ fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
 fn get_type_name(cx: &LateContext<'_>, ty: Ty<'_>) -> String {
     match ty.kind() {
         ty::Adt(t, _) => cx.tcx.def_path_str(t.did),
-        ty::Ref(_, r, _) => get_type_name(cx, &r),
+        ty::Ref(_, r, _) => get_type_name(cx, r),
         _ => ty.to_string(),
     }
 }
@@ -230,7 +230,7 @@ fn compare_inputs(
     for (closure_input, function_arg) in closure_inputs.zip(call_args) {
         if let PatKind::Binding(_, _, ident, _) = closure_input.pat.kind {
             // XXXManishearth Should I be checking the binding mode here?
-            if let ExprKind::Path(QPath::Resolved(None, ref p)) = function_arg.kind {
+            if let ExprKind::Path(QPath::Resolved(None, p)) = function_arg.kind {
                 if p.segments.len() != 1 {
                     // If it's a proper path, it can't be a local variable
                     return false;
diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs
index ea33a4d98fd..762f64fe37a 100644
--- a/clippy_lints/src/eval_order_dependence.rs
+++ b/clippy_lints/src/eval_order_dependence.rs
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // Find a write to a local variable.
         match expr.kind {
-            ExprKind::Assign(ref lhs, ..) | ExprKind::AssignOp(_, ref lhs, _) => {
+            ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) => {
                 if let Some(var) = path_to_local(lhs) {
                     let mut visitor = ReadVisitor {
                         cx,
@@ -87,12 +87,12 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence {
     }
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         match stmt.kind {
-            StmtKind::Local(ref local) => {
-                if let Local { init: Some(ref e), .. } = **local {
+            StmtKind::Local(local) => {
+                if let Local { init: Some(e), .. } = local {
                     DivergenceVisitor { cx }.visit_expr(e);
                 }
             },
-            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => DivergenceVisitor { cx }.maybe_walk_expr(e),
+            StmtKind::Expr(e) | StmtKind::Semi(e) => DivergenceVisitor { cx }.maybe_walk_expr(e),
             StmtKind::Item(..) => {},
         }
     }
@@ -106,7 +106,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
     fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
             ExprKind::Closure(..) => {},
-            ExprKind::Match(ref e, arms, _) => {
+            ExprKind::Match(e, arms, _) => {
                 self.visit_expr(e);
                 for arm in arms {
                     if let Some(Guard::If(if_expr)) = arm.guard {
@@ -130,7 +130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
             ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e),
-            ExprKind::Call(ref func, _) => {
+            ExprKind::Call(func, _) => {
                 let typ = self.cx.typeck_results().expr_ty(func);
                 match typ.kind() {
                     ty::FnDef(..) | ty::FnPtr(_) => {
@@ -266,10 +266,10 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr<'_>) -
 
 fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt<'_>) -> StopEarly {
     match stmt.kind {
-        StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => check_expr(vis, expr),
+        StmtKind::Expr(expr) | StmtKind::Semi(expr) => check_expr(vis, expr),
         // If the declaration is of a local variable, check its initializer
         // expression if it has one. Otherwise, keep going.
-        StmtKind::Local(ref local) => local
+        StmtKind::Local(local) => local
             .init
             .as_ref()
             .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)),
@@ -343,7 +343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
 /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`.
 fn is_in_assignment_position(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     if let Some(parent) = get_parent_expr(cx, expr) {
-        if let ExprKind::Assign(ref lhs, ..) = parent.kind {
+        if let ExprKind::Assign(lhs, ..) = parent.kind {
             return lhs.hir_id == expr.hir_id;
         }
     }
diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs
index 6c9652fd87d..249ee27330b 100644
--- a/clippy_lints/src/excessive_bools.rs
+++ b/clippy_lints/src/excessive_bools.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{attr_by_name, in_macro, match_path_ast};
+use clippy_utils::{in_macro, match_path_ast};
 use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 
 use std::convert::TryInto;
 
@@ -138,7 +138,7 @@ impl EarlyLintPass for ExcessiveBools {
         }
         match &item.kind {
             ItemKind::Struct(variant_data, _) => {
-                if attr_by_name(&item.attrs, "repr").is_some() {
+                if item.attrs.iter().any(|attr| attr.has_name(sym::repr)) {
                     return;
                 }
 
diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs
index 635b6d83eab..16246e548b6 100644
--- a/clippy_lints/src/exit.rs
+++ b/clippy_lints/src/exit.rs
@@ -28,20 +28,18 @@ declare_lint_pass!(Exit => [EXIT]);
 impl<'tcx> LateLintPass<'tcx> for Exit {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::Call(ref path_expr, ref _args) = e.kind;
+            if let ExprKind::Call(path_expr, _args) = e.kind;
             if let ExprKind::Path(ref path) = path_expr.kind;
             if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id();
             if match_def_path(cx, def_id, &paths::EXIT);
+            let parent = cx.tcx.hir().get_parent_item(e.hir_id);
+            if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find(parent);
+            // If the next item up is a function we check if it is an entry point
+            // and only then emit a linter warning
+            let def_id = cx.tcx.hir().local_def_id(parent);
+            if !is_entrypoint_fn(cx, def_id.to_def_id());
             then {
-                let parent = cx.tcx.hir().get_parent_item(e.hir_id);
-                if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find(parent) {
-                    // If the next item up is a function we check if it is an entry point
-                    // and only then emit a linter warning
-                    let def_id = cx.tcx.hir().local_def_id(parent);
-                    if !is_entrypoint_fn(cx, def_id.to_def_id()) {
-                        span_lint(cx, EXIT, e.span, "usage of `process::exit`");
-                    }
-                }
+                span_lint(cx, EXIT, e.span, "usage of `process::exit`");
             }
         }
     }
diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs
index 4146b7baa10..da4936ff25b 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -34,11 +34,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // match call to unwrap
-            if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args, _) = expr.kind;
+            if let ExprKind::MethodCall(unwrap_fun, _, unwrap_args, _) = expr.kind;
             if unwrap_fun.ident.name == sym::unwrap;
             // match call to write_fmt
             if !unwrap_args.is_empty();
-            if let ExprKind::MethodCall(ref write_fun, _, write_args, _) =
+            if let ExprKind::MethodCall(write_fun, _, write_args, _) =
                 unwrap_args[0].kind;
             if write_fun.ident.name == sym!(write_fmt);
             // match calls to std::io::stdout() / std::io::stderr ()
@@ -135,10 +135,10 @@ fn write_output_string(write_args: &[Expr<'_>]) -> Option<String> {
     if_chain! {
         // Obtain the string that should be printed
         if write_args.len() > 1;
-        if let ExprKind::Call(_, ref output_args) = write_args[1].kind;
+        if let ExprKind::Call(_, output_args) = write_args[1].kind;
         if !output_args.is_empty();
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref output_string_expr) = output_args[0].kind;
-        if let ExprKind::Array(ref string_exprs) = output_string_expr.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, output_string_expr) = output_args[0].kind;
+        if let ExprKind::Array(string_exprs) = output_string_expr.kind;
         // we only want to provide an automatic suggestion for simple (non-format) strings
         if string_exprs.len() == 1;
         if let ExprKind::Lit(ref lit) = string_exprs[0].kind;
diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs
index 52a5a7acf0d..2937fcb9ca0 100644
--- a/clippy_lints/src/fallible_impl_from.rs
+++ b/clippy_lints/src/fallible_impl_from.rs
@@ -81,8 +81,8 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h
         fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
             // check for `begin_panic`
             if_chain! {
-                if let ExprKind::Call(ref func_expr, _) = expr.kind;
-                if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.kind;
+                if let ExprKind::Call(func_expr, _) = expr.kind;
+                if let ExprKind::Path(QPath::Resolved(_, path)) = func_expr.kind;
                 if let Some(path_def_id) = path.res.opt_def_id();
                 if match_panic_def_id(self.lcx, path_def_id);
                 if is_expn_of(expr.span, "unreachable").is_none();
diff --git a/clippy_lints/src/float_equality_without_abs.rs b/clippy_lints/src/float_equality_without_abs.rs
index 0c59db360f9..b5ebe5f90ba 100644
--- a/clippy_lints/src/float_equality_without_abs.rs
+++ b/clippy_lints/src/float_equality_without_abs.rs
@@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs {
         let rhs;
 
         // check if expr is a binary expression with a lt or gt operator
-        if let ExprKind::Binary(op, ref left, ref right) = expr.kind {
+        if let ExprKind::Binary(op, left, right) = expr.kind {
             match op.node {
                 BinOpKind::Lt => {
                     lhs = left;
@@ -88,8 +88,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs {
             if let ty::Float(_) = t_val_r.kind();
 
             then {
-                let sug_l = sugg::Sugg::hir(cx, &val_l, "..");
-                let sug_r = sugg::Sugg::hir(cx, &val_r, "..");
+                let sug_l = sugg::Sugg::hir(cx, val_l, "..");
+                let sug_r = sugg::Sugg::hir(cx, val_r, "..");
                 // format the suggestion
                 let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par());
                 // spans the lint
diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs
index 1ca5c685a75..7968e7b764d 100644
--- a/clippy_lints/src/float_literal.rs
+++ b/clippy_lints/src/float_literal.rs
@@ -61,8 +61,8 @@ declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]);
 
 impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+        let ty = cx.typeck_results().expr_ty(expr);
         if_chain! {
-            let ty = cx.typeck_results().expr_ty(expr);
             if let ty::Float(fty) = *ty.kind();
             if let hir::ExprKind::Lit(ref lit) = expr.kind;
             if let LitKind::Float(sym, lit_float_ty) = lit.node;
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index 0b5f0379ce6..e0b687b0205 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -131,7 +131,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
     let mut suggestion = Sugg::hir(cx, expr, "..");
 
     if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind {
-        expr = &inner_expr;
+        expr = inner_expr;
     }
 
     if_chain! {
@@ -313,8 +313,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
                     Spanned {
                         node: BinOpKind::Add, ..
                     },
-                    ref lhs,
-                    ref rhs,
+                    lhs,
+                    rhs,
                 ) = parent.kind
                 {
                     let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
@@ -329,7 +329,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
                             "{}.mul_add({}, {})",
                             Sugg::hir(cx, &args[0], ".."),
                             Sugg::hir(cx, &args[0], ".."),
-                            Sugg::hir(cx, &other_addend, ".."),
+                            Sugg::hir(cx, other_addend, ".."),
                         ),
                         Applicability::MachineApplicable,
                     );
@@ -356,18 +356,18 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
         Spanned {
             node: BinOpKind::Add, ..
         },
-        ref add_lhs,
-        ref add_rhs,
+        add_lhs,
+        add_rhs,
     ) = args[0].kind
     {
         // check if expression of the form x * x + y * y
         if_chain! {
-            if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lmul_lhs, ref lmul_rhs) = add_lhs.kind;
-            if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref rmul_lhs, ref rmul_rhs) = add_rhs.kind;
+            if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lmul_lhs, lmul_rhs) = add_lhs.kind;
+            if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, rmul_lhs, rmul_rhs) = add_rhs.kind;
             if eq_expr_value(cx, lmul_lhs, lmul_rhs);
             if eq_expr_value(cx, rmul_lhs, rmul_rhs);
             then {
-                return Some(format!("{}.hypot({})", Sugg::hir(cx, &lmul_lhs, ".."), Sugg::hir(cx, &rmul_lhs, "..")));
+                return Some(format!("{}.hypot({})", Sugg::hir(cx, lmul_lhs, ".."), Sugg::hir(cx, rmul_lhs, "..")));
             }
         }
 
@@ -376,13 +376,13 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
             if let ExprKind::MethodCall(
                 PathSegment { ident: lmethod_name, .. },
                 ref _lspan,
-                ref largs,
+                largs,
                 _
             ) = add_lhs.kind;
             if let ExprKind::MethodCall(
                 PathSegment { ident: rmethod_name, .. },
                 ref _rspan,
-                ref rargs,
+                rargs,
                 _
             ) = add_rhs.kind;
             if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
@@ -416,11 +416,11 @@ fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
 // and suggest usage of `x.exp_m1() - (y - 1)` instead
 fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) = expr.kind;
+        if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind;
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
         if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
         if F32(1.0) == value || F64(1.0) == value;
-        if let ExprKind::MethodCall(ref path, _, ref method_args, _) = lhs.kind;
+        if let ExprKind::MethodCall(path, _, method_args, _) = lhs.kind;
         if cx.typeck_results().expr_ty(&method_args[0]).is_floating_point();
         if path.ident.name.as_str() == "exp";
         then {
@@ -442,7 +442,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
 fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
     if_chain! {
-        if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lhs, ref rhs) = &expr.kind;
+        if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lhs, rhs) = &expr.kind;
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
         if cx.typeck_results().expr_ty(rhs).is_floating_point();
         then {
@@ -604,8 +604,8 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
 fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, ref args_a, _) = expr_a.kind;
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, ref args_b, _) = expr_b.kind;
+        if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind;
+        if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind;
         then {
             return method_name_a.as_str() == method_name_b.as_str() &&
                 args_a.len() == args_b.len() &&
@@ -630,8 +630,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
             rhs,
         ) = &expr.kind;
         if are_same_base_logs(cx, lhs, rhs);
-        if let ExprKind::MethodCall(_, _, ref largs, _) = lhs.kind;
-        if let ExprKind::MethodCall(_, _, ref rargs, _) = rhs.kind;
+        if let ExprKind::MethodCall(_, _, largs, _) = lhs.kind;
+        if let ExprKind::MethodCall(_, _, rargs, _) = rhs.kind;
         then {
             span_lint_and_sugg(
                 cx,
@@ -675,7 +675,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
                     expr.span,
                     "conversion to degrees can be done more accurately",
                     "consider using",
-                    format!("{}.to_degrees()", Sugg::hir(cx, &mul_lhs, "..")),
+                    format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..")),
                     Applicability::MachineApplicable,
                 );
             } else if
@@ -688,7 +688,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
                     expr.span,
                     "conversion to radians can be done more accurately",
                     "consider using",
-                    format!("{}.to_radians()", Sugg::hir(cx, &mul_lhs, "..")),
+                    format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..")),
                     Applicability::MachineApplicable,
                 );
             }
@@ -698,7 +698,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
 impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind {
+        if let ExprKind::MethodCall(path, _, args, _) = &expr.kind {
             let recv_ty = cx.typeck_results().expr_ty(&args[0]);
 
             if recv_ty.is_floating_point() {
diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index a33f987b423..4729abbd8e3 100644
--- a/clippy_lints/src/format.rs
+++ b/clippy_lints/src/format.rs
@@ -78,8 +78,8 @@ fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg:
 
 fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> {
     if_chain! {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind;
-        if let ExprKind::Array(ref elems) = arms[0].body.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, format_args) = expr.kind;
+        if let ExprKind::Array(elems) = arms[0].body.kind;
         if elems.len() == 1;
         if let Some(args) = match_function_call(cx, &elems[0], &paths::FMT_ARGUMENTV1_NEW);
         // matches `core::fmt::Display::fmt`
@@ -88,10 +88,10 @@ fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &
         if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
         if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
         // check `(arg0,)` in match block
-        if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
+        if let PatKind::Tuple(pats, None) = arms[0].pat.kind;
         if pats.len() == 1;
         then {
-            let ty = cx.typeck_results().pat_ty(&pats[0]).peel_refs();
+            let ty = cx.typeck_results().pat_ty(pats[0]).peel_refs();
             if *ty.kind() != rustc_middle::ty::Str && !is_type_diagnostic_item(cx, ty, sym::string_type) {
                 return None;
             }
@@ -101,7 +101,7 @@ fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &
                 }
             } else {
                 let snip = snippet(cx, format_args.span, "<arg>");
-                if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
+                if let ExprKind::MethodCall(path, _, _, _) = format_args.kind {
                     if path.ident.name == sym!(to_string) {
                         return Some(format!("{}", snip));
                     }
@@ -120,16 +120,16 @@ fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Strin
         if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1);
         if args.len() == 2;
         // Argument 1 in `new_v1()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
-        if let ExprKind::Array(ref pieces) = arr.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, arr) = args[0].kind;
+        if let ExprKind::Array(pieces) = arr.kind;
         if pieces.len() == 1;
         if let ExprKind::Lit(ref lit) = pieces[0].kind;
         if let LitKind::Str(ref s, _) = lit.node;
         // Argument 2 in `new_v1()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
-        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, arg1) = args[1].kind;
+        if let ExprKind::Match(matchee, arms, MatchSource::Normal) = arg1.kind;
         if arms.len() == 1;
-        if let ExprKind::Tup(ref tup) = matchee.kind;
+        if let ExprKind::Tup(tup) = matchee.kind;
         then {
             // `format!("foo")` expansion contains `match () { () => [], }`
             if tup.is_empty() {
@@ -152,16 +152,16 @@ fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<S
         if args.len() == 3;
         if check_unformatted(&args[2]);
         // Argument 1 in `new_v1_formatted()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
-        if let ExprKind::Array(ref pieces) = arr.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, arr) = args[0].kind;
+        if let ExprKind::Array(pieces) = arr.kind;
         if pieces.len() == 1;
         if let ExprKind::Lit(ref lit) = pieces[0].kind;
         if let LitKind::Str(..) = lit.node;
         // Argument 2 in `new_v1_formatted()`
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
-        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, arg1) = args[1].kind;
+        if let ExprKind::Match(matchee, arms, MatchSource::Normal) = arg1.kind;
         if arms.len() == 1;
-        if let ExprKind::Tup(ref tup) = matchee.kind;
+        if let ExprKind::Tup(tup) = matchee.kind;
         then {
             return on_argumentv1_new(cx, &tup[0], arms);
         }
@@ -182,14 +182,14 @@ fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<S
 /// ```
 fn check_unformatted(expr: &Expr<'_>) -> bool {
     if_chain! {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind;
-        if let ExprKind::Array(ref exprs) = expr.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind;
+        if let ExprKind::Array(exprs) = expr.kind;
         if exprs.len() == 1;
         // struct `core::fmt::rt::v1::Argument`
-        if let ExprKind::Struct(_, ref fields, _) = exprs[0].kind;
+        if let ExprKind::Struct(_, fields, _) = exprs[0].kind;
         if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format);
         // struct `core::fmt::rt::v1::FormatSpec`
-        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.kind;
+        if let ExprKind::Struct(_, fields, _) = format_field.expr.kind;
         if let Some(precision_field) = fields.iter().find(|f| f.ident.name == sym::precision);
         if let ExprKind::Path(ref precision_path) = precision_field.expr.kind;
         if last_path_segment(precision_path).ident.name == sym::Implied;
diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs
index b10e83c0ea8..48612befc68 100644
--- a/clippy_lints/src/formatting.rs
+++ b/clippy_lints/src/formatting.rs
@@ -217,9 +217,8 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
         if let Some(else_snippet) = snippet_opt(cx, else_span);
         if let Some(else_pos) = else_snippet.find("else");
         if else_snippet[else_pos..].contains('\n');
-        let else_desc = if is_if(else_) { "if" } else { "{..}" };
-
         then {
+            let else_desc = if is_if(else_) { "if" } else { "{..}" };
             span_lint_and_note(
                 cx,
                 SUSPICIOUS_ELSE_FORMATTING,
diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs
deleted file mode 100644
index 5fe46065348..00000000000
--- a/clippy_lints/src/functions.rs
+++ /dev/null
@@ -1,738 +0,0 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_opt};
-use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, type_is_unsafe_function};
-use clippy_utils::{
-    attr_by_name, attrs::is_proc_macro, is_trait_impl_item, iter_input_pats, match_def_path, must_use_attr,
-    path_to_local, return_ty, trait_ref_of_method,
-};
-use if_chain::if_chain;
-use rustc_ast::ast::Attribute;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_hir::intravisit;
-use rustc_hir::{def::Res, def_id::DefId, QPath};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
-use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Ty};
-use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::source_map::Span;
-use rustc_span::sym;
-use rustc_target::spec::abi::Abi;
-use rustc_typeck::hir_ty_to_ty;
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for functions with too many parameters.
-    ///
-    /// **Why is this bad?** Functions with lots of parameters are considered bad
-    /// style and reduce readability (“what does the 5th parameter mean?”). Consider
-    /// grouping some parameters into a new type.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// # struct Color;
-    /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
-    ///     // ..
-    /// }
-    /// ```
-    pub TOO_MANY_ARGUMENTS,
-    complexity,
-    "functions with too many arguments"
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for functions with a large amount of lines.
-    ///
-    /// **Why is this bad?** Functions with a lot of lines are harder to understand
-    /// due to having to look at a larger amount of code to understand what the
-    /// function is doing. Consider splitting the body of the function into
-    /// multiple functions.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// fn im_too_long() {
-    ///     println!("");
-    ///     // ... 100 more LoC
-    ///     println!("");
-    /// }
-    /// ```
-    pub TOO_MANY_LINES,
-    pedantic,
-    "functions with too many lines"
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for public functions that dereference raw pointer
-    /// arguments but are not marked unsafe.
-    ///
-    /// **Why is this bad?** The function should probably be marked `unsafe`, since
-    /// for an arbitrary raw pointer, there is no way of telling for sure if it is
-    /// valid.
-    ///
-    /// **Known problems:**
-    ///
-    /// * It does not check functions recursively so if the pointer is passed to a
-    /// private non-`unsafe` function which does the dereferencing, the lint won't
-    /// trigger.
-    /// * It only checks for arguments whose type are raw pointers, not raw pointers
-    /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or
-    /// `some_argument.get_raw_ptr()`).
-    ///
-    /// **Example:**
-    /// ```rust,ignore
-    /// // Bad
-    /// pub fn foo(x: *const u8) {
-    ///     println!("{}", unsafe { *x });
-    /// }
-    ///
-    /// // Good
-    /// pub unsafe fn foo(x: *const u8) {
-    ///     println!("{}", unsafe { *x });
-    /// }
-    /// ```
-    pub NOT_UNSAFE_PTR_ARG_DEREF,
-    correctness,
-    "public functions dereferencing raw pointer arguments but not marked `unsafe`"
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for a [`#[must_use]`] attribute on
-    /// unit-returning functions and methods.
-    ///
-    /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
-    ///
-    /// **Why is this bad?** Unit values are useless. The attribute is likely
-    /// a remnant of a refactoring that removed the return type.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Examples:**
-    /// ```rust
-    /// #[must_use]
-    /// fn useless() { }
-    /// ```
-    pub MUST_USE_UNIT,
-    style,
-    "`#[must_use]` attribute on a unit-returning function / method"
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for a [`#[must_use]`] attribute without
-    /// further information on functions and methods that return a type already
-    /// marked as `#[must_use]`.
-    ///
-    /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
-    ///
-    /// **Why is this bad?** The attribute isn't needed. Not using the result
-    /// will already be reported. Alternatively, one can add some text to the
-    /// attribute to improve the lint message.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Examples:**
-    /// ```rust
-    /// #[must_use]
-    /// fn double_must_use() -> Result<(), ()> {
-    ///     unimplemented!();
-    /// }
-    /// ```
-    pub DOUBLE_MUST_USE,
-    style,
-    "`#[must_use]` attribute on a `#[must_use]`-returning function / method"
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for public functions that have no
-    /// [`#[must_use]`] attribute, but return something not already marked
-    /// must-use, have no mutable arg and mutate no statics.
-    ///
-    /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
-    ///
-    /// **Why is this bad?** Not bad at all, this lint just shows places where
-    /// you could add the attribute.
-    ///
-    /// **Known problems:** The lint only checks the arguments for mutable
-    /// types without looking if they are actually changed. On the other hand,
-    /// it also ignores a broad range of potentially interesting side effects,
-    /// because we cannot decide whether the programmer intends the function to
-    /// be called for the side effect or the result. Expect many false
-    /// positives. At least we don't lint if the result type is unit or already
-    /// `#[must_use]`.
-    ///
-    /// **Examples:**
-    /// ```rust
-    /// // this could be annotated with `#[must_use]`.
-    /// fn id<T>(t: T) -> T { t }
-    /// ```
-    pub MUST_USE_CANDIDATE,
-    pedantic,
-    "function or method that could take a `#[must_use]` attribute"
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for public functions that return a `Result`
-    /// with an `Err` type of `()`. It suggests using a custom type that
-    /// implements [`std::error::Error`].
-    ///
-    /// **Why is this bad?** Unit does not implement `Error` and carries no
-    /// further information about what went wrong.
-    ///
-    /// **Known problems:** Of course, this lint assumes that `Result` is used
-    /// for a fallible operation (which is after all the intended use). However
-    /// code may opt to (mis)use it as a basic two-variant-enum. In that case,
-    /// the suggestion is misguided, and the code should use a custom enum
-    /// instead.
-    ///
-    /// **Examples:**
-    /// ```rust
-    /// pub fn read_u8() -> Result<u8, ()> { Err(()) }
-    /// ```
-    /// should become
-    /// ```rust,should_panic
-    /// use std::fmt;
-    ///
-    /// #[derive(Debug)]
-    /// pub struct EndOfStream;
-    ///
-    /// impl fmt::Display for EndOfStream {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "End of Stream")
-    ///     }
-    /// }
-    ///
-    /// impl std::error::Error for EndOfStream { }
-    ///
-    /// pub fn read_u8() -> Result<u8, EndOfStream> { Err(EndOfStream) }
-    ///# fn main() {
-    ///#     read_u8().unwrap();
-    ///# }
-    /// ```
-    ///
-    /// Note that there are crates that simplify creating the error type, e.g.
-    /// [`thiserror`](https://docs.rs/thiserror).
-    pub RESULT_UNIT_ERR,
-    style,
-    "public function returning `Result` with an `Err` type of `()`"
-}
-
-#[derive(Copy, Clone)]
-pub struct Functions {
-    threshold: u64,
-    max_lines: u64,
-}
-
-impl Functions {
-    pub fn new(threshold: u64, max_lines: u64) -> Self {
-        Self { threshold, max_lines }
-    }
-}
-
-impl_lint_pass!(Functions => [
-    TOO_MANY_ARGUMENTS,
-    TOO_MANY_LINES,
-    NOT_UNSAFE_PTR_ARG_DEREF,
-    MUST_USE_UNIT,
-    DOUBLE_MUST_USE,
-    MUST_USE_CANDIDATE,
-    RESULT_UNIT_ERR,
-]);
-
-impl<'tcx> LateLintPass<'tcx> for Functions {
-    fn check_fn(
-        &mut self,
-        cx: &LateContext<'tcx>,
-        kind: intravisit::FnKind<'tcx>,
-        decl: &'tcx hir::FnDecl<'_>,
-        body: &'tcx hir::Body<'_>,
-        span: Span,
-        hir_id: hir::HirId,
-    ) {
-        let unsafety = match kind {
-            intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
-            intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
-            intravisit::FnKind::Closure => return,
-        };
-
-        // don't warn for implementations, it's not their fault
-        if !is_trait_impl_item(cx, hir_id) {
-            // don't lint extern functions decls, it's not their fault either
-            match kind {
-                intravisit::FnKind::Method(
-                    _,
-                    &hir::FnSig {
-                        header: hir::FnHeader { abi: Abi::Rust, .. },
-                        ..
-                    },
-                    _,
-                )
-                | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => {
-                    self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi()))
-                },
-                _ => {},
-            }
-        }
-
-        Self::check_raw_ptr(cx, unsafety, decl, body, hir_id);
-        self.check_line_number(cx, span, body);
-    }
-
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let attr = must_use_attr(attrs);
-        if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind {
-            let is_public = cx.access_levels.is_exported(item.hir_id());
-            let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-            if is_public {
-                check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
-            }
-            if let Some(attr) = attr {
-                check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
-                return;
-            }
-            if is_public && !is_proc_macro(cx.sess(), attrs) && attr_by_name(attrs, "no_mangle").is_none() {
-                check_must_use_candidate(
-                    cx,
-                    &sig.decl,
-                    cx.tcx.hir().body(*body_id),
-                    item.span,
-                    item.hir_id(),
-                    item.span.with_hi(sig.decl.output.span().hi()),
-                    "this function could have a `#[must_use]` attribute",
-                );
-            }
-        }
-    }
-
-    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
-            let is_public = cx.access_levels.is_exported(item.hir_id());
-            let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-            if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() {
-                check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
-            }
-            let attrs = cx.tcx.hir().attrs(item.hir_id());
-            let attr = must_use_attr(attrs);
-            if let Some(attr) = attr {
-                check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
-            } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.hir_id()).is_none()
-            {
-                check_must_use_candidate(
-                    cx,
-                    &sig.decl,
-                    cx.tcx.hir().body(*body_id),
-                    item.span,
-                    item.hir_id(),
-                    item.span.with_hi(sig.decl.output.span().hi()),
-                    "this method could have a `#[must_use]` attribute",
-                );
-            }
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
-            // don't lint extern functions decls, it's not their fault
-            if sig.header.abi == Abi::Rust {
-                self.check_arg_number(cx, &sig.decl, item.span.with_hi(sig.decl.output.span().hi()));
-            }
-            let is_public = cx.access_levels.is_exported(item.hir_id());
-            let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-            if is_public {
-                check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
-            }
-
-            let attrs = cx.tcx.hir().attrs(item.hir_id());
-            let attr = must_use_attr(attrs);
-            if let Some(attr) = attr {
-                check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
-            }
-            if let hir::TraitFn::Provided(eid) = *eid {
-                let body = cx.tcx.hir().body(eid);
-                Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
-
-                if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
-                    check_must_use_candidate(
-                        cx,
-                        &sig.decl,
-                        body,
-                        item.span,
-                        item.hir_id(),
-                        item.span.with_hi(sig.decl.output.span().hi()),
-                        "this method could have a `#[must_use]` attribute",
-                    );
-                }
-            }
-        }
-    }
-}
-
-impl<'tcx> Functions {
-    fn check_arg_number(self, cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span) {
-        let args = decl.inputs.len() as u64;
-        if args > self.threshold {
-            span_lint(
-                cx,
-                TOO_MANY_ARGUMENTS,
-                fn_span,
-                &format!("this function has too many arguments ({}/{})", args, self.threshold),
-            );
-        }
-    }
-
-    fn check_line_number(self, cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>) {
-        if in_external_macro(cx.sess(), span) {
-            return;
-        }
-
-        let code_snippet = snippet(cx, body.value.span, "..");
-        let mut line_count: u64 = 0;
-        let mut in_comment = false;
-        let mut code_in_line;
-
-        // Skip the surrounding function decl.
-        let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1);
-        let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len());
-        let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines();
-
-        for mut line in function_lines {
-            code_in_line = false;
-            loop {
-                line = line.trim_start();
-                if line.is_empty() {
-                    break;
-                }
-                if in_comment {
-                    if let Some(i) = line.find("*/") {
-                        line = &line[i + 2..];
-                        in_comment = false;
-                        continue;
-                    }
-                } else {
-                    let multi_idx = line.find("/*").unwrap_or_else(|| line.len());
-                    let single_idx = line.find("//").unwrap_or_else(|| line.len());
-                    code_in_line |= multi_idx > 0 && single_idx > 0;
-                    // Implies multi_idx is below line.len()
-                    if multi_idx < single_idx {
-                        line = &line[multi_idx + 2..];
-                        in_comment = true;
-                        continue;
-                    }
-                }
-                break;
-            }
-            if code_in_line {
-                line_count += 1;
-            }
-        }
-
-        if line_count > self.max_lines {
-            span_lint(
-                cx,
-                TOO_MANY_LINES,
-                span,
-                &format!("this function has too many lines ({}/{})", line_count, self.max_lines),
-            )
-        }
-    }
-
-    fn check_raw_ptr(
-        cx: &LateContext<'tcx>,
-        unsafety: hir::Unsafety,
-        decl: &'tcx hir::FnDecl<'_>,
-        body: &'tcx hir::Body<'_>,
-        hir_id: hir::HirId,
-    ) {
-        let expr = &body.value;
-        if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
-            let raw_ptrs = iter_input_pats(decl, body)
-                .zip(decl.inputs.iter())
-                .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
-                .collect::<FxHashSet<_>>();
-
-            if !raw_ptrs.is_empty() {
-                let typeck_results = cx.tcx.typeck_body(body.id());
-                let mut v = DerefVisitor {
-                    cx,
-                    ptrs: raw_ptrs,
-                    typeck_results,
-                };
-
-                intravisit::walk_expr(&mut v, expr);
-            }
-        }
-    }
-}
-
-fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) {
-    if_chain! {
-        if !in_external_macro(cx.sess(), item_span);
-        if let hir::FnRetTy::Return(ref ty) = decl.output;
-        let ty = hir_ty_to_ty(cx.tcx, ty);
-        if is_type_diagnostic_item(cx, ty, sym::result_type);
-        if let ty::Adt(_, substs) = ty.kind();
-        let err_ty = substs.type_at(1);
-        if err_ty.is_unit();
-        then {
-            span_lint_and_help(
-                cx,
-                RESULT_UNIT_ERR,
-                fn_header_span,
-                "this returns a `Result<_, ()>",
-                None,
-                "use a custom Error type instead",
-            );
-        }
-    }
-}
-
-fn check_needless_must_use(
-    cx: &LateContext<'_>,
-    decl: &hir::FnDecl<'_>,
-    item_id: hir::HirId,
-    item_span: Span,
-    fn_header_span: Span,
-    attr: &Attribute,
-) {
-    if in_external_macro(cx.sess(), item_span) {
-        return;
-    }
-    if returns_unit(decl) {
-        span_lint_and_then(
-            cx,
-            MUST_USE_UNIT,
-            fn_header_span,
-            "this unit-returning function has a `#[must_use]` attribute",
-            |diag| {
-                diag.span_suggestion(
-                    attr.span,
-                    "remove the attribute",
-                    "".into(),
-                    Applicability::MachineApplicable,
-                );
-            },
-        );
-    } else if !attr.value_str().is_some() && is_must_use_ty(cx, return_ty(cx, item_id)) {
-        span_lint_and_help(
-            cx,
-            DOUBLE_MUST_USE,
-            fn_header_span,
-            "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`",
-            None,
-            "either add some descriptive text or remove the attribute",
-        );
-    }
-}
-
-fn check_must_use_candidate<'tcx>(
-    cx: &LateContext<'tcx>,
-    decl: &'tcx hir::FnDecl<'_>,
-    body: &'tcx hir::Body<'_>,
-    item_span: Span,
-    item_id: hir::HirId,
-    fn_span: Span,
-    msg: &str,
-) {
-    if has_mutable_arg(cx, body)
-        || mutates_static(cx, body)
-        || in_external_macro(cx.sess(), item_span)
-        || returns_unit(decl)
-        || !cx.access_levels.is_exported(item_id)
-        || is_must_use_ty(cx, return_ty(cx, item_id))
-    {
-        return;
-    }
-    span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
-        if let Some(snippet) = snippet_opt(cx, fn_span) {
-            diag.span_suggestion(
-                fn_span,
-                "add the attribute",
-                format!("#[must_use] {}", snippet),
-                Applicability::MachineApplicable,
-            );
-        }
-    });
-}
-
-fn returns_unit(decl: &hir::FnDecl<'_>) -> bool {
-    match decl.output {
-        hir::FnRetTy::DefaultReturn(_) => true,
-        hir::FnRetTy::Return(ref ty) => match ty.kind {
-            hir::TyKind::Tup(ref tys) => tys.is_empty(),
-            hir::TyKind::Never => true,
-            _ => false,
-        },
-    }
-}
-
-fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool {
-    let mut tys = FxHashSet::default();
-    body.params.iter().any(|param| is_mutable_pat(cx, &param.pat, &mut tys))
-}
-
-fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut FxHashSet<DefId>) -> bool {
-    if let hir::PatKind::Wild = pat.kind {
-        return false; // ignore `_` patterns
-    }
-    if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
-        is_mutable_ty(cx, &cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys)
-    } else {
-        false
-    }
-}
-
-static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]];
-
-fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut FxHashSet<DefId>) -> bool {
-    match *ty.kind() {
-        // primitive types are never mutable
-        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
-        ty::Adt(ref adt, ref substs) => {
-            tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
-                || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path))
-                    && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
-        },
-        ty::Tuple(ref substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)),
-        ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys),
-        ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => {
-            mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys)
-        },
-        // calling something constitutes a side effect, so return true on all callables
-        // also never calls need not be used, so return true for them, too
-        _ => true,
-    }
-}
-
-fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
-    if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
-        Some(id)
-    } else {
-        None
-    }
-}
-
-struct DerefVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    ptrs: FxHashSet<hir::HirId>,
-    typeck_results: &'a ty::TypeckResults<'tcx>,
-}
-
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        match expr.kind {
-            hir::ExprKind::Call(ref f, args) => {
-                let ty = self.typeck_results.expr_ty(f);
-
-                if type_is_unsafe_function(self.cx, ty) {
-                    for arg in args {
-                        self.check_arg(arg);
-                    }
-                }
-            },
-            hir::ExprKind::MethodCall(_, _, args, _) => {
-                let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
-                let base_type = self.cx.tcx.type_of(def_id);
-
-                if type_is_unsafe_function(self.cx, base_type) {
-                    for arg in args {
-                        self.check_arg(arg);
-                    }
-                }
-            },
-            hir::ExprKind::Unary(hir::UnOp::Deref, ref ptr) => self.check_arg(ptr),
-            _ => (),
-        }
-
-        intravisit::walk_expr(self, expr);
-    }
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
-}
-
-impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
-    fn check_arg(&self, ptr: &hir::Expr<'_>) {
-        if let Some(id) = path_to_local(ptr) {
-            if self.ptrs.contains(&id) {
-                span_lint(
-                    self.cx,
-                    NOT_UNSAFE_PTR_ARG_DEREF,
-                    ptr.span,
-                    "this public function dereferences a raw pointer but is not marked `unsafe`",
-                );
-            }
-        }
-    }
-}
-
-struct StaticMutVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    mutates_static: bool,
-}
-
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall};
-
-        if self.mutates_static {
-            return;
-        }
-        match expr.kind {
-            Call(_, args) | MethodCall(_, _, args, _) => {
-                let mut tys = FxHashSet::default();
-                for arg in args {
-                    if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
-                        && is_mutable_ty(
-                            self.cx,
-                            self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
-                            arg.span,
-                            &mut tys,
-                        )
-                        && is_mutated_static(arg)
-                    {
-                        self.mutates_static = true;
-                        return;
-                    }
-                    tys.clear();
-                }
-            },
-            Assign(ref target, ..) | AssignOp(_, ref target, _) | AddrOf(_, hir::Mutability::Mut, ref target) => {
-                self.mutates_static |= is_mutated_static(target)
-            },
-            _ => {},
-        }
-    }
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
-}
-
-fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
-    use hir::ExprKind::{Field, Index, Path};
-
-    match e.kind {
-        Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
-        Path(_) => true,
-        Field(ref inner, _) | Index(ref inner, _) => is_mutated_static(inner),
-        _ => false,
-    }
-}
-
-fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
-    let mut v = StaticMutVisitor {
-        cx,
-        mutates_static: false,
-    };
-    intravisit::walk_expr(&mut v, &body.value);
-    v.mutates_static
-}
diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs
new file mode 100644
index 00000000000..2beb9bc94bf
--- /dev/null
+++ b/clippy_lints/src/functions/mod.rs
@@ -0,0 +1,267 @@
+mod must_use;
+mod not_unsafe_ptr_arg_deref;
+mod result_unit_err;
+mod too_many_arguments;
+mod too_many_lines;
+
+use rustc_hir as hir;
+use rustc_hir::intravisit;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for functions with too many parameters.
+    ///
+    /// **Why is this bad?** Functions with lots of parameters are considered bad
+    /// style and reduce readability (“what does the 5th parameter mean?”). Consider
+    /// grouping some parameters into a new type.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// # struct Color;
+    /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
+    ///     // ..
+    /// }
+    /// ```
+    pub TOO_MANY_ARGUMENTS,
+    complexity,
+    "functions with too many arguments"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for functions with a large amount of lines.
+    ///
+    /// **Why is this bad?** Functions with a lot of lines are harder to understand
+    /// due to having to look at a larger amount of code to understand what the
+    /// function is doing. Consider splitting the body of the function into
+    /// multiple functions.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// fn im_too_long() {
+    ///     println!("");
+    ///     // ... 100 more LoC
+    ///     println!("");
+    /// }
+    /// ```
+    pub TOO_MANY_LINES,
+    pedantic,
+    "functions with too many lines"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for public functions that dereference raw pointer
+    /// arguments but are not marked `unsafe`.
+    ///
+    /// **Why is this bad?** The function should probably be marked `unsafe`, since
+    /// for an arbitrary raw pointer, there is no way of telling for sure if it is
+    /// valid.
+    ///
+    /// **Known problems:**
+    ///
+    /// * It does not check functions recursively so if the pointer is passed to a
+    /// private non-`unsafe` function which does the dereferencing, the lint won't
+    /// trigger.
+    /// * It only checks for arguments whose type are raw pointers, not raw pointers
+    /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or
+    /// `some_argument.get_raw_ptr()`).
+    ///
+    /// **Example:**
+    /// ```rust,ignore
+    /// // Bad
+    /// pub fn foo(x: *const u8) {
+    ///     println!("{}", unsafe { *x });
+    /// }
+    ///
+    /// // Good
+    /// pub unsafe fn foo(x: *const u8) {
+    ///     println!("{}", unsafe { *x });
+    /// }
+    /// ```
+    pub NOT_UNSAFE_PTR_ARG_DEREF,
+    correctness,
+    "public functions dereferencing raw pointer arguments but not marked `unsafe`"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for a [`#[must_use]`] attribute on
+    /// unit-returning functions and methods.
+    ///
+    /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
+    ///
+    /// **Why is this bad?** Unit values are useless. The attribute is likely
+    /// a remnant of a refactoring that removed the return type.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Examples:**
+    /// ```rust
+    /// #[must_use]
+    /// fn useless() { }
+    /// ```
+    pub MUST_USE_UNIT,
+    style,
+    "`#[must_use]` attribute on a unit-returning function / method"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for a [`#[must_use]`] attribute without
+    /// further information on functions and methods that return a type already
+    /// marked as `#[must_use]`.
+    ///
+    /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
+    ///
+    /// **Why is this bad?** The attribute isn't needed. Not using the result
+    /// will already be reported. Alternatively, one can add some text to the
+    /// attribute to improve the lint message.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Examples:**
+    /// ```rust
+    /// #[must_use]
+    /// fn double_must_use() -> Result<(), ()> {
+    ///     unimplemented!();
+    /// }
+    /// ```
+    pub DOUBLE_MUST_USE,
+    style,
+    "`#[must_use]` attribute on a `#[must_use]`-returning function / method"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for public functions that have no
+    /// [`#[must_use]`] attribute, but return something not already marked
+    /// must-use, have no mutable arg and mutate no statics.
+    ///
+    /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
+    ///
+    /// **Why is this bad?** Not bad at all, this lint just shows places where
+    /// you could add the attribute.
+    ///
+    /// **Known problems:** The lint only checks the arguments for mutable
+    /// types without looking if they are actually changed. On the other hand,
+    /// it also ignores a broad range of potentially interesting side effects,
+    /// because we cannot decide whether the programmer intends the function to
+    /// be called for the side effect or the result. Expect many false
+    /// positives. At least we don't lint if the result type is unit or already
+    /// `#[must_use]`.
+    ///
+    /// **Examples:**
+    /// ```rust
+    /// // this could be annotated with `#[must_use]`.
+    /// fn id<T>(t: T) -> T { t }
+    /// ```
+    pub MUST_USE_CANDIDATE,
+    pedantic,
+    "function or method that could take a `#[must_use]` attribute"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for public functions that return a `Result`
+    /// with an `Err` type of `()`. It suggests using a custom type that
+    /// implements `std::error::Error`.
+    ///
+    /// **Why is this bad?** Unit does not implement `Error` and carries no
+    /// further information about what went wrong.
+    ///
+    /// **Known problems:** Of course, this lint assumes that `Result` is used
+    /// for a fallible operation (which is after all the intended use). However
+    /// code may opt to (mis)use it as a basic two-variant-enum. In that case,
+    /// the suggestion is misguided, and the code should use a custom enum
+    /// instead.
+    ///
+    /// **Examples:**
+    /// ```rust
+    /// pub fn read_u8() -> Result<u8, ()> { Err(()) }
+    /// ```
+    /// should become
+    /// ```rust,should_panic
+    /// use std::fmt;
+    ///
+    /// #[derive(Debug)]
+    /// pub struct EndOfStream;
+    ///
+    /// impl fmt::Display for EndOfStream {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         write!(f, "End of Stream")
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for EndOfStream { }
+    ///
+    /// pub fn read_u8() -> Result<u8, EndOfStream> { Err(EndOfStream) }
+    ///# fn main() {
+    ///#     read_u8().unwrap();
+    ///# }
+    /// ```
+    ///
+    /// Note that there are crates that simplify creating the error type, e.g.
+    /// [`thiserror`](https://docs.rs/thiserror).
+    pub RESULT_UNIT_ERR,
+    style,
+    "public function returning `Result` with an `Err` type of `()`"
+}
+
+#[derive(Copy, Clone)]
+pub struct Functions {
+    too_many_arguments_threshold: u64,
+    too_many_lines_threshold: u64,
+}
+
+impl Functions {
+    pub fn new(too_many_arguments_threshold: u64, too_many_lines_threshold: u64) -> Self {
+        Self {
+            too_many_arguments_threshold,
+            too_many_lines_threshold,
+        }
+    }
+}
+
+impl_lint_pass!(Functions => [
+    TOO_MANY_ARGUMENTS,
+    TOO_MANY_LINES,
+    NOT_UNSAFE_PTR_ARG_DEREF,
+    MUST_USE_UNIT,
+    DOUBLE_MUST_USE,
+    MUST_USE_CANDIDATE,
+    RESULT_UNIT_ERR,
+]);
+
+impl<'tcx> LateLintPass<'tcx> for Functions {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        kind: intravisit::FnKind<'tcx>,
+        decl: &'tcx hir::FnDecl<'_>,
+        body: &'tcx hir::Body<'_>,
+        span: Span,
+        hir_id: hir::HirId,
+    ) {
+        too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
+        too_many_lines::check_fn(cx, span, body, self.too_many_lines_threshold);
+        not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
+        must_use::check_item(cx, item);
+        result_unit_err::check_item(cx, item);
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
+        must_use::check_impl_item(cx, item);
+        result_unit_err::check_impl_item(cx, item);
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
+        too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
+        not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
+        must_use::check_trait_item(cx, item);
+        result_unit_err::check_trait_item(cx, item);
+    }
+}
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
new file mode 100644
index 00000000000..20288427b4a
--- /dev/null
+++ b/clippy_lints/src/functions/must_use.rs
@@ -0,0 +1,272 @@
+use rustc_ast::ast::Attribute;
+use rustc_errors::Applicability;
+use rustc_hir::def_id::DefIdSet;
+use rustc_hir::{self as hir, def::Res, intravisit, QPath};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::{
+    hir::map::Map,
+    lint::in_external_macro,
+    ty::{self, Ty},
+};
+use rustc_span::{sym, Span};
+
+use clippy_utils::attrs::is_proc_macro;
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::is_must_use_ty;
+use clippy_utils::{match_def_path, must_use_attr, return_ty, trait_ref_of_method};
+
+use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
+
+pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
+    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attr = must_use_attr(attrs);
+    if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind {
+        let is_public = cx.access_levels.is_exported(item.hir_id());
+        let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+        if let Some(attr) = attr {
+            check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+            return;
+        } else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
+            check_must_use_candidate(
+                cx,
+                sig.decl,
+                cx.tcx.hir().body(*body_id),
+                item.span,
+                item.hir_id(),
+                item.span.with_hi(sig.decl.output.span().hi()),
+                "this function could have a `#[must_use]` attribute",
+            );
+        }
+    }
+}
+
+pub(super) fn check_impl_item(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
+    if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
+        let is_public = cx.access_levels.is_exported(item.hir_id());
+        let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attr = must_use_attr(attrs);
+        if let Some(attr) = attr {
+            check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+        } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.hir_id()).is_none() {
+            check_must_use_candidate(
+                cx,
+                sig.decl,
+                cx.tcx.hir().body(*body_id),
+                item.span,
+                item.hir_id(),
+                item.span.with_hi(sig.decl.output.span().hi()),
+                "this method could have a `#[must_use]` attribute",
+            );
+        }
+    }
+}
+
+pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
+    if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
+        let is_public = cx.access_levels.is_exported(item.hir_id());
+        let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+
+        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attr = must_use_attr(attrs);
+        if let Some(attr) = attr {
+            check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+        } else if let hir::TraitFn::Provided(eid) = *eid {
+            let body = cx.tcx.hir().body(eid);
+            if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
+                check_must_use_candidate(
+                    cx,
+                    sig.decl,
+                    body,
+                    item.span,
+                    item.hir_id(),
+                    item.span.with_hi(sig.decl.output.span().hi()),
+                    "this method could have a `#[must_use]` attribute",
+                );
+            }
+        }
+    }
+}
+
+fn check_needless_must_use(
+    cx: &LateContext<'_>,
+    decl: &hir::FnDecl<'_>,
+    item_id: hir::HirId,
+    item_span: Span,
+    fn_header_span: Span,
+    attr: &Attribute,
+) {
+    if in_external_macro(cx.sess(), item_span) {
+        return;
+    }
+    if returns_unit(decl) {
+        span_lint_and_then(
+            cx,
+            MUST_USE_UNIT,
+            fn_header_span,
+            "this unit-returning function has a `#[must_use]` attribute",
+            |diag| {
+                diag.span_suggestion(
+                    attr.span,
+                    "remove the attribute",
+                    "".into(),
+                    Applicability::MachineApplicable,
+                );
+            },
+        );
+    } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+        span_lint_and_help(
+            cx,
+            DOUBLE_MUST_USE,
+            fn_header_span,
+            "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`",
+            None,
+            "either add some descriptive text or remove the attribute",
+        );
+    }
+}
+
+fn check_must_use_candidate<'tcx>(
+    cx: &LateContext<'tcx>,
+    decl: &'tcx hir::FnDecl<'_>,
+    body: &'tcx hir::Body<'_>,
+    item_span: Span,
+    item_id: hir::HirId,
+    fn_span: Span,
+    msg: &str,
+) {
+    if has_mutable_arg(cx, body)
+        || mutates_static(cx, body)
+        || in_external_macro(cx.sess(), item_span)
+        || returns_unit(decl)
+        || !cx.access_levels.is_exported(item_id)
+        || is_must_use_ty(cx, return_ty(cx, item_id))
+    {
+        return;
+    }
+    span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
+        if let Some(snippet) = snippet_opt(cx, fn_span) {
+            diag.span_suggestion(
+                fn_span,
+                "add the attribute",
+                format!("#[must_use] {}", snippet),
+                Applicability::MachineApplicable,
+            );
+        }
+    });
+}
+
+fn returns_unit(decl: &hir::FnDecl<'_>) -> bool {
+    match decl.output {
+        hir::FnRetTy::DefaultReturn(_) => true,
+        hir::FnRetTy::Return(ty) => match ty.kind {
+            hir::TyKind::Tup(tys) => tys.is_empty(),
+            hir::TyKind::Never => true,
+            _ => false,
+        },
+    }
+}
+
+fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool {
+    let mut tys = DefIdSet::default();
+    body.params.iter().any(|param| is_mutable_pat(cx, param.pat, &mut tys))
+}
+
+fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) -> bool {
+    if let hir::PatKind::Wild = pat.kind {
+        return false; // ignore `_` patterns
+    }
+    if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
+        is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys)
+    } else {
+        false
+    }
+}
+
+static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]];
+
+fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool {
+    match *ty.kind() {
+        // primitive types are never mutable
+        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
+        ty::Adt(adt, substs) => {
+            tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
+                || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path))
+                    && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
+        },
+        ty::Tuple(substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)),
+        ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys),
+        ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => {
+            mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys)
+        },
+        // calling something constitutes a side effect, so return true on all callables
+        // also never calls need not be used, so return true for them, too
+        _ => true,
+    }
+}
+
+struct StaticMutVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    mutates_static: bool,
+}
+
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+        use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall};
+
+        if self.mutates_static {
+            return;
+        }
+        match expr.kind {
+            Call(_, args) | MethodCall(_, _, args, _) => {
+                let mut tys = DefIdSet::default();
+                for arg in args {
+                    if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                        && is_mutable_ty(
+                            self.cx,
+                            self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
+                            arg.span,
+                            &mut tys,
+                        )
+                        && is_mutated_static(arg)
+                    {
+                        self.mutates_static = true;
+                        return;
+                    }
+                    tys.clear();
+                }
+            },
+            Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
+                self.mutates_static |= is_mutated_static(target)
+            },
+            _ => {},
+        }
+    }
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::None
+    }
+}
+
+fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
+    use hir::ExprKind::{Field, Index, Path};
+
+    match e.kind {
+        Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
+        Path(_) => true,
+        Field(inner, _) | Index(inner, _) => is_mutated_static(inner),
+        _ => false,
+    }
+}
+
+fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
+    let mut v = StaticMutVisitor {
+        cx,
+        mutates_static: false,
+    };
+    intravisit::walk_expr(&mut v, &body.value);
+    v.mutates_static
+}
diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
new file mode 100644
index 00000000000..b8ea6990866
--- /dev/null
+++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -0,0 +1,124 @@
+use rustc_hir::{self as hir, intravisit, HirIdSet};
+use rustc_lint::LateContext;
+use rustc_middle::{hir::map::Map, ty};
+
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::type_is_unsafe_function;
+use clippy_utils::{iter_input_pats, path_to_local};
+
+use super::NOT_UNSAFE_PTR_ARG_DEREF;
+
+pub(super) fn check_fn(
+    cx: &LateContext<'tcx>,
+    kind: intravisit::FnKind<'tcx>,
+    decl: &'tcx hir::FnDecl<'tcx>,
+    body: &'tcx hir::Body<'tcx>,
+    hir_id: hir::HirId,
+) {
+    let unsafety = match kind {
+        intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
+        intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
+        intravisit::FnKind::Closure => return,
+    };
+
+    check_raw_ptr(cx, unsafety, decl, body, hir_id);
+}
+
+pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
+    if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
+        let body = cx.tcx.hir().body(eid);
+        check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.hir_id());
+    }
+}
+
+fn check_raw_ptr(
+    cx: &LateContext<'tcx>,
+    unsafety: hir::Unsafety,
+    decl: &'tcx hir::FnDecl<'tcx>,
+    body: &'tcx hir::Body<'tcx>,
+    hir_id: hir::HirId,
+) {
+    let expr = &body.value;
+    if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
+        let raw_ptrs = iter_input_pats(decl, body)
+            .zip(decl.inputs.iter())
+            .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
+            .collect::<HirIdSet>();
+
+        if !raw_ptrs.is_empty() {
+            let typeck_results = cx.tcx.typeck_body(body.id());
+            let mut v = DerefVisitor {
+                cx,
+                ptrs: raw_ptrs,
+                typeck_results,
+            };
+
+            intravisit::walk_expr(&mut v, expr);
+        }
+    }
+}
+
+fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
+    if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
+        Some(id)
+    } else {
+        None
+    }
+}
+
+struct DerefVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    ptrs: HirIdSet,
+    typeck_results: &'a ty::TypeckResults<'tcx>,
+}
+
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+        match expr.kind {
+            hir::ExprKind::Call(f, args) => {
+                let ty = self.typeck_results.expr_ty(f);
+
+                if type_is_unsafe_function(self.cx, ty) {
+                    for arg in args {
+                        self.check_arg(arg);
+                    }
+                }
+            },
+            hir::ExprKind::MethodCall(_, _, args, _) => {
+                let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
+                let base_type = self.cx.tcx.type_of(def_id);
+
+                if type_is_unsafe_function(self.cx, base_type) {
+                    for arg in args {
+                        self.check_arg(arg);
+                    }
+                }
+            },
+            hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => self.check_arg(ptr),
+            _ => (),
+        }
+
+        intravisit::walk_expr(self, expr);
+    }
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::None
+    }
+}
+
+impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
+    fn check_arg(&self, ptr: &hir::Expr<'_>) {
+        if let Some(id) = path_to_local(ptr) {
+            if self.ptrs.contains(&id) {
+                span_lint(
+                    self.cx,
+                    NOT_UNSAFE_PTR_ARG_DEREF,
+                    ptr.span,
+                    "this public function dereferences a raw pointer but is not marked `unsafe`",
+                );
+            }
+        }
+    }
+}
diff --git a/clippy_lints/src/functions/result_unit_err.rs b/clippy_lints/src/functions/result_unit_err.rs
new file mode 100644
index 00000000000..c073f312d38
--- /dev/null
+++ b/clippy_lints/src/functions/result_unit_err.rs
@@ -0,0 +1,66 @@
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty;
+use rustc_span::{sym, Span};
+use rustc_typeck::hir_ty_to_ty;
+
+use if_chain::if_chain;
+
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::trait_ref_of_method;
+use clippy_utils::ty::is_type_diagnostic_item;
+
+use super::RESULT_UNIT_ERR;
+
+pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
+    if let hir::ItemKind::Fn(ref sig, ref _generics, _) = item.kind {
+        let is_public = cx.access_levels.is_exported(item.hir_id());
+        let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+        if is_public {
+            check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
+        }
+    }
+}
+
+pub(super) fn check_impl_item(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
+    if let hir::ImplItemKind::Fn(ref sig, _) = item.kind {
+        let is_public = cx.access_levels.is_exported(item.hir_id());
+        let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+        if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() {
+            check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
+        }
+    }
+}
+
+pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
+    if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
+        let is_public = cx.access_levels.is_exported(item.hir_id());
+        let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+        if is_public {
+            check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
+        }
+    }
+}
+
+fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) {
+    if_chain! {
+        if !in_external_macro(cx.sess(), item_span);
+        if let hir::FnRetTy::Return(ty) = decl.output;
+        let ty = hir_ty_to_ty(cx.tcx, ty);
+        if is_type_diagnostic_item(cx, ty, sym::result_type);
+        if let ty::Adt(_, substs) = ty.kind();
+        let err_ty = substs.type_at(1);
+        if err_ty.is_unit();
+        then {
+            span_lint_and_help(
+                cx,
+                RESULT_UNIT_ERR,
+                fn_header_span,
+                "this returns a `Result<_, ()>`",
+                None,
+                "use a custom `Error` type instead",
+            );
+        }
+    }
+}
diff --git a/clippy_lints/src/functions/too_many_arguments.rs b/clippy_lints/src/functions/too_many_arguments.rs
new file mode 100644
index 00000000000..63a14d8d4cd
--- /dev/null
+++ b/clippy_lints/src/functions/too_many_arguments.rs
@@ -0,0 +1,73 @@
+use rustc_hir::{self as hir, intravisit};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
+
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_trait_impl_item;
+
+use super::TOO_MANY_ARGUMENTS;
+
+pub(super) fn check_fn(
+    cx: &LateContext<'tcx>,
+    kind: intravisit::FnKind<'tcx>,
+    decl: &'tcx hir::FnDecl<'_>,
+    span: Span,
+    hir_id: hir::HirId,
+    too_many_arguments_threshold: u64,
+) {
+    // don't warn for implementations, it's not their fault
+    if !is_trait_impl_item(cx, hir_id) {
+        // don't lint extern functions decls, it's not their fault either
+        match kind {
+            intravisit::FnKind::Method(
+                _,
+                &hir::FnSig {
+                    header: hir::FnHeader { abi: Abi::Rust, .. },
+                    ..
+                },
+                _,
+            )
+            | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => check_arg_number(
+                cx,
+                decl,
+                span.with_hi(decl.output.span().hi()),
+                too_many_arguments_threshold,
+            ),
+            _ => {},
+        }
+    }
+}
+
+pub(super) fn check_trait_item(
+    cx: &LateContext<'tcx>,
+    item: &'tcx hir::TraitItem<'_>,
+    too_many_arguments_threshold: u64,
+) {
+    if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
+        // don't lint extern functions decls, it's not their fault
+        if sig.header.abi == Abi::Rust {
+            check_arg_number(
+                cx,
+                sig.decl,
+                item.span.with_hi(sig.decl.output.span().hi()),
+                too_many_arguments_threshold,
+            );
+        }
+    }
+}
+
+fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span, too_many_arguments_threshold: u64) {
+    let args = decl.inputs.len() as u64;
+    if args > too_many_arguments_threshold {
+        span_lint(
+            cx,
+            TOO_MANY_ARGUMENTS,
+            fn_span,
+            &format!(
+                "this function has too many arguments ({}/{})",
+                args, too_many_arguments_threshold
+            ),
+        );
+    }
+}
diff --git a/clippy_lints/src/functions/too_many_lines.rs b/clippy_lints/src/functions/too_many_lines.rs
new file mode 100644
index 00000000000..aa5494d5a7d
--- /dev/null
+++ b/clippy_lints/src/functions/too_many_lines.rs
@@ -0,0 +1,68 @@
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_span::Span;
+
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::source::snippet;
+
+use super::TOO_MANY_LINES;
+
+pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>, too_many_lines_threshold: u64) {
+    if in_external_macro(cx.sess(), span) {
+        return;
+    }
+
+    let code_snippet = snippet(cx, body.value.span, "..");
+    let mut line_count: u64 = 0;
+    let mut in_comment = false;
+    let mut code_in_line;
+
+    // Skip the surrounding function decl.
+    let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1);
+    let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len());
+    let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines();
+
+    for mut line in function_lines {
+        code_in_line = false;
+        loop {
+            line = line.trim_start();
+            if line.is_empty() {
+                break;
+            }
+            if in_comment {
+                if let Some(i) = line.find("*/") {
+                    line = &line[i + 2..];
+                    in_comment = false;
+                    continue;
+                }
+            } else {
+                let multi_idx = line.find("/*").unwrap_or_else(|| line.len());
+                let single_idx = line.find("//").unwrap_or_else(|| line.len());
+                code_in_line |= multi_idx > 0 && single_idx > 0;
+                // Implies multi_idx is below line.len()
+                if multi_idx < single_idx {
+                    line = &line[multi_idx + 2..];
+                    in_comment = true;
+                    continue;
+                }
+            }
+            break;
+        }
+        if code_in_line {
+            line_count += 1;
+        }
+    }
+
+    if line_count > too_many_lines_threshold {
+        span_lint(
+            cx,
+            TOO_MANY_LINES,
+            span,
+            &format!(
+                "this function has too many lines ({}/{})",
+                line_count, too_many_lines_threshold
+            ),
+        )
+    }
+}
diff --git a/clippy_lints/src/get_last_with_len.rs b/clippy_lints/src/get_last_with_len.rs
index cbcef567c53..3707e792177 100644
--- a/clippy_lints/src/get_last_with_len.rs
+++ b/clippy_lints/src/get_last_with_len.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for GetLastWithLen {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // Is a method call
-            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
 
             // Method name is "get"
             if path.ident.name == sym!(get);
diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs
index 8bed5e1bf64..366b3b46a8a 100644
--- a/clippy_lints/src/identity_op.rs
+++ b/clippy_lints/src/identity_op.rs
@@ -35,7 +35,7 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp {
         if e.span.from_expansion() {
             return;
         }
-        if let ExprKind::Binary(cmp, ref left, ref right) = e.kind {
+        if let ExprKind::Binary(cmp, left, right) = e.kind {
             if is_allowed(cx, cmp, left, right) {
                 return;
             }
diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs
index 4aab43256bf..f661f7ede82 100644
--- a/clippy_lints/src/if_let_mutex.rs
+++ b/clippy_lints/src/if_let_mutex.rs
@@ -55,8 +55,8 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
             cx,
         };
         if let ExprKind::Match(
-            ref op,
-            ref arms,
+            op,
+            arms,
             MatchSource::IfLetDesugar {
                 contains_else_clause: true,
             },
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
         {
             op_visit.visit_expr(op);
             if op_visit.mutex_lock_called {
-                for arm in *arms {
+                for arm in arms {
                     arm_visit.visit_arm(arm);
                 }
 
@@ -94,13 +94,10 @@ impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> {
     type Map = Map<'tcx>;
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if let Some(mutex) = is_mutex_lock_call(self.cx, expr);
-            then {
-                self.found_mutex = Some(mutex);
-                self.mutex_lock_called = true;
-                return;
-            }
+        if let Some(mutex) = is_mutex_lock_call(self.cx, expr) {
+            self.found_mutex = Some(mutex);
+            self.mutex_lock_called = true;
+            return;
         }
         visit::walk_expr(self, expr);
     }
@@ -121,13 +118,10 @@ impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> {
     type Map = Map<'tcx>;
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if_chain! {
-            if let Some(mutex) = is_mutex_lock_call(self.cx, expr);
-            then {
-                self.found_mutex = Some(mutex);
-                self.mutex_lock_called = true;
-                return;
-            }
+        if let Some(mutex) = is_mutex_lock_call(self.cx, expr) {
+            self.found_mutex = Some(mutex);
+            self.mutex_lock_called = true;
+            return;
         }
         visit::walk_expr(self, expr);
     }
diff --git a/clippy_lints/src/if_let_some_result.rs b/clippy_lints/src/if_let_some_result.rs
index 6e9280c8c7e..611da3744ee 100644
--- a/clippy_lints/src/if_let_some_result.rs
+++ b/clippy_lints/src/if_let_some_result.rs
@@ -44,9 +44,9 @@ declare_lint_pass!(OkIfLet => [IF_LET_SOME_RESULT]);
 impl<'tcx> LateLintPass<'tcx> for OkIfLet {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! { //begin checking variables
-            if let ExprKind::Match(ref op, ref body, MatchSource::IfLetDesugar { .. }) = expr.kind; //test if expr is if let
-            if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
-            if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _)  = body[0].pat.kind; //get operation
+            if let ExprKind::Match(op, body, MatchSource::IfLetDesugar { .. }) = expr.kind; //test if expr is if let
+            if let ExprKind::MethodCall(_, ok_span, result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
+            if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = body[0].pat.kind; //get operation
             if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
             if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&result_types[0]), sym::result_type);
             if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";
diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index 0b5bf060d4c..ee16519692f 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/clippy_lints/src/if_then_some_else_none.rs
@@ -72,15 +72,15 @@ impl LateLintPass<'_> for IfThenSomeElseNone {
         }
 
         if_chain! {
-            if let ExprKind::If(ref cond, ref then, Some(ref els)) = expr.kind;
-            if let ExprKind::Block(ref then_block, _) = then.kind;
-            if let Some(ref then_expr) = then_block.expr;
-            if let ExprKind::Call(ref then_call, [then_arg]) = then_expr.kind;
+            if let ExprKind::If(cond, then, Some(els)) = expr.kind;
+            if let ExprKind::Block(then_block, _) = then.kind;
+            if let Some(then_expr) = then_block.expr;
+            if let ExprKind::Call(then_call, [then_arg]) = then_expr.kind;
             if let ExprKind::Path(ref then_call_qpath) = then_call.kind;
             if match_qpath(then_call_qpath, &clippy_utils::paths::OPTION_SOME);
-            if let ExprKind::Block(ref els_block, _) = els.kind;
+            if let ExprKind::Block(els_block, _) = els.kind;
             if els_block.stmts.is_empty();
-            if let Some(ref els_expr) = els_block.expr;
+            if let Some(els_expr) = els_block.expr;
             if let ExprKind::Path(ref els_call_qpath) = els_expr.kind;
             if match_qpath(els_call_qpath, &clippy_utils::paths::OPTION_NONE);
             then {
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
new file mode 100644
index 00000000000..77a38544edc
--- /dev/null
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -0,0 +1,377 @@
+#![allow(rustc::default_hash_types)]
+
+use std::borrow::Cow;
+use std::collections::BTreeMap;
+
+use rustc_errors::DiagnosticBuilder;
+use rustc_hir as hir;
+use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, NestedVisitorMap, Visitor};
+use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::map::Map;
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::{Ty, TyS, TypeckResults};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Span;
+use rustc_span::symbol::sym;
+use rustc_typeck::hir_ty_to_ty;
+
+use if_chain::if_chain;
+
+use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::paths;
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{differing_macro_contexts, match_path};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for public `impl` or `fn` missing generalization
+    /// over different hashers and implicitly defaulting to the default hashing
+    /// algorithm (`SipHash`).
+    ///
+    /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be
+    /// used with them.
+    ///
+    /// **Known problems:** Suggestions for replacing constructors can contain
+    /// false-positives. Also applying suggestions can require modification of other
+    /// pieces of code, possibly including external crates.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// # use std::collections::HashMap;
+    /// # use std::hash::{Hash, BuildHasher};
+    /// # trait Serialize {};
+    /// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { }
+    ///
+    /// pub fn foo(map: &mut HashMap<i32, i32>) { }
+    /// ```
+    /// could be rewritten as
+    /// ```rust
+    /// # use std::collections::HashMap;
+    /// # use std::hash::{Hash, BuildHasher};
+    /// # trait Serialize {};
+    /// impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { }
+    ///
+    /// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { }
+    /// ```
+    pub IMPLICIT_HASHER,
+    pedantic,
+    "missing generalization over different hashers"
+}
+
+declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]);
+
+impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
+    #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)]
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        use rustc_span::BytePos;
+
+        fn suggestion<'tcx>(
+            cx: &LateContext<'tcx>,
+            diag: &mut DiagnosticBuilder<'_>,
+            generics_span: Span,
+            generics_suggestion_span: Span,
+            target: &ImplicitHasherType<'_>,
+            vis: ImplicitHasherConstructorVisitor<'_, '_, '_>,
+        ) {
+            let generics_snip = snippet(cx, generics_span, "");
+            // trim `<` `>`
+            let generics_snip = if generics_snip.is_empty() {
+                ""
+            } else {
+                &generics_snip[1..generics_snip.len() - 1]
+            };
+
+            multispan_sugg(
+                diag,
+                "consider adding a type parameter",
+                vec![
+                    (
+                        generics_suggestion_span,
+                        format!(
+                            "<{}{}S: ::std::hash::BuildHasher{}>",
+                            generics_snip,
+                            if generics_snip.is_empty() { "" } else { ", " },
+                            if vis.suggestions.is_empty() {
+                                ""
+                            } else {
+                                // request users to add `Default` bound so that generic constructors can be used
+                                " + Default"
+                            },
+                        ),
+                    ),
+                    (
+                        target.span(),
+                        format!("{}<{}, S>", target.type_name(), target.type_arguments(),),
+                    ),
+                ],
+            );
+
+            if !vis.suggestions.is_empty() {
+                multispan_sugg(diag, "...and use generic constructor", vis.suggestions);
+            }
+        }
+
+        if !cx.access_levels.is_exported(item.hir_id()) {
+            return;
+        }
+
+        match item.kind {
+            ItemKind::Impl(ref impl_) => {
+                let mut vis = ImplicitHasherTypeVisitor::new(cx);
+                vis.visit_ty(impl_.self_ty);
+
+                for target in &vis.found {
+                    if differing_macro_contexts(item.span, target.span()) {
+                        return;
+                    }
+
+                    let generics_suggestion_span = impl_.generics.span.substitute_dummy({
+                        let pos = snippet_opt(cx, item.span.until(target.span()))
+                            .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
+                        if let Some(pos) = pos {
+                            Span::new(pos, pos, item.span.data().ctxt)
+                        } else {
+                            return;
+                        }
+                    });
+
+                    let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
+                    for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
+                        ctr_vis.visit_impl_item(item);
+                    }
+
+                    span_lint_and_then(
+                        cx,
+                        IMPLICIT_HASHER,
+                        target.span(),
+                        &format!(
+                            "impl for `{}` should be generalized over different hashers",
+                            target.type_name()
+                        ),
+                        move |diag| {
+                            suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis);
+                        },
+                    );
+                }
+            },
+            ItemKind::Fn(ref sig, ref generics, body_id) => {
+                let body = cx.tcx.hir().body(body_id);
+
+                for ty in sig.decl.inputs {
+                    let mut vis = ImplicitHasherTypeVisitor::new(cx);
+                    vis.visit_ty(ty);
+
+                    for target in &vis.found {
+                        if in_external_macro(cx.sess(), generics.span) {
+                            continue;
+                        }
+                        let generics_suggestion_span = generics.span.substitute_dummy({
+                            let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span))
+                                .and_then(|snip| {
+                                    let i = snip.find("fn")?;
+                                    Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
+                                })
+                                .expect("failed to create span for type parameters");
+                            Span::new(pos, pos, item.span.data().ctxt)
+                        });
+
+                        let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
+                        ctr_vis.visit_body(body);
+
+                        span_lint_and_then(
+                            cx,
+                            IMPLICIT_HASHER,
+                            target.span(),
+                            &format!(
+                                "parameter of type `{}` should be generalized over different hashers",
+                                target.type_name()
+                            ),
+                            move |diag| {
+                                suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis);
+                            },
+                        );
+                    }
+                }
+            },
+            _ => {},
+        }
+    }
+}
+
+enum ImplicitHasherType<'tcx> {
+    HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>),
+    HashSet(Span, Ty<'tcx>, Cow<'static, str>),
+}
+
+impl<'tcx> ImplicitHasherType<'tcx> {
+    /// Checks that `ty` is a target type without a `BuildHasher`.
+    fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> {
+        if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind {
+            let params: Vec<_> = path
+                .segments
+                .last()
+                .as_ref()?
+                .args
+                .as_ref()?
+                .args
+                .iter()
+                .filter_map(|arg| match arg {
+                    GenericArg::Type(ty) => Some(ty),
+                    _ => None,
+                })
+                .collect();
+            let params_len = params.len();
+
+            let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+
+            if is_type_diagnostic_item(cx, ty, sym::hashmap_type) && params_len == 2 {
+                Some(ImplicitHasherType::HashMap(
+                    hir_ty.span,
+                    ty,
+                    snippet(cx, params[0].span, "K"),
+                    snippet(cx, params[1].span, "V"),
+                ))
+            } else if is_type_diagnostic_item(cx, ty, sym::hashset_type) && params_len == 1 {
+                Some(ImplicitHasherType::HashSet(
+                    hir_ty.span,
+                    ty,
+                    snippet(cx, params[0].span, "T"),
+                ))
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    fn type_name(&self) -> &'static str {
+        match *self {
+            ImplicitHasherType::HashMap(..) => "HashMap",
+            ImplicitHasherType::HashSet(..) => "HashSet",
+        }
+    }
+
+    fn type_arguments(&self) -> String {
+        match *self {
+            ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v),
+            ImplicitHasherType::HashSet(.., ref t) => format!("{}", t),
+        }
+    }
+
+    fn ty(&self) -> Ty<'tcx> {
+        match *self {
+            ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty,
+        }
+    }
+
+    fn span(&self) -> Span {
+        match *self {
+            ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span,
+        }
+    }
+}
+
+struct ImplicitHasherTypeVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    found: Vec<ImplicitHasherType<'tcx>>,
+}
+
+impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
+    fn new(cx: &'a LateContext<'tcx>) -> Self {
+        Self { cx, found: vec![] }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) {
+        if let Some(target) = ImplicitHasherType::new(self.cx, t) {
+            self.found.push(target);
+        }
+
+        walk_ty(self, t);
+    }
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+}
+
+/// Looks for default-hasher-dependent constructors like `HashMap::new`.
+struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>,
+    target: &'b ImplicitHasherType<'tcx>,
+    suggestions: BTreeMap<Span, String>,
+}
+
+impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
+    fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self {
+        Self {
+            cx,
+            maybe_typeck_results: cx.maybe_typeck_results(),
+            target,
+            suggestions: BTreeMap::new(),
+        }
+    }
+}
+
+impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn visit_body(&mut self, body: &'tcx Body<'_>) {
+        let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id()));
+        walk_body(self, body);
+        self.maybe_typeck_results = old_maybe_typeck_results;
+    }
+
+    fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
+        if_chain! {
+            if let ExprKind::Call(fun, args) = e.kind;
+            if let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind;
+            if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind;
+            then {
+                if !TyS::same_type(self.target.ty(), self.maybe_typeck_results.unwrap().expr_ty(e)) {
+                    return;
+                }
+
+                if match_path(ty_path, &paths::HASHMAP) {
+                    if method.ident.name == sym::new {
+                        self.suggestions
+                            .insert(e.span, "HashMap::default()".to_string());
+                    } else if method.ident.name == sym!(with_capacity) {
+                        self.suggestions.insert(
+                            e.span,
+                            format!(
+                                "HashMap::with_capacity_and_hasher({}, Default::default())",
+                                snippet(self.cx, args[0].span, "capacity"),
+                            ),
+                        );
+                    }
+                } else if match_path(ty_path, &paths::HASHSET) {
+                    if method.ident.name == sym::new {
+                        self.suggestions
+                            .insert(e.span, "HashSet::default()".to_string());
+                    } else if method.ident.name == sym!(with_capacity) {
+                        self.suggestions.insert(
+                            e.span,
+                            format!(
+                                "HashSet::with_capacity_and_hasher({}, Default::default())",
+                                snippet(self.cx, args[0].span, "capacity"),
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+
+        walk_expr(self, e);
+    }
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    }
+}
diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs
index 6863645a92d..6b379b0d59b 100644
--- a/clippy_lints/src/implicit_return.rs
+++ b/clippy_lints/src/implicit_return.rs
@@ -100,10 +100,10 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
             if check_all_arms {
                 for arm in arms {
-                    expr_match(cx, &arm.body);
+                    expr_match(cx, arm.body);
                 }
             } else {
-                expr_match(cx, &arms.first().expect("`if let` doesn't have a single arm").body);
+                expr_match(cx, arms.first().expect("`if let` doesn't have a single arm").body);
             }
         },
         // skip if it already has a return statement
diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 5207c628987..cba3183e869 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -46,21 +46,21 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
             if let ExprKind::If(cond, then, None) = &expr.kind;
 
             // Check if the conditional expression is a binary operation
-            if let ExprKind::Binary(ref cond_op, ref cond_left, ref cond_right) = cond.kind;
+            if let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind;
 
             // Ensure that the binary operator is >, != and <
             if BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node;
 
             // Check if the true condition block has only one statement
-            if let ExprKind::Block(ref block, _) = then.kind;
+            if let ExprKind::Block(block, _) = then.kind;
             if block.stmts.len() == 1 && block.expr.is_none();
 
             // Check if assign operation is done
-            if let StmtKind::Semi(ref e) = block.stmts[0].kind;
+            if let StmtKind::Semi(e) = block.stmts[0].kind;
             if let Some(target) = subtracts_one(cx, e);
 
             // Extracting out the variable name
-            if let ExprKind::Path(QPath::Resolved(_, ref ares_path)) = target.kind;
+            if let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind;
 
             then {
                 // Handle symmetric conditions in the if statement
@@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
                             print_lint_and_sugg(cx, &var_name, expr);
                         };
                     },
-                    ExprKind::Call(ref func, _) => {
+                    ExprKind::Call(func, _) => {
                         if let ExprKind::Path(ref cond_num_path) = func.kind {
                             if INT_TYPES.iter().any(|int_type| match_qpath(cond_num_path, &[int_type, "min_value"])) {
                                 print_lint_and_sugg(cx, &var_name, expr);
@@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
 
 fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &Expr<'a>) -> Option<&'a Expr<'a>> {
     match expr.kind {
-        ExprKind::AssignOp(ref op1, ref target, ref value) => {
+        ExprKind::AssignOp(ref op1, target, value) => {
             if_chain! {
                 if BinOpKind::Sub == op1.node;
                 // Check if literal being subtracted is one
@@ -133,9 +133,9 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &Expr<'a>) -> Option<&'a Expr<'
                 }
             }
         },
-        ExprKind::Assign(ref target, ref value, _) => {
+        ExprKind::Assign(target, value, _) => {
             if_chain! {
-                if let ExprKind::Binary(ref op1, ref left1, ref right1) = value.kind;
+                if let ExprKind::Binary(ref op1, left1, right1) = value.kind;
                 if BinOpKind::Sub == op1.node;
 
                 if SpanlessEq::new(cx).eq_expr(left1, target);
diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs
index 94d39019608..1c54599abc4 100644
--- a/clippy_lints/src/indexing_slicing.rs
+++ b/clippy_lints/src/indexing_slicing.rs
@@ -88,7 +88,7 @@ declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]
 
 impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Index(ref array, ref index) = &expr.kind {
+        if let ExprKind::Index(array, index) = &expr.kind {
             let ty = cx.typeck_results().expr_ty(array).peel_refs();
             if let Some(range) = higher::range(index) {
                 // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs
index fb35bc1e780..bbb4ddc613a 100644
--- a/clippy_lints/src/infinite_iter.rs
+++ b/clippy_lints/src/infinite_iter.rs
@@ -139,7 +139,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
 
 fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(ref method, _, ref args, _) => {
+        ExprKind::MethodCall(method, _, args, _) => {
             for &(name, len, heuristic, cap) in &HEURISTICS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return (match heuristic {
@@ -159,9 +159,9 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
             }
             Finite
         },
-        ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
-        ExprKind::Box(ref e) | ExprKind::AddrOf(BorrowKind::Ref, _, ref e) => is_infinite(cx, e),
-        ExprKind::Call(ref path, _) => {
+        ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
+        ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
+        ExprKind::Call(path, _) => {
             if let ExprKind::Path(ref qpath) = path.kind {
                 match_qpath(qpath, &paths::REPEAT).into()
             } else {
@@ -215,7 +215,7 @@ const INFINITE_COLLECTORS: [&[&str]; 8] = [
 
 fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(ref method, _, ref args, _) => {
+        ExprKind::MethodCall(method, _, args, _) => {
             for &(name, len) in &COMPLETING_METHODS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return is_infinite(cx, &args[0]);
@@ -240,7 +240,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                 }
             }
         },
-        ExprKind::Binary(op, ref l, ref r) => {
+        ExprKind::Binary(op, l, r) => {
             if op.node.is_comparison() {
                 return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite);
             }
diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs
index 5b2e70e3ce9..c31013e49be 100644
--- a/clippy_lints/src/inherent_impl.rs
+++ b/clippy_lints/src/inherent_impl.rs
@@ -2,7 +2,7 @@
 
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::in_macro;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{def_id, Crate, Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -43,7 +43,7 @@ declare_clippy_lint! {
 #[allow(clippy::module_name_repetitions)]
 #[derive(Default)]
 pub struct MultipleInherentImpl {
-    impls: FxHashMap<def_id::DefId, Span>,
+    impls: DefIdMap<Span>,
 }
 
 impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]);
diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs
new file mode 100644
index 00000000000..c67c02eefa5
--- /dev/null
+++ b/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -0,0 +1,221 @@
+use std::cmp::Ordering;
+
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, IntTy, UintTy};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+use rustc_target::abi::LayoutOf;
+
+use crate::consts::{constant, Constant};
+
+use clippy_utils::comparisons::Rel;
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::source::snippet;
+use clippy_utils::{comparisons, sext};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for comparisons where the relation is always either
+    /// true or false, but where one side has been upcast so that the comparison is
+    /// necessary. Only integer types are checked.
+    ///
+    /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300`
+    /// will mistakenly imply that it is possible for `x` to be outside the range of
+    /// `u8`.
+    ///
+    /// **Known problems:**
+    /// https://github.com/rust-lang/rust-clippy/issues/886
+    ///
+    /// **Example:**
+    /// ```rust
+    /// let x: u8 = 1;
+    /// (x as u32) > 300;
+    /// ```
+    pub INVALID_UPCAST_COMPARISONS,
+    pedantic,
+    "a comparison involving an upcast which is always true or false"
+}
+
+declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
+
+#[derive(Copy, Clone, Debug, Eq)]
+enum FullInt {
+    S(i128),
+    U(u128),
+}
+
+impl FullInt {
+    #[allow(clippy::cast_sign_loss)]
+    #[must_use]
+    fn cmp_s_u(s: i128, u: u128) -> Ordering {
+        if s < 0 {
+            Ordering::Less
+        } else if u > (i128::MAX as u128) {
+            Ordering::Greater
+        } else {
+            (s as u128).cmp(&u)
+        }
+    }
+}
+
+impl PartialEq for FullInt {
+    #[must_use]
+    fn eq(&self, other: &Self) -> bool {
+        self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
+    }
+}
+
+impl PartialOrd for FullInt {
+    #[must_use]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(match (self, other) {
+            (&Self::S(s), &Self::S(o)) => s.cmp(&o),
+            (&Self::U(s), &Self::U(o)) => s.cmp(&o),
+            (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
+            (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
+        })
+    }
+}
+
+impl Ord for FullInt {
+    #[must_use]
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.partial_cmp(other)
+            .expect("`partial_cmp` for FullInt can never return `None`")
+    }
+}
+
+fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
+    if let ExprKind::Cast(cast_exp, _) = expr.kind {
+        let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
+        let cast_ty = cx.typeck_results().expr_ty(expr);
+        // if it's a cast from i32 to u32 wrapping will invalidate all these checks
+        if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) {
+            return None;
+        }
+        match pre_cast_ty.kind() {
+            ty::Int(int_ty) => Some(match int_ty {
+                IntTy::I8 => (FullInt::S(i128::from(i8::MIN)), FullInt::S(i128::from(i8::MAX))),
+                IntTy::I16 => (FullInt::S(i128::from(i16::MIN)), FullInt::S(i128::from(i16::MAX))),
+                IntTy::I32 => (FullInt::S(i128::from(i32::MIN)), FullInt::S(i128::from(i32::MAX))),
+                IntTy::I64 => (FullInt::S(i128::from(i64::MIN)), FullInt::S(i128::from(i64::MAX))),
+                IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)),
+                IntTy::Isize => (FullInt::S(isize::MIN as i128), FullInt::S(isize::MAX as i128)),
+            }),
+            ty::Uint(uint_ty) => Some(match uint_ty {
+                UintTy::U8 => (FullInt::U(u128::from(u8::MIN)), FullInt::U(u128::from(u8::MAX))),
+                UintTy::U16 => (FullInt::U(u128::from(u16::MIN)), FullInt::U(u128::from(u16::MAX))),
+                UintTy::U32 => (FullInt::U(u128::from(u32::MIN)), FullInt::U(u128::from(u32::MAX))),
+                UintTy::U64 => (FullInt::U(u128::from(u64::MIN)), FullInt::U(u128::from(u64::MAX))),
+                UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)),
+                UintTy::Usize => (FullInt::U(usize::MIN as u128), FullInt::U(usize::MAX as u128)),
+            }),
+            _ => None,
+        }
+    } else {
+        None
+    }
+}
+
+fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
+    let val = constant(cx, cx.typeck_results(), expr)?.0;
+    if let Constant::Int(const_int) = val {
+        match *cx.typeck_results().expr_ty(expr).kind() {
+            ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
+            ty::Uint(_) => Some(FullInt::U(const_int)),
+            _ => None,
+        }
+    } else {
+        None
+    }
+}
+
+fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
+    if let ExprKind::Cast(cast_val, _) = expr.kind {
+        span_lint(
+            cx,
+            INVALID_UPCAST_COMPARISONS,
+            span,
+            &format!(
+                "because of the numeric bounds on `{}` prior to casting, this expression is always {}",
+                snippet(cx, cast_val.span, "the expression"),
+                if always { "true" } else { "false" },
+            ),
+        );
+    }
+}
+
+fn upcast_comparison_bounds_err<'tcx>(
+    cx: &LateContext<'tcx>,
+    span: Span,
+    rel: comparisons::Rel,
+    lhs_bounds: Option<(FullInt, FullInt)>,
+    lhs: &'tcx Expr<'_>,
+    rhs: &'tcx Expr<'_>,
+    invert: bool,
+) {
+    if let Some((lb, ub)) = lhs_bounds {
+        if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
+            if rel == Rel::Eq || rel == Rel::Ne {
+                if norm_rhs_val < lb || norm_rhs_val > ub {
+                    err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
+                }
+            } else if match rel {
+                Rel::Lt => {
+                    if invert {
+                        norm_rhs_val < lb
+                    } else {
+                        ub < norm_rhs_val
+                    }
+                },
+                Rel::Le => {
+                    if invert {
+                        norm_rhs_val <= lb
+                    } else {
+                        ub <= norm_rhs_val
+                    }
+                },
+                Rel::Eq | Rel::Ne => unreachable!(),
+            } {
+                err_upcast_comparison(cx, span, lhs, true)
+            } else if match rel {
+                Rel::Lt => {
+                    if invert {
+                        norm_rhs_val >= ub
+                    } else {
+                        lb >= norm_rhs_val
+                    }
+                },
+                Rel::Le => {
+                    if invert {
+                        norm_rhs_val > ub
+                    } else {
+                        lb > norm_rhs_val
+                    }
+                },
+                Rel::Eq | Rel::Ne => unreachable!(),
+            } {
+                err_upcast_comparison(cx, span, lhs, false)
+            }
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if let ExprKind::Binary(ref cmp, lhs, rhs) = expr.kind {
+            let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
+            let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
+                val
+            } else {
+                return;
+            };
+
+            let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs);
+            let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs);
+
+            upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false);
+            upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true);
+        }
+    }
+}
diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs
index 76584dc1822..f166748d86b 100644
--- a/clippy_lints/src/large_enum_variant.rs
+++ b/clippy_lints/src/large_enum_variant.rs
@@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
                             );
                             if variant.fields.len() == 1 {
                                 let span = match def.variants[i].data {
-                                    VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => {
+                                    VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) => {
                                         fields[0].ty.span
                                     },
                                     VariantData::Unit(..) => unreachable!(),
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 717f2ea84f4..bb57adff7be 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -3,16 +3,19 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{get_item_name, get_parent_as_impl, is_allowed};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
+use rustc_hir::def_id::DefIdSet;
 use rustc_hir::{
     def_id::DefId, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, ImplItem, ImplItemKind, ImplicitSelfKind, Item,
     ItemKind, Mutability, Node, TraitItemRef, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, AssocKind, FnSig};
+use rustc_middle::ty::{self, AssocKind, FnSig, Ty, TyS};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::{Span, Spanned, Symbol};
+use rustc_span::{
+    source_map::{Span, Spanned, Symbol},
+    symbol::sym,
+};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for getting the length of something via `.len()`
@@ -118,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             return;
         }
 
-        if let ItemKind::Trait(_, _, _, _, ref trait_items) = item.kind {
+        if let ItemKind::Trait(_, _, _, _, trait_items) = item.kind {
             check_trait_items(cx, item, trait_items);
         }
     }
@@ -137,6 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             if let Some(local_id) = ty_id.as_local();
             let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
             if !is_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id);
+            if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.def_id).skip_binder());
             then {
                 let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
                     Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
@@ -148,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
                     }
                     _ => return,
                 };
-                check_for_is_empty(cx, sig.span, sig.decl.implicit_self, ty_id, name, kind)
+                check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind)
             }
         }
     }
@@ -158,7 +162,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             return;
         }
 
-        if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.kind {
+        if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind {
             match cmp {
                 BinOpKind::Eq => {
                     check_cmp(cx, expr.span, left, right, "", 0); // len == 0
@@ -195,7 +199,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
     }
 
     // fill the set with current and super traits
-    fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_>) {
+    fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) {
         if set.insert(traitt) {
             for supertrait in rustc_trait_selection::traits::supertrait_def_ids(cx.tcx, traitt) {
                 fill_trait_set(supertrait, set, cx);
@@ -204,7 +208,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
     }
 
     if cx.access_levels.is_exported(visited_trait.hir_id()) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
-        let mut current_and_super_traits = FxHashSet::default();
+        let mut current_and_super_traits = DefIdSet::default();
         fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
 
         let is_empty_method_found = current_and_super_traits
@@ -231,10 +235,62 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
     }
 }
 
+#[derive(Debug, Clone, Copy)]
+enum LenOutput<'tcx> {
+    Integral,
+    Option(DefId),
+    Result(DefId, Ty<'tcx>),
+}
+fn parse_len_output(cx: &LateContext<'_>, sig: FnSig<'tcx>) -> Option<LenOutput<'tcx>> {
+    match *sig.output().kind() {
+        ty::Int(_) | ty::Uint(_) => Some(LenOutput::Integral),
+        ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) => {
+            subs.type_at(0).is_integral().then(|| LenOutput::Option(adt.did))
+        },
+        ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::result_type, adt.did) => subs
+            .type_at(0)
+            .is_integral()
+            .then(|| LenOutput::Result(adt.did, subs.type_at(1))),
+        _ => None,
+    }
+}
+
+impl LenOutput<'_> {
+    fn matches_is_empty_output(self, ty: Ty<'_>) -> bool {
+        match (self, ty.kind()) {
+            (_, &ty::Bool) => true,
+            (Self::Option(id), &ty::Adt(adt, subs)) if id == adt.did => subs.type_at(0).is_bool(),
+            (Self::Result(id, err_ty), &ty::Adt(adt, subs)) if id == adt.did => {
+                subs.type_at(0).is_bool() && TyS::same_type(subs.type_at(1), err_ty)
+            },
+            _ => false,
+        }
+    }
+
+    fn expected_sig(self, self_kind: ImplicitSelfKind) -> String {
+        let self_ref = match self_kind {
+            ImplicitSelfKind::ImmRef => "&",
+            ImplicitSelfKind::MutRef => "&mut ",
+            _ => "",
+        };
+        match self {
+            Self::Integral => format!("expected signature: `({}self) -> bool`", self_ref),
+            Self::Option(_) => format!(
+                "expected signature: `({}self) -> bool` or `({}self) -> Option<bool>",
+                self_ref, self_ref
+            ),
+            Self::Result(..) => format!(
+                "expected signature: `({}self) -> bool` or `({}self) -> Result<bool>",
+                self_ref, self_ref
+            ),
+        }
+    }
+}
+
 /// Checks if the given signature matches the expectations for `is_empty`
-fn check_is_empty_sig(cx: &LateContext<'_>, sig: FnSig<'_>, self_kind: ImplicitSelfKind) -> bool {
+fn check_is_empty_sig(sig: FnSig<'_>, self_kind: ImplicitSelfKind, len_output: LenOutput<'_>) -> bool {
     match &**sig.inputs_and_output {
-        [arg, res] if *res == cx.tcx.types.bool => {
+        [arg, res] if len_output.matches_is_empty_output(res) => {
             matches!(
                 (arg.kind(), self_kind),
                 (ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::ImmRef)
@@ -250,6 +306,7 @@ fn check_for_is_empty(
     cx: &LateContext<'_>,
     span: Span,
     self_kind: ImplicitSelfKind,
+    output: LenOutput<'_>,
     impl_ty: DefId,
     item_name: Symbol,
     item_kind: &str,
@@ -289,7 +346,7 @@ fn check_for_is_empty(
         },
         Some(is_empty)
             if !(is_empty.fn_has_self_parameter
-                && check_is_empty_sig(cx, cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind)) =>
+                && check_is_empty_sig(cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind, output)) =>
         {
             (
                 format!(
@@ -309,21 +366,13 @@ fn check_for_is_empty(
             db.span_note(span, "`is_empty` defined here");
         }
         if let Some(self_kind) = self_kind {
-            db.note(&format!(
-                "expected signature: `({}self) -> bool`",
-                match self_kind {
-                    ImplicitSelfKind::ImmRef => "&",
-                    ImplicitSelfKind::MutRef => "&mut ",
-                    _ => "",
-                }
-            ));
+            db.note(&output.expected_sig(self_kind));
         }
     });
 }
 
 fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
-    if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind)
-    {
+    if let (&ExprKind::MethodCall(method_path, _, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
         // check if we are in an is_empty() method
         if let Some(name) = get_item_name(cx, method) {
             if name.as_str() == "is_empty" {
@@ -401,7 +450,7 @@ fn is_empty_string(expr: &Expr<'_>) -> bool {
 }
 
 fn is_empty_array(expr: &Expr<'_>) -> bool {
-    if let ExprKind::Array(ref arr) = expr.kind {
+    if let ExprKind::Array(arr) = expr.kind {
         return arr.is_empty();
     }
     false
@@ -430,17 +479,17 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
             cx.tcx
                 .associated_items(*imp)
                 .in_definition_order()
-                .any(|item| is_is_empty(cx, &item))
+                .any(|item| is_is_empty(cx, item))
         })
     }
 
     let ty = &cx.typeck_results().expr_ty(expr).peel_refs();
     match ty.kind() {
-        ty::Dynamic(ref tt, ..) => tt.principal().map_or(false, |principal| {
+        ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| {
             cx.tcx
                 .associated_items(principal.def_id())
                 .in_definition_order()
-                .any(|item| is_is_empty(cx, &item))
+                .any(|item| is_is_empty(cx, item))
         }),
         ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
         ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs
index 2d7d9c9befb..67eae4d87bb 100644
--- a/clippy_lints/src/let_if_seq.rs
+++ b/clippy_lints/src/let_if_seq.rs
@@ -61,13 +61,13 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
         while let Some(stmt) = it.next() {
             if_chain! {
                 if let Some(expr) = it.peek();
-                if let hir::StmtKind::Local(ref local) = stmt.kind;
+                if let hir::StmtKind::Local(local) = stmt.kind;
                 if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind;
-                if let hir::StmtKind::Expr(ref if_) = expr.kind;
-                if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.kind;
+                if let hir::StmtKind::Expr(if_) = expr.kind;
+                if let hir::ExprKind::If(cond, then, ref else_) = if_.kind;
                 let mut used_visitor = LocalUsedVisitor::new(cx, canonical_id);
                 if !used_visitor.check_expr(cond);
-                if let hir::ExprKind::Block(ref then, _) = then.kind;
+                if let hir::ExprKind::Block(then, _) = then.kind;
                 if let Some(value) = check_assign(cx, canonical_id, &*then);
                 if !used_visitor.check_expr(value);
                 then {
@@ -79,20 +79,20 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
                     );
                     if has_interior_mutability { return; }
 
-                    let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
-                        if let hir::ExprKind::Block(ref else_, _) = else_.kind {
+                    let (default_multi_stmts, default) = if let Some(else_) = *else_ {
+                        if let hir::ExprKind::Block(else_, _) = else_.kind {
                             if let Some(default) = check_assign(cx, canonical_id, else_) {
                                 (else_.stmts.len() > 1, default)
-                            } else if let Some(ref default) = local.init {
-                                (true, &**default)
+                            } else if let Some(default) = local.init {
+                                (true, default)
                             } else {
                                 continue;
                             }
                         } else {
                             continue;
                         }
-                    } else if let Some(ref default) = local.init {
-                        (false, &**default)
+                    } else if let Some(default) = local.init {
+                        (false, default)
                     } else {
                         continue;
                     };
@@ -144,8 +144,8 @@ fn check_assign<'tcx>(
     if_chain! {
         if block.expr.is_none();
         if let Some(expr) = block.stmts.iter().last();
-        if let hir::StmtKind::Semi(ref expr) = expr.kind;
-        if let hir::ExprKind::Assign(ref var, ref value, _) = expr.kind;
+        if let hir::StmtKind::Semi(expr) = expr.kind;
+        if let hir::ExprKind::Assign(var, value, _) = expr.kind;
         if path_to_local_id(var, decl);
         then {
             let mut v = LocalUsedVisitor::new(cx, decl);
diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs
index 7e3a76ded2c..17e23781db7 100644
--- a/clippy_lints/src/let_underscore.rs
+++ b/clippy_lints/src/let_underscore.rs
@@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
 
         if_chain! {
             if let PatKind::Wild = local.pat.kind;
-            if let Some(ref init) = local.init;
+            if let Some(init) = local.init;
             then {
                 let init_ty = cx.typeck_results().expr_ty(init);
                 let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index a99ed7656bf..7abd02c53f1 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -6,7 +6,6 @@
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
 #![feature(once_cell)]
-#![cfg_attr(bootstrap, feature(or_patterns))]
 #![feature(rustc_private)]
 #![feature(stmt_expr_attributes)]
 #![feature(control_flow_enum)]
@@ -23,7 +22,6 @@
 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
-extern crate rustc_attr;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
@@ -166,6 +164,7 @@ mod consts;
 mod utils;
 
 // begin lints modules, do not remove this comment, it’s used in `update_lints`
+mod absurd_extreme_comparisons;
 mod approx_const;
 mod arithmetic;
 mod as_conversions;
@@ -233,6 +232,7 @@ mod if_let_mutex;
 mod if_let_some_result;
 mod if_not_else;
 mod if_then_some_else_none;
+mod implicit_hasher;
 mod implicit_return;
 mod implicit_saturating_sub;
 mod inconsistent_struct_constructor;
@@ -243,6 +243,7 @@ mod inherent_to_string;
 mod inline_fn_without_body;
 mod int_plus_one;
 mod integer_division;
+mod invalid_upcast_comparisons;
 mod items_after_statements;
 mod large_const_arrays;
 mod large_enum_variant;
@@ -290,6 +291,7 @@ mod needless_bool;
 mod needless_borrow;
 mod needless_borrowed_ref;
 mod needless_continue;
+mod needless_for_each;
 mod needless_pass_by_value;
 mod needless_question_mark;
 mod needless_update;
@@ -299,6 +301,7 @@ mod new_without_default;
 mod no_effect;
 mod non_copy_const;
 mod non_expressive_names;
+mod non_octal_unix_permissions;
 mod open_options;
 mod option_env_unwrap;
 mod option_if_let_else;
@@ -539,476 +542,482 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     // begin register lints, do not remove this comment, it’s used in `update_lints`
     store.register_lints(&[
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::CLIPPY_LINTS_INTERNAL,
+        utils::internal_lints::CLIPPY_LINTS_INTERNAL,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
+        utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::COMPILER_LINT_FUNCTIONS,
+        utils::internal_lints::COMPILER_LINT_FUNCTIONS,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::DEFAULT_LINT,
+        utils::internal_lints::DEFAULT_LINT,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::INTERNING_DEFINED_SYMBOL,
+        utils::internal_lints::IF_CHAIN_STYLE,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::INVALID_PATHS,
+        utils::internal_lints::INTERNING_DEFINED_SYMBOL,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::LINT_WITHOUT_LINT_PASS,
+        utils::internal_lints::INVALID_PATHS,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
+        utils::internal_lints::LINT_WITHOUT_LINT_PASS,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::OUTER_EXPN_EXPN_DATA,
+        utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::PRODUCE_ICE,
+        utils::internal_lints::OUTER_EXPN_EXPN_DATA,
         #[cfg(feature = "internal-lints")]
-        &utils::internal_lints::UNNECESSARY_SYMBOL_STR,
-        &approx_const::APPROX_CONSTANT,
-        &arithmetic::FLOAT_ARITHMETIC,
-        &arithmetic::INTEGER_ARITHMETIC,
-        &as_conversions::AS_CONVERSIONS,
-        &asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
-        &asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
-        &assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
-        &assign_ops::ASSIGN_OP_PATTERN,
-        &assign_ops::MISREFACTORED_ASSIGN_OP,
-        &async_yields_async::ASYNC_YIELDS_ASYNC,
-        &atomic_ordering::INVALID_ATOMIC_ORDERING,
-        &attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
-        &attrs::DEPRECATED_CFG_ATTR,
-        &attrs::DEPRECATED_SEMVER,
-        &attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
-        &attrs::INLINE_ALWAYS,
-        &attrs::MISMATCHED_TARGET_OS,
-        &attrs::USELESS_ATTRIBUTE,
-        &await_holding_invalid::AWAIT_HOLDING_LOCK,
-        &await_holding_invalid::AWAIT_HOLDING_REFCELL_REF,
-        &bit_mask::BAD_BIT_MASK,
-        &bit_mask::INEFFECTIVE_BIT_MASK,
-        &bit_mask::VERBOSE_BIT_MASK,
-        &blacklisted_name::BLACKLISTED_NAME,
-        &blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS,
-        &booleans::LOGIC_BUG,
-        &booleans::NONMINIMAL_BOOL,
-        &bytecount::NAIVE_BYTECOUNT,
-        &cargo_common_metadata::CARGO_COMMON_METADATA,
-        &case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
-        &casts::CAST_LOSSLESS,
-        &casts::CAST_POSSIBLE_TRUNCATION,
-        &casts::CAST_POSSIBLE_WRAP,
-        &casts::CAST_PRECISION_LOSS,
-        &casts::CAST_PTR_ALIGNMENT,
-        &casts::CAST_REF_TO_MUT,
-        &casts::CAST_SIGN_LOSS,
-        &casts::CHAR_LIT_AS_U8,
-        &casts::FN_TO_NUMERIC_CAST,
-        &casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
-        &casts::PTR_AS_PTR,
-        &casts::UNNECESSARY_CAST,
-        &checked_conversions::CHECKED_CONVERSIONS,
-        &cognitive_complexity::COGNITIVE_COMPLEXITY,
-        &collapsible_if::COLLAPSIBLE_ELSE_IF,
-        &collapsible_if::COLLAPSIBLE_IF,
-        &collapsible_match::COLLAPSIBLE_MATCH,
-        &comparison_chain::COMPARISON_CHAIN,
-        &copies::IFS_SAME_COND,
-        &copies::IF_SAME_THEN_ELSE,
-        &copies::SAME_FUNCTIONS_IN_IF_CONDITION,
-        &copy_iterator::COPY_ITERATOR,
-        &create_dir::CREATE_DIR,
-        &dbg_macro::DBG_MACRO,
-        &default::DEFAULT_TRAIT_ACCESS,
-        &default::FIELD_REASSIGN_WITH_DEFAULT,
-        &default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK,
-        &dereference::EXPLICIT_DEREF_METHODS,
-        &derive::DERIVE_HASH_XOR_EQ,
-        &derive::DERIVE_ORD_XOR_PARTIAL_ORD,
-        &derive::EXPL_IMPL_CLONE_ON_COPY,
-        &derive::UNSAFE_DERIVE_DESERIALIZE,
-        &disallowed_method::DISALLOWED_METHOD,
-        &doc::DOC_MARKDOWN,
-        &doc::MISSING_ERRORS_DOC,
-        &doc::MISSING_PANICS_DOC,
-        &doc::MISSING_SAFETY_DOC,
-        &doc::NEEDLESS_DOCTEST_MAIN,
-        &double_comparison::DOUBLE_COMPARISONS,
-        &double_parens::DOUBLE_PARENS,
-        &drop_forget_ref::DROP_COPY,
-        &drop_forget_ref::DROP_REF,
-        &drop_forget_ref::FORGET_COPY,
-        &drop_forget_ref::FORGET_REF,
-        &duration_subsec::DURATION_SUBSEC,
-        &else_if_without_else::ELSE_IF_WITHOUT_ELSE,
-        &empty_enum::EMPTY_ENUM,
-        &entry::MAP_ENTRY,
-        &enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
-        &enum_variants::ENUM_VARIANT_NAMES,
-        &enum_variants::MODULE_INCEPTION,
-        &enum_variants::MODULE_NAME_REPETITIONS,
-        &enum_variants::PUB_ENUM_VARIANT_NAMES,
-        &eq_op::EQ_OP,
-        &eq_op::OP_REF,
-        &erasing_op::ERASING_OP,
-        &escape::BOXED_LOCAL,
-        &eta_reduction::REDUNDANT_CLOSURE,
-        &eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
-        &eval_order_dependence::DIVERGING_SUB_EXPRESSION,
-        &eval_order_dependence::EVAL_ORDER_DEPENDENCE,
-        &excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS,
-        &excessive_bools::STRUCT_EXCESSIVE_BOOLS,
-        &exhaustive_items::EXHAUSTIVE_ENUMS,
-        &exhaustive_items::EXHAUSTIVE_STRUCTS,
-        &exit::EXIT,
-        &explicit_write::EXPLICIT_WRITE,
-        &fallible_impl_from::FALLIBLE_IMPL_FROM,
-        &float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS,
-        &float_literal::EXCESSIVE_PRECISION,
-        &float_literal::LOSSY_FLOAT_LITERAL,
-        &floating_point_arithmetic::IMPRECISE_FLOPS,
-        &floating_point_arithmetic::SUBOPTIMAL_FLOPS,
-        &format::USELESS_FORMAT,
-        &formatting::POSSIBLE_MISSING_COMMA,
-        &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
-        &formatting::SUSPICIOUS_ELSE_FORMATTING,
-        &formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
-        &from_over_into::FROM_OVER_INTO,
-        &from_str_radix_10::FROM_STR_RADIX_10,
-        &functions::DOUBLE_MUST_USE,
-        &functions::MUST_USE_CANDIDATE,
-        &functions::MUST_USE_UNIT,
-        &functions::NOT_UNSAFE_PTR_ARG_DEREF,
-        &functions::RESULT_UNIT_ERR,
-        &functions::TOO_MANY_ARGUMENTS,
-        &functions::TOO_MANY_LINES,
-        &future_not_send::FUTURE_NOT_SEND,
-        &get_last_with_len::GET_LAST_WITH_LEN,
-        &identity_op::IDENTITY_OP,
-        &if_let_mutex::IF_LET_MUTEX,
-        &if_let_some_result::IF_LET_SOME_RESULT,
-        &if_not_else::IF_NOT_ELSE,
-        &if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
-        &implicit_return::IMPLICIT_RETURN,
-        &implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
-        &inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
-        &indexing_slicing::INDEXING_SLICING,
-        &indexing_slicing::OUT_OF_BOUNDS_INDEXING,
-        &infinite_iter::INFINITE_ITER,
-        &infinite_iter::MAYBE_INFINITE_ITER,
-        &inherent_impl::MULTIPLE_INHERENT_IMPL,
-        &inherent_to_string::INHERENT_TO_STRING,
-        &inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
-        &inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
-        &int_plus_one::INT_PLUS_ONE,
-        &integer_division::INTEGER_DIVISION,
-        &items_after_statements::ITEMS_AFTER_STATEMENTS,
-        &large_const_arrays::LARGE_CONST_ARRAYS,
-        &large_enum_variant::LARGE_ENUM_VARIANT,
-        &large_stack_arrays::LARGE_STACK_ARRAYS,
-        &len_zero::COMPARISON_TO_EMPTY,
-        &len_zero::LEN_WITHOUT_IS_EMPTY,
-        &len_zero::LEN_ZERO,
-        &let_if_seq::USELESS_LET_IF_SEQ,
-        &let_underscore::LET_UNDERSCORE_DROP,
-        &let_underscore::LET_UNDERSCORE_LOCK,
-        &let_underscore::LET_UNDERSCORE_MUST_USE,
-        &lifetimes::EXTRA_UNUSED_LIFETIMES,
-        &lifetimes::NEEDLESS_LIFETIMES,
-        &literal_representation::DECIMAL_LITERAL_REPRESENTATION,
-        &literal_representation::INCONSISTENT_DIGIT_GROUPING,
-        &literal_representation::LARGE_DIGIT_GROUPS,
-        &literal_representation::MISTYPED_LITERAL_SUFFIXES,
-        &literal_representation::UNREADABLE_LITERAL,
-        &literal_representation::UNUSUAL_BYTE_GROUPINGS,
-        &loops::EMPTY_LOOP,
-        &loops::EXPLICIT_COUNTER_LOOP,
-        &loops::EXPLICIT_INTO_ITER_LOOP,
-        &loops::EXPLICIT_ITER_LOOP,
-        &loops::FOR_KV_MAP,
-        &loops::FOR_LOOPS_OVER_FALLIBLES,
-        &loops::ITER_NEXT_LOOP,
-        &loops::MANUAL_FLATTEN,
-        &loops::MANUAL_MEMCPY,
-        &loops::MUT_RANGE_BOUND,
-        &loops::NEEDLESS_COLLECT,
-        &loops::NEEDLESS_RANGE_LOOP,
-        &loops::NEVER_LOOP,
-        &loops::SAME_ITEM_PUSH,
-        &loops::SINGLE_ELEMENT_LOOP,
-        &loops::WHILE_IMMUTABLE_CONDITION,
-        &loops::WHILE_LET_LOOP,
-        &loops::WHILE_LET_ON_ITERATOR,
-        &macro_use::MACRO_USE_IMPORTS,
-        &main_recursion::MAIN_RECURSION,
-        &manual_async_fn::MANUAL_ASYNC_FN,
-        &manual_map::MANUAL_MAP,
-        &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
-        &manual_ok_or::MANUAL_OK_OR,
-        &manual_strip::MANUAL_STRIP,
-        &manual_unwrap_or::MANUAL_UNWRAP_OR,
-        &map_clone::MAP_CLONE,
-        &map_err_ignore::MAP_ERR_IGNORE,
-        &map_identity::MAP_IDENTITY,
-        &map_unit_fn::OPTION_MAP_UNIT_FN,
-        &map_unit_fn::RESULT_MAP_UNIT_FN,
-        &match_on_vec_items::MATCH_ON_VEC_ITEMS,
-        &matches::INFALLIBLE_DESTRUCTURING_MATCH,
-        &matches::MATCH_AS_REF,
-        &matches::MATCH_BOOL,
-        &matches::MATCH_LIKE_MATCHES_MACRO,
-        &matches::MATCH_OVERLAPPING_ARM,
-        &matches::MATCH_REF_PATS,
-        &matches::MATCH_SAME_ARMS,
-        &matches::MATCH_SINGLE_BINDING,
-        &matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
-        &matches::MATCH_WILD_ERR_ARM,
-        &matches::REDUNDANT_PATTERN_MATCHING,
-        &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
-        &matches::SINGLE_MATCH,
-        &matches::SINGLE_MATCH_ELSE,
-        &matches::WILDCARD_ENUM_MATCH_ARM,
-        &matches::WILDCARD_IN_OR_PATTERNS,
-        &mem_discriminant::MEM_DISCRIMINANT_NON_ENUM,
-        &mem_forget::MEM_FORGET,
-        &mem_replace::MEM_REPLACE_OPTION_WITH_NONE,
-        &mem_replace::MEM_REPLACE_WITH_DEFAULT,
-        &mem_replace::MEM_REPLACE_WITH_UNINIT,
-        &methods::BIND_INSTEAD_OF_MAP,
-        &methods::BYTES_NTH,
-        &methods::CHARS_LAST_CMP,
-        &methods::CHARS_NEXT_CMP,
-        &methods::CLONE_DOUBLE_REF,
-        &methods::CLONE_ON_COPY,
-        &methods::CLONE_ON_REF_PTR,
-        &methods::EXPECT_FUN_CALL,
-        &methods::EXPECT_USED,
-        &methods::FILETYPE_IS_FILE,
-        &methods::FILTER_MAP,
-        &methods::FILTER_MAP_IDENTITY,
-        &methods::FILTER_MAP_NEXT,
-        &methods::FILTER_NEXT,
-        &methods::FLAT_MAP_IDENTITY,
-        &methods::FROM_ITER_INSTEAD_OF_COLLECT,
-        &methods::GET_UNWRAP,
-        &methods::IMPLICIT_CLONE,
-        &methods::INEFFICIENT_TO_STRING,
-        &methods::INSPECT_FOR_EACH,
-        &methods::INTO_ITER_ON_REF,
-        &methods::ITERATOR_STEP_BY_ZERO,
-        &methods::ITER_CLONED_COLLECT,
-        &methods::ITER_COUNT,
-        &methods::ITER_NEXT_SLICE,
-        &methods::ITER_NTH,
-        &methods::ITER_NTH_ZERO,
-        &methods::ITER_SKIP_NEXT,
-        &methods::MANUAL_FILTER_MAP,
-        &methods::MANUAL_FIND_MAP,
-        &methods::MANUAL_SATURATING_ARITHMETIC,
-        &methods::MAP_COLLECT_RESULT_UNIT,
-        &methods::MAP_FLATTEN,
-        &methods::MAP_UNWRAP_OR,
-        &methods::NEW_RET_NO_SELF,
-        &methods::OK_EXPECT,
-        &methods::OPTION_AS_REF_DEREF,
-        &methods::OPTION_MAP_OR_NONE,
-        &methods::OR_FUN_CALL,
-        &methods::RESULT_MAP_OR_INTO_OPTION,
-        &methods::SEARCH_IS_SOME,
-        &methods::SHOULD_IMPLEMENT_TRAIT,
-        &methods::SINGLE_CHAR_ADD_STR,
-        &methods::SINGLE_CHAR_PATTERN,
-        &methods::SKIP_WHILE_NEXT,
-        &methods::STRING_EXTEND_CHARS,
-        &methods::SUSPICIOUS_MAP,
-        &methods::UNINIT_ASSUMED_INIT,
-        &methods::UNNECESSARY_FILTER_MAP,
-        &methods::UNNECESSARY_FOLD,
-        &methods::UNNECESSARY_LAZY_EVALUATIONS,
-        &methods::UNWRAP_USED,
-        &methods::USELESS_ASREF,
-        &methods::WRONG_PUB_SELF_CONVENTION,
-        &methods::WRONG_SELF_CONVENTION,
-        &methods::ZST_OFFSET,
-        &minmax::MIN_MAX,
-        &misc::CMP_NAN,
-        &misc::CMP_OWNED,
-        &misc::FLOAT_CMP,
-        &misc::FLOAT_CMP_CONST,
-        &misc::MODULO_ONE,
-        &misc::SHORT_CIRCUIT_STATEMENT,
-        &misc::TOPLEVEL_REF_ARG,
-        &misc::USED_UNDERSCORE_BINDING,
-        &misc::ZERO_PTR,
-        &misc_early::BUILTIN_TYPE_SHADOW,
-        &misc_early::DOUBLE_NEG,
-        &misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
-        &misc_early::MIXED_CASE_HEX_LITERALS,
-        &misc_early::REDUNDANT_PATTERN,
-        &misc_early::UNNEEDED_FIELD_PATTERN,
-        &misc_early::UNNEEDED_WILDCARD_PATTERN,
-        &misc_early::UNSEPARATED_LITERAL_SUFFIX,
-        &misc_early::ZERO_PREFIXED_LITERAL,
-        &missing_const_for_fn::MISSING_CONST_FOR_FN,
-        &missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
-        &missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
-        &modulo_arithmetic::MODULO_ARITHMETIC,
-        &multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
-        &mut_key::MUTABLE_KEY_TYPE,
-        &mut_mut::MUT_MUT,
-        &mut_mutex_lock::MUT_MUTEX_LOCK,
-        &mut_reference::UNNECESSARY_MUT_PASSED,
-        &mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL,
-        &mutex_atomic::MUTEX_ATOMIC,
-        &mutex_atomic::MUTEX_INTEGER,
-        &needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE,
-        &needless_bool::BOOL_COMPARISON,
-        &needless_bool::NEEDLESS_BOOL,
-        &needless_borrow::NEEDLESS_BORROW,
-        &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
-        &needless_continue::NEEDLESS_CONTINUE,
-        &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
-        &needless_question_mark::NEEDLESS_QUESTION_MARK,
-        &needless_update::NEEDLESS_UPDATE,
-        &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD,
-        &neg_multiply::NEG_MULTIPLY,
-        &new_without_default::NEW_WITHOUT_DEFAULT,
-        &no_effect::NO_EFFECT,
-        &no_effect::UNNECESSARY_OPERATION,
-        &non_copy_const::BORROW_INTERIOR_MUTABLE_CONST,
-        &non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST,
-        &non_expressive_names::JUST_UNDERSCORES_AND_DIGITS,
-        &non_expressive_names::MANY_SINGLE_CHAR_NAMES,
-        &non_expressive_names::SIMILAR_NAMES,
-        &open_options::NONSENSICAL_OPEN_OPTIONS,
-        &option_env_unwrap::OPTION_ENV_UNWRAP,
-        &option_if_let_else::OPTION_IF_LET_ELSE,
-        &overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
-        &panic_in_result_fn::PANIC_IN_RESULT_FN,
-        &panic_unimplemented::PANIC,
-        &panic_unimplemented::TODO,
-        &panic_unimplemented::UNIMPLEMENTED,
-        &panic_unimplemented::UNREACHABLE,
-        &partialeq_ne_impl::PARTIALEQ_NE_IMPL,
-        &pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE,
-        &pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF,
-        &path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
-        &pattern_type_mismatch::PATTERN_TYPE_MISMATCH,
-        &precedence::PRECEDENCE,
-        &ptr::CMP_NULL,
-        &ptr::MUT_FROM_REF,
-        &ptr::PTR_ARG,
-        &ptr_eq::PTR_EQ,
-        &ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
-        &question_mark::QUESTION_MARK,
-        &ranges::MANUAL_RANGE_CONTAINS,
-        &ranges::RANGE_MINUS_ONE,
-        &ranges::RANGE_PLUS_ONE,
-        &ranges::RANGE_ZIP_WITH_LEN,
-        &ranges::REVERSED_EMPTY_RANGES,
-        &redundant_clone::REDUNDANT_CLONE,
-        &redundant_closure_call::REDUNDANT_CLOSURE_CALL,
-        &redundant_else::REDUNDANT_ELSE,
-        &redundant_field_names::REDUNDANT_FIELD_NAMES,
-        &redundant_pub_crate::REDUNDANT_PUB_CRATE,
-        &redundant_slicing::REDUNDANT_SLICING,
-        &redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
-        &ref_option_ref::REF_OPTION_REF,
-        &reference::DEREF_ADDROF,
-        &reference::REF_IN_DEREF,
-        &regex::INVALID_REGEX,
-        &regex::TRIVIAL_REGEX,
-        &repeat_once::REPEAT_ONCE,
-        &returns::LET_AND_RETURN,
-        &returns::NEEDLESS_RETURN,
-        &self_assignment::SELF_ASSIGNMENT,
-        &semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
-        &serde_api::SERDE_API_MISUSE,
-        &shadow::SHADOW_REUSE,
-        &shadow::SHADOW_SAME,
-        &shadow::SHADOW_UNRELATED,
-        &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
-        &size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
-        &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
-        &stable_sort_primitive::STABLE_SORT_PRIMITIVE,
-        &strings::STRING_ADD,
-        &strings::STRING_ADD_ASSIGN,
-        &strings::STRING_FROM_UTF8_AS_BYTES,
-        &strings::STRING_LIT_AS_BYTES,
-        &strings::STRING_TO_STRING,
-        &strings::STR_TO_STRING,
-        &suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS,
-        &suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
-        &suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
-        &swap::ALMOST_SWAPPED,
-        &swap::MANUAL_SWAP,
-        &tabs_in_doc_comments::TABS_IN_DOC_COMMENTS,
-        &temporary_assignment::TEMPORARY_ASSIGNMENT,
-        &to_digit_is_some::TO_DIGIT_IS_SOME,
-        &to_string_in_display::TO_STRING_IN_DISPLAY,
-        &trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS,
-        &trait_bounds::TYPE_REPETITION_IN_BOUNDS,
-        &transmute::CROSSPOINTER_TRANSMUTE,
-        &transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
-        &transmute::TRANSMUTE_BYTES_TO_STR,
-        &transmute::TRANSMUTE_FLOAT_TO_INT,
-        &transmute::TRANSMUTE_INT_TO_BOOL,
-        &transmute::TRANSMUTE_INT_TO_CHAR,
-        &transmute::TRANSMUTE_INT_TO_FLOAT,
-        &transmute::TRANSMUTE_PTR_TO_PTR,
-        &transmute::TRANSMUTE_PTR_TO_REF,
-        &transmute::UNSOUND_COLLECTION_TRANSMUTE,
-        &transmute::USELESS_TRANSMUTE,
-        &transmute::WRONG_TRANSMUTE,
-        &transmuting_null::TRANSMUTING_NULL,
-        &try_err::TRY_ERR,
-        &types::ABSURD_EXTREME_COMPARISONS,
-        &types::BORROWED_BOX,
-        &types::BOX_VEC,
-        &types::IMPLICIT_HASHER,
-        &types::INVALID_UPCAST_COMPARISONS,
-        &types::LINKEDLIST,
-        &types::OPTION_OPTION,
-        &types::RC_BUFFER,
-        &types::REDUNDANT_ALLOCATION,
-        &types::TYPE_COMPLEXITY,
-        &types::VEC_BOX,
-        &undropped_manually_drops::UNDROPPED_MANUALLY_DROPS,
-        &unicode::INVISIBLE_CHARACTERS,
-        &unicode::NON_ASCII_LITERAL,
-        &unicode::UNICODE_NOT_NFC,
-        &unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
-        &unit_types::LET_UNIT_VALUE,
-        &unit_types::UNIT_ARG,
-        &unit_types::UNIT_CMP,
-        &unnamed_address::FN_ADDRESS_COMPARISONS,
-        &unnamed_address::VTABLE_ADDRESS_COMPARISONS,
-        &unnecessary_sort_by::UNNECESSARY_SORT_BY,
-        &unnecessary_wraps::UNNECESSARY_WRAPS,
-        &unnested_or_patterns::UNNESTED_OR_PATTERNS,
-        &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
-        &unused_io_amount::UNUSED_IO_AMOUNT,
-        &unused_self::UNUSED_SELF,
-        &unused_unit::UNUSED_UNIT,
-        &unwrap::PANICKING_UNWRAP,
-        &unwrap::UNNECESSARY_UNWRAP,
-        &unwrap_in_result::UNWRAP_IN_RESULT,
-        &upper_case_acronyms::UPPER_CASE_ACRONYMS,
-        &use_self::USE_SELF,
-        &useless_conversion::USELESS_CONVERSION,
-        &vec::USELESS_VEC,
-        &vec_init_then_push::VEC_INIT_THEN_PUSH,
-        &vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
-        &verbose_file_reads::VERBOSE_FILE_READS,
-        &wildcard_dependencies::WILDCARD_DEPENDENCIES,
-        &wildcard_imports::ENUM_GLOB_USE,
-        &wildcard_imports::WILDCARD_IMPORTS,
-        &write::PRINTLN_EMPTY_STRING,
-        &write::PRINT_LITERAL,
-        &write::PRINT_STDERR,
-        &write::PRINT_STDOUT,
-        &write::PRINT_WITH_NEWLINE,
-        &write::USE_DEBUG,
-        &write::WRITELN_EMPTY_STRING,
-        &write::WRITE_LITERAL,
-        &write::WRITE_WITH_NEWLINE,
-        &zero_div_zero::ZERO_DIVIDED_BY_ZERO,
-        &zero_sized_map_values::ZERO_SIZED_MAP_VALUES,
+        utils::internal_lints::PRODUCE_ICE,
+        #[cfg(feature = "internal-lints")]
+        utils::internal_lints::UNNECESSARY_SYMBOL_STR,
+        absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS,
+        approx_const::APPROX_CONSTANT,
+        arithmetic::FLOAT_ARITHMETIC,
+        arithmetic::INTEGER_ARITHMETIC,
+        as_conversions::AS_CONVERSIONS,
+        asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
+        asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
+        assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
+        assign_ops::ASSIGN_OP_PATTERN,
+        assign_ops::MISREFACTORED_ASSIGN_OP,
+        async_yields_async::ASYNC_YIELDS_ASYNC,
+        atomic_ordering::INVALID_ATOMIC_ORDERING,
+        attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
+        attrs::DEPRECATED_CFG_ATTR,
+        attrs::DEPRECATED_SEMVER,
+        attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
+        attrs::INLINE_ALWAYS,
+        attrs::MISMATCHED_TARGET_OS,
+        attrs::USELESS_ATTRIBUTE,
+        await_holding_invalid::AWAIT_HOLDING_LOCK,
+        await_holding_invalid::AWAIT_HOLDING_REFCELL_REF,
+        bit_mask::BAD_BIT_MASK,
+        bit_mask::INEFFECTIVE_BIT_MASK,
+        bit_mask::VERBOSE_BIT_MASK,
+        blacklisted_name::BLACKLISTED_NAME,
+        blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS,
+        booleans::LOGIC_BUG,
+        booleans::NONMINIMAL_BOOL,
+        bytecount::NAIVE_BYTECOUNT,
+        cargo_common_metadata::CARGO_COMMON_METADATA,
+        case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
+        casts::CAST_LOSSLESS,
+        casts::CAST_POSSIBLE_TRUNCATION,
+        casts::CAST_POSSIBLE_WRAP,
+        casts::CAST_PRECISION_LOSS,
+        casts::CAST_PTR_ALIGNMENT,
+        casts::CAST_REF_TO_MUT,
+        casts::CAST_SIGN_LOSS,
+        casts::CHAR_LIT_AS_U8,
+        casts::FN_TO_NUMERIC_CAST,
+        casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
+        casts::PTR_AS_PTR,
+        casts::UNNECESSARY_CAST,
+        checked_conversions::CHECKED_CONVERSIONS,
+        cognitive_complexity::COGNITIVE_COMPLEXITY,
+        collapsible_if::COLLAPSIBLE_ELSE_IF,
+        collapsible_if::COLLAPSIBLE_IF,
+        collapsible_match::COLLAPSIBLE_MATCH,
+        comparison_chain::COMPARISON_CHAIN,
+        copies::BRANCHES_SHARING_CODE,
+        copies::IFS_SAME_COND,
+        copies::IF_SAME_THEN_ELSE,
+        copies::SAME_FUNCTIONS_IN_IF_CONDITION,
+        copy_iterator::COPY_ITERATOR,
+        create_dir::CREATE_DIR,
+        dbg_macro::DBG_MACRO,
+        default::DEFAULT_TRAIT_ACCESS,
+        default::FIELD_REASSIGN_WITH_DEFAULT,
+        default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK,
+        dereference::EXPLICIT_DEREF_METHODS,
+        derive::DERIVE_HASH_XOR_EQ,
+        derive::DERIVE_ORD_XOR_PARTIAL_ORD,
+        derive::EXPL_IMPL_CLONE_ON_COPY,
+        derive::UNSAFE_DERIVE_DESERIALIZE,
+        disallowed_method::DISALLOWED_METHOD,
+        doc::DOC_MARKDOWN,
+        doc::MISSING_ERRORS_DOC,
+        doc::MISSING_PANICS_DOC,
+        doc::MISSING_SAFETY_DOC,
+        doc::NEEDLESS_DOCTEST_MAIN,
+        double_comparison::DOUBLE_COMPARISONS,
+        double_parens::DOUBLE_PARENS,
+        drop_forget_ref::DROP_COPY,
+        drop_forget_ref::DROP_REF,
+        drop_forget_ref::FORGET_COPY,
+        drop_forget_ref::FORGET_REF,
+        duration_subsec::DURATION_SUBSEC,
+        else_if_without_else::ELSE_IF_WITHOUT_ELSE,
+        empty_enum::EMPTY_ENUM,
+        entry::MAP_ENTRY,
+        enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
+        enum_variants::ENUM_VARIANT_NAMES,
+        enum_variants::MODULE_INCEPTION,
+        enum_variants::MODULE_NAME_REPETITIONS,
+        enum_variants::PUB_ENUM_VARIANT_NAMES,
+        eq_op::EQ_OP,
+        eq_op::OP_REF,
+        erasing_op::ERASING_OP,
+        escape::BOXED_LOCAL,
+        eta_reduction::REDUNDANT_CLOSURE,
+        eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
+        eval_order_dependence::DIVERGING_SUB_EXPRESSION,
+        eval_order_dependence::EVAL_ORDER_DEPENDENCE,
+        excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS,
+        excessive_bools::STRUCT_EXCESSIVE_BOOLS,
+        exhaustive_items::EXHAUSTIVE_ENUMS,
+        exhaustive_items::EXHAUSTIVE_STRUCTS,
+        exit::EXIT,
+        explicit_write::EXPLICIT_WRITE,
+        fallible_impl_from::FALLIBLE_IMPL_FROM,
+        float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS,
+        float_literal::EXCESSIVE_PRECISION,
+        float_literal::LOSSY_FLOAT_LITERAL,
+        floating_point_arithmetic::IMPRECISE_FLOPS,
+        floating_point_arithmetic::SUBOPTIMAL_FLOPS,
+        format::USELESS_FORMAT,
+        formatting::POSSIBLE_MISSING_COMMA,
+        formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
+        formatting::SUSPICIOUS_ELSE_FORMATTING,
+        formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
+        from_over_into::FROM_OVER_INTO,
+        from_str_radix_10::FROM_STR_RADIX_10,
+        functions::DOUBLE_MUST_USE,
+        functions::MUST_USE_CANDIDATE,
+        functions::MUST_USE_UNIT,
+        functions::NOT_UNSAFE_PTR_ARG_DEREF,
+        functions::RESULT_UNIT_ERR,
+        functions::TOO_MANY_ARGUMENTS,
+        functions::TOO_MANY_LINES,
+        future_not_send::FUTURE_NOT_SEND,
+        get_last_with_len::GET_LAST_WITH_LEN,
+        identity_op::IDENTITY_OP,
+        if_let_mutex::IF_LET_MUTEX,
+        if_let_some_result::IF_LET_SOME_RESULT,
+        if_not_else::IF_NOT_ELSE,
+        if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
+        implicit_hasher::IMPLICIT_HASHER,
+        implicit_return::IMPLICIT_RETURN,
+        implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
+        inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
+        indexing_slicing::INDEXING_SLICING,
+        indexing_slicing::OUT_OF_BOUNDS_INDEXING,
+        infinite_iter::INFINITE_ITER,
+        infinite_iter::MAYBE_INFINITE_ITER,
+        inherent_impl::MULTIPLE_INHERENT_IMPL,
+        inherent_to_string::INHERENT_TO_STRING,
+        inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
+        inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
+        int_plus_one::INT_PLUS_ONE,
+        integer_division::INTEGER_DIVISION,
+        invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS,
+        items_after_statements::ITEMS_AFTER_STATEMENTS,
+        large_const_arrays::LARGE_CONST_ARRAYS,
+        large_enum_variant::LARGE_ENUM_VARIANT,
+        large_stack_arrays::LARGE_STACK_ARRAYS,
+        len_zero::COMPARISON_TO_EMPTY,
+        len_zero::LEN_WITHOUT_IS_EMPTY,
+        len_zero::LEN_ZERO,
+        let_if_seq::USELESS_LET_IF_SEQ,
+        let_underscore::LET_UNDERSCORE_DROP,
+        let_underscore::LET_UNDERSCORE_LOCK,
+        let_underscore::LET_UNDERSCORE_MUST_USE,
+        lifetimes::EXTRA_UNUSED_LIFETIMES,
+        lifetimes::NEEDLESS_LIFETIMES,
+        literal_representation::DECIMAL_LITERAL_REPRESENTATION,
+        literal_representation::INCONSISTENT_DIGIT_GROUPING,
+        literal_representation::LARGE_DIGIT_GROUPS,
+        literal_representation::MISTYPED_LITERAL_SUFFIXES,
+        literal_representation::UNREADABLE_LITERAL,
+        literal_representation::UNUSUAL_BYTE_GROUPINGS,
+        loops::EMPTY_LOOP,
+        loops::EXPLICIT_COUNTER_LOOP,
+        loops::EXPLICIT_INTO_ITER_LOOP,
+        loops::EXPLICIT_ITER_LOOP,
+        loops::FOR_KV_MAP,
+        loops::FOR_LOOPS_OVER_FALLIBLES,
+        loops::ITER_NEXT_LOOP,
+        loops::MANUAL_FLATTEN,
+        loops::MANUAL_MEMCPY,
+        loops::MUT_RANGE_BOUND,
+        loops::NEEDLESS_COLLECT,
+        loops::NEEDLESS_RANGE_LOOP,
+        loops::NEVER_LOOP,
+        loops::SAME_ITEM_PUSH,
+        loops::SINGLE_ELEMENT_LOOP,
+        loops::WHILE_IMMUTABLE_CONDITION,
+        loops::WHILE_LET_LOOP,
+        loops::WHILE_LET_ON_ITERATOR,
+        macro_use::MACRO_USE_IMPORTS,
+        main_recursion::MAIN_RECURSION,
+        manual_async_fn::MANUAL_ASYNC_FN,
+        manual_map::MANUAL_MAP,
+        manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
+        manual_ok_or::MANUAL_OK_OR,
+        manual_strip::MANUAL_STRIP,
+        manual_unwrap_or::MANUAL_UNWRAP_OR,
+        map_clone::MAP_CLONE,
+        map_err_ignore::MAP_ERR_IGNORE,
+        map_identity::MAP_IDENTITY,
+        map_unit_fn::OPTION_MAP_UNIT_FN,
+        map_unit_fn::RESULT_MAP_UNIT_FN,
+        match_on_vec_items::MATCH_ON_VEC_ITEMS,
+        matches::INFALLIBLE_DESTRUCTURING_MATCH,
+        matches::MATCH_AS_REF,
+        matches::MATCH_BOOL,
+        matches::MATCH_LIKE_MATCHES_MACRO,
+        matches::MATCH_OVERLAPPING_ARM,
+        matches::MATCH_REF_PATS,
+        matches::MATCH_SAME_ARMS,
+        matches::MATCH_SINGLE_BINDING,
+        matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
+        matches::MATCH_WILD_ERR_ARM,
+        matches::REDUNDANT_PATTERN_MATCHING,
+        matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
+        matches::SINGLE_MATCH,
+        matches::SINGLE_MATCH_ELSE,
+        matches::WILDCARD_ENUM_MATCH_ARM,
+        matches::WILDCARD_IN_OR_PATTERNS,
+        mem_discriminant::MEM_DISCRIMINANT_NON_ENUM,
+        mem_forget::MEM_FORGET,
+        mem_replace::MEM_REPLACE_OPTION_WITH_NONE,
+        mem_replace::MEM_REPLACE_WITH_DEFAULT,
+        mem_replace::MEM_REPLACE_WITH_UNINIT,
+        methods::BIND_INSTEAD_OF_MAP,
+        methods::BYTES_NTH,
+        methods::CHARS_LAST_CMP,
+        methods::CHARS_NEXT_CMP,
+        methods::CLONE_DOUBLE_REF,
+        methods::CLONE_ON_COPY,
+        methods::CLONE_ON_REF_PTR,
+        methods::EXPECT_FUN_CALL,
+        methods::EXPECT_USED,
+        methods::FILETYPE_IS_FILE,
+        methods::FILTER_MAP,
+        methods::FILTER_MAP_IDENTITY,
+        methods::FILTER_MAP_NEXT,
+        methods::FILTER_NEXT,
+        methods::FLAT_MAP_IDENTITY,
+        methods::FROM_ITER_INSTEAD_OF_COLLECT,
+        methods::GET_UNWRAP,
+        methods::IMPLICIT_CLONE,
+        methods::INEFFICIENT_TO_STRING,
+        methods::INSPECT_FOR_EACH,
+        methods::INTO_ITER_ON_REF,
+        methods::ITERATOR_STEP_BY_ZERO,
+        methods::ITER_CLONED_COLLECT,
+        methods::ITER_COUNT,
+        methods::ITER_NEXT_SLICE,
+        methods::ITER_NTH,
+        methods::ITER_NTH_ZERO,
+        methods::ITER_SKIP_NEXT,
+        methods::MANUAL_FILTER_MAP,
+        methods::MANUAL_FIND_MAP,
+        methods::MANUAL_SATURATING_ARITHMETIC,
+        methods::MAP_COLLECT_RESULT_UNIT,
+        methods::MAP_FLATTEN,
+        methods::MAP_UNWRAP_OR,
+        methods::NEW_RET_NO_SELF,
+        methods::OK_EXPECT,
+        methods::OPTION_AS_REF_DEREF,
+        methods::OPTION_FILTER_MAP,
+        methods::OPTION_MAP_OR_NONE,
+        methods::OR_FUN_CALL,
+        methods::RESULT_MAP_OR_INTO_OPTION,
+        methods::SEARCH_IS_SOME,
+        methods::SHOULD_IMPLEMENT_TRAIT,
+        methods::SINGLE_CHAR_ADD_STR,
+        methods::SINGLE_CHAR_PATTERN,
+        methods::SKIP_WHILE_NEXT,
+        methods::STRING_EXTEND_CHARS,
+        methods::SUSPICIOUS_MAP,
+        methods::UNINIT_ASSUMED_INIT,
+        methods::UNNECESSARY_FILTER_MAP,
+        methods::UNNECESSARY_FOLD,
+        methods::UNNECESSARY_LAZY_EVALUATIONS,
+        methods::UNWRAP_USED,
+        methods::USELESS_ASREF,
+        methods::WRONG_PUB_SELF_CONVENTION,
+        methods::WRONG_SELF_CONVENTION,
+        methods::ZST_OFFSET,
+        minmax::MIN_MAX,
+        misc::CMP_NAN,
+        misc::CMP_OWNED,
+        misc::FLOAT_CMP,
+        misc::FLOAT_CMP_CONST,
+        misc::MODULO_ONE,
+        misc::SHORT_CIRCUIT_STATEMENT,
+        misc::TOPLEVEL_REF_ARG,
+        misc::USED_UNDERSCORE_BINDING,
+        misc::ZERO_PTR,
+        misc_early::BUILTIN_TYPE_SHADOW,
+        misc_early::DOUBLE_NEG,
+        misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
+        misc_early::MIXED_CASE_HEX_LITERALS,
+        misc_early::REDUNDANT_PATTERN,
+        misc_early::UNNEEDED_FIELD_PATTERN,
+        misc_early::UNNEEDED_WILDCARD_PATTERN,
+        misc_early::UNSEPARATED_LITERAL_SUFFIX,
+        misc_early::ZERO_PREFIXED_LITERAL,
+        missing_const_for_fn::MISSING_CONST_FOR_FN,
+        missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
+        missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
+        modulo_arithmetic::MODULO_ARITHMETIC,
+        multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
+        mut_key::MUTABLE_KEY_TYPE,
+        mut_mut::MUT_MUT,
+        mut_mutex_lock::MUT_MUTEX_LOCK,
+        mut_reference::UNNECESSARY_MUT_PASSED,
+        mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL,
+        mutex_atomic::MUTEX_ATOMIC,
+        mutex_atomic::MUTEX_INTEGER,
+        needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE,
+        needless_bool::BOOL_COMPARISON,
+        needless_bool::NEEDLESS_BOOL,
+        needless_borrow::NEEDLESS_BORROW,
+        needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
+        needless_continue::NEEDLESS_CONTINUE,
+        needless_for_each::NEEDLESS_FOR_EACH,
+        needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
+        needless_question_mark::NEEDLESS_QUESTION_MARK,
+        needless_update::NEEDLESS_UPDATE,
+        neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD,
+        neg_multiply::NEG_MULTIPLY,
+        new_without_default::NEW_WITHOUT_DEFAULT,
+        no_effect::NO_EFFECT,
+        no_effect::UNNECESSARY_OPERATION,
+        non_copy_const::BORROW_INTERIOR_MUTABLE_CONST,
+        non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST,
+        non_expressive_names::JUST_UNDERSCORES_AND_DIGITS,
+        non_expressive_names::MANY_SINGLE_CHAR_NAMES,
+        non_expressive_names::SIMILAR_NAMES,
+        non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS,
+        open_options::NONSENSICAL_OPEN_OPTIONS,
+        option_env_unwrap::OPTION_ENV_UNWRAP,
+        option_if_let_else::OPTION_IF_LET_ELSE,
+        overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
+        panic_in_result_fn::PANIC_IN_RESULT_FN,
+        panic_unimplemented::PANIC,
+        panic_unimplemented::TODO,
+        panic_unimplemented::UNIMPLEMENTED,
+        panic_unimplemented::UNREACHABLE,
+        partialeq_ne_impl::PARTIALEQ_NE_IMPL,
+        pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE,
+        pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF,
+        path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
+        pattern_type_mismatch::PATTERN_TYPE_MISMATCH,
+        precedence::PRECEDENCE,
+        ptr::CMP_NULL,
+        ptr::MUT_FROM_REF,
+        ptr::PTR_ARG,
+        ptr_eq::PTR_EQ,
+        ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
+        question_mark::QUESTION_MARK,
+        ranges::MANUAL_RANGE_CONTAINS,
+        ranges::RANGE_MINUS_ONE,
+        ranges::RANGE_PLUS_ONE,
+        ranges::RANGE_ZIP_WITH_LEN,
+        ranges::REVERSED_EMPTY_RANGES,
+        redundant_clone::REDUNDANT_CLONE,
+        redundant_closure_call::REDUNDANT_CLOSURE_CALL,
+        redundant_else::REDUNDANT_ELSE,
+        redundant_field_names::REDUNDANT_FIELD_NAMES,
+        redundant_pub_crate::REDUNDANT_PUB_CRATE,
+        redundant_slicing::REDUNDANT_SLICING,
+        redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
+        ref_option_ref::REF_OPTION_REF,
+        reference::DEREF_ADDROF,
+        reference::REF_IN_DEREF,
+        regex::INVALID_REGEX,
+        regex::TRIVIAL_REGEX,
+        repeat_once::REPEAT_ONCE,
+        returns::LET_AND_RETURN,
+        returns::NEEDLESS_RETURN,
+        self_assignment::SELF_ASSIGNMENT,
+        semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
+        serde_api::SERDE_API_MISUSE,
+        shadow::SHADOW_REUSE,
+        shadow::SHADOW_SAME,
+        shadow::SHADOW_UNRELATED,
+        single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
+        size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
+        slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
+        stable_sort_primitive::STABLE_SORT_PRIMITIVE,
+        strings::STRING_ADD,
+        strings::STRING_ADD_ASSIGN,
+        strings::STRING_FROM_UTF8_AS_BYTES,
+        strings::STRING_LIT_AS_BYTES,
+        strings::STRING_TO_STRING,
+        strings::STR_TO_STRING,
+        suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS,
+        suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
+        suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
+        swap::ALMOST_SWAPPED,
+        swap::MANUAL_SWAP,
+        tabs_in_doc_comments::TABS_IN_DOC_COMMENTS,
+        temporary_assignment::TEMPORARY_ASSIGNMENT,
+        to_digit_is_some::TO_DIGIT_IS_SOME,
+        to_string_in_display::TO_STRING_IN_DISPLAY,
+        trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS,
+        trait_bounds::TYPE_REPETITION_IN_BOUNDS,
+        transmute::CROSSPOINTER_TRANSMUTE,
+        transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
+        transmute::TRANSMUTE_BYTES_TO_STR,
+        transmute::TRANSMUTE_FLOAT_TO_INT,
+        transmute::TRANSMUTE_INT_TO_BOOL,
+        transmute::TRANSMUTE_INT_TO_CHAR,
+        transmute::TRANSMUTE_INT_TO_FLOAT,
+        transmute::TRANSMUTE_PTR_TO_PTR,
+        transmute::TRANSMUTE_PTR_TO_REF,
+        transmute::UNSOUND_COLLECTION_TRANSMUTE,
+        transmute::USELESS_TRANSMUTE,
+        transmute::WRONG_TRANSMUTE,
+        transmuting_null::TRANSMUTING_NULL,
+        try_err::TRY_ERR,
+        types::BORROWED_BOX,
+        types::BOX_VEC,
+        types::LINKEDLIST,
+        types::OPTION_OPTION,
+        types::RC_BUFFER,
+        types::REDUNDANT_ALLOCATION,
+        types::TYPE_COMPLEXITY,
+        types::VEC_BOX,
+        undropped_manually_drops::UNDROPPED_MANUALLY_DROPS,
+        unicode::INVISIBLE_CHARACTERS,
+        unicode::NON_ASCII_LITERAL,
+        unicode::UNICODE_NOT_NFC,
+        unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
+        unit_types::LET_UNIT_VALUE,
+        unit_types::UNIT_ARG,
+        unit_types::UNIT_CMP,
+        unnamed_address::FN_ADDRESS_COMPARISONS,
+        unnamed_address::VTABLE_ADDRESS_COMPARISONS,
+        unnecessary_sort_by::UNNECESSARY_SORT_BY,
+        unnecessary_wraps::UNNECESSARY_WRAPS,
+        unnested_or_patterns::UNNESTED_OR_PATTERNS,
+        unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
+        unused_io_amount::UNUSED_IO_AMOUNT,
+        unused_self::UNUSED_SELF,
+        unused_unit::UNUSED_UNIT,
+        unwrap::PANICKING_UNWRAP,
+        unwrap::UNNECESSARY_UNWRAP,
+        unwrap_in_result::UNWRAP_IN_RESULT,
+        upper_case_acronyms::UPPER_CASE_ACRONYMS,
+        use_self::USE_SELF,
+        useless_conversion::USELESS_CONVERSION,
+        vec::USELESS_VEC,
+        vec_init_then_push::VEC_INIT_THEN_PUSH,
+        vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
+        verbose_file_reads::VERBOSE_FILE_READS,
+        wildcard_dependencies::WILDCARD_DEPENDENCIES,
+        wildcard_imports::ENUM_GLOB_USE,
+        wildcard_imports::WILDCARD_IMPORTS,
+        write::PRINTLN_EMPTY_STRING,
+        write::PRINT_LITERAL,
+        write::PRINT_STDERR,
+        write::PRINT_STDOUT,
+        write::PRINT_WITH_NEWLINE,
+        write::USE_DEBUG,
+        write::WRITELN_EMPTY_STRING,
+        write::WRITE_LITERAL,
+        write::WRITE_WITH_NEWLINE,
+        zero_div_zero::ZERO_DIVIDED_BY_ZERO,
+        zero_sized_map_values::ZERO_SIZED_MAP_VALUES,
     ]);
     // end register lints, do not remove this comment, it’s used in `update_lints`
 
@@ -1020,6 +1029,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
         store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
         store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
+        store.register_late_pass(|| box utils::internal_lints::IfChainStyle);
         store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
         store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default());
         store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
@@ -1030,7 +1040,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
     store.register_late_pass(|| box serde_api::SerdeApi);
     let vec_box_size_threshold = conf.vec_box_size_threshold;
-    store.register_late_pass(move || box types::Types::new(vec_box_size_threshold));
+    let type_complexity_threshold = conf.type_complexity_threshold;
+    store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold));
     store.register_late_pass(|| box booleans::NonminimalBool);
     store.register_late_pass(|| box eq_op::EqOp);
     store.register_late_pass(|| box enum_clike::UnportableVariant);
@@ -1041,6 +1052,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box ptr_eq::PtrEq);
     store.register_late_pass(|| box needless_bool::NeedlessBool);
     store.register_late_pass(|| box needless_bool::BoolComparison);
+    store.register_late_pass(|| box needless_for_each::NeedlessForEach);
     store.register_late_pass(|| box approx_const::ApproxConstant);
     store.register_late_pass(|| box misc::MiscLints);
     store.register_late_pass(|| box eta_reduction::EtaReduction);
@@ -1059,6 +1071,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
     store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback);
     store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor);
+    store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions);
 
     let msrv = conf.msrv.as_ref().and_then(|s| {
         parse_msrv(s, None, None).or_else(|| {
@@ -1081,6 +1094,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv));
     store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark::new(msrv));
     store.register_late_pass(move || box casts::Casts::new(msrv));
+    store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv));
 
     store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
     store.register_late_pass(|| box map_clone::MapClone);
@@ -1091,8 +1105,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box main_recursion::MainRecursion::default());
     store.register_late_pass(|| box lifetimes::Lifetimes);
     store.register_late_pass(|| box entry::HashMapPass);
-    let type_complexity_threshold = conf.type_complexity_threshold;
-    store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
     store.register_late_pass(|| box minmax::MinMaxPass);
     store.register_late_pass(|| box open_options::OpenOptions);
     store.register_late_pass(|| box zero_div_zero::ZeroDiv);
@@ -1114,8 +1126,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
     store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
     store.register_late_pass(|| box empty_enum::EmptyEnum);
-    store.register_late_pass(|| box types::AbsurdExtremeComparisons);
-    store.register_late_pass(|| box types::InvalidUpcastComparisons);
+    store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons);
+    store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons);
     store.register_late_pass(|| box regex::Regex::default());
     store.register_late_pass(|| box copies::CopyAndPaste);
     store.register_late_pass(|| box copy_iterator::CopyIterator);
@@ -1125,9 +1137,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box new_without_default::NewWithoutDefault::default());
     let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>();
     store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone()));
-    let too_many_arguments_threshold1 = conf.too_many_arguments_threshold;
-    let too_many_lines_threshold2 = conf.too_many_lines_threshold;
-    store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold1, too_many_lines_threshold2));
+    let too_many_arguments_threshold = conf.too_many_arguments_threshold;
+    let too_many_lines_threshold = conf.too_many_lines_threshold;
+    store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold));
     let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
     store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone()));
     store.register_late_pass(|| box neg_multiply::NegMultiply);
@@ -1159,7 +1171,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box infinite_iter::InfiniteIter);
     store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
     store.register_late_pass(|| box useless_conversion::UselessConversion::default());
-    store.register_late_pass(|| box types::ImplicitHasher);
+    store.register_late_pass(|| box implicit_hasher::ImplicitHasher);
     store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
     store.register_late_pass(|| box double_comparison::DoubleComparisons);
     store.register_late_pass(|| box question_mark::QuestionMark);
@@ -1256,7 +1268,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
         single_char_binding_names_threshold,
     });
-    store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns);
     store.register_late_pass(|| box macro_use::MacroUseImports::default());
     store.register_late_pass(|| box map_identity::MapIdentity);
     store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch);
@@ -1285,784 +1296,792 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
 
     store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
-        LintId::of(&arithmetic::FLOAT_ARITHMETIC),
-        LintId::of(&arithmetic::INTEGER_ARITHMETIC),
-        LintId::of(&as_conversions::AS_CONVERSIONS),
-        LintId::of(&asm_syntax::INLINE_ASM_X86_ATT_SYNTAX),
-        LintId::of(&asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX),
-        LintId::of(&create_dir::CREATE_DIR),
-        LintId::of(&dbg_macro::DBG_MACRO),
-        LintId::of(&default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK),
-        LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE),
-        LintId::of(&exhaustive_items::EXHAUSTIVE_ENUMS),
-        LintId::of(&exhaustive_items::EXHAUSTIVE_STRUCTS),
-        LintId::of(&exit::EXIT),
-        LintId::of(&float_literal::LOSSY_FLOAT_LITERAL),
-        LintId::of(&if_then_some_else_none::IF_THEN_SOME_ELSE_NONE),
-        LintId::of(&implicit_return::IMPLICIT_RETURN),
-        LintId::of(&indexing_slicing::INDEXING_SLICING),
-        LintId::of(&inherent_impl::MULTIPLE_INHERENT_IMPL),
-        LintId::of(&integer_division::INTEGER_DIVISION),
-        LintId::of(&let_underscore::LET_UNDERSCORE_MUST_USE),
-        LintId::of(&literal_representation::DECIMAL_LITERAL_REPRESENTATION),
-        LintId::of(&map_err_ignore::MAP_ERR_IGNORE),
-        LintId::of(&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS),
-        LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM),
-        LintId::of(&mem_forget::MEM_FORGET),
-        LintId::of(&methods::CLONE_ON_REF_PTR),
-        LintId::of(&methods::EXPECT_USED),
-        LintId::of(&methods::FILETYPE_IS_FILE),
-        LintId::of(&methods::GET_UNWRAP),
-        LintId::of(&methods::UNWRAP_USED),
-        LintId::of(&methods::WRONG_PUB_SELF_CONVENTION),
-        LintId::of(&misc::FLOAT_CMP_CONST),
-        LintId::of(&misc_early::UNNEEDED_FIELD_PATTERN),
-        LintId::of(&missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
-        LintId::of(&missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
-        LintId::of(&modulo_arithmetic::MODULO_ARITHMETIC),
-        LintId::of(&panic_in_result_fn::PANIC_IN_RESULT_FN),
-        LintId::of(&panic_unimplemented::PANIC),
-        LintId::of(&panic_unimplemented::TODO),
-        LintId::of(&panic_unimplemented::UNIMPLEMENTED),
-        LintId::of(&panic_unimplemented::UNREACHABLE),
-        LintId::of(&pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
-        LintId::of(&semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
-        LintId::of(&shadow::SHADOW_REUSE),
-        LintId::of(&shadow::SHADOW_SAME),
-        LintId::of(&strings::STRING_ADD),
-        LintId::of(&strings::STRING_TO_STRING),
-        LintId::of(&strings::STR_TO_STRING),
-        LintId::of(&types::RC_BUFFER),
-        LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT),
-        LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
-        LintId::of(&write::PRINT_STDERR),
-        LintId::of(&write::PRINT_STDOUT),
-        LintId::of(&write::USE_DEBUG),
+        LintId::of(arithmetic::FLOAT_ARITHMETIC),
+        LintId::of(arithmetic::INTEGER_ARITHMETIC),
+        LintId::of(as_conversions::AS_CONVERSIONS),
+        LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX),
+        LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX),
+        LintId::of(create_dir::CREATE_DIR),
+        LintId::of(dbg_macro::DBG_MACRO),
+        LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK),
+        LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
+        LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
+        LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS),
+        LintId::of(exit::EXIT),
+        LintId::of(float_literal::LOSSY_FLOAT_LITERAL),
+        LintId::of(if_then_some_else_none::IF_THEN_SOME_ELSE_NONE),
+        LintId::of(implicit_return::IMPLICIT_RETURN),
+        LintId::of(indexing_slicing::INDEXING_SLICING),
+        LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL),
+        LintId::of(integer_division::INTEGER_DIVISION),
+        LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE),
+        LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION),
+        LintId::of(map_err_ignore::MAP_ERR_IGNORE),
+        LintId::of(matches::REST_PAT_IN_FULLY_BOUND_STRUCTS),
+        LintId::of(matches::WILDCARD_ENUM_MATCH_ARM),
+        LintId::of(mem_forget::MEM_FORGET),
+        LintId::of(methods::CLONE_ON_REF_PTR),
+        LintId::of(methods::EXPECT_USED),
+        LintId::of(methods::FILETYPE_IS_FILE),
+        LintId::of(methods::GET_UNWRAP),
+        LintId::of(methods::UNWRAP_USED),
+        LintId::of(methods::WRONG_PUB_SELF_CONVENTION),
+        LintId::of(misc::FLOAT_CMP_CONST),
+        LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
+        LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
+        LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
+        LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
+        LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
+        LintId::of(panic_unimplemented::PANIC),
+        LintId::of(panic_unimplemented::TODO),
+        LintId::of(panic_unimplemented::UNIMPLEMENTED),
+        LintId::of(panic_unimplemented::UNREACHABLE),
+        LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
+        LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
+        LintId::of(shadow::SHADOW_REUSE),
+        LintId::of(shadow::SHADOW_SAME),
+        LintId::of(strings::STRING_ADD),
+        LintId::of(strings::STRING_TO_STRING),
+        LintId::of(strings::STR_TO_STRING),
+        LintId::of(types::RC_BUFFER),
+        LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
+        LintId::of(verbose_file_reads::VERBOSE_FILE_READS),
+        LintId::of(write::PRINT_STDERR),
+        LintId::of(write::PRINT_STDOUT),
+        LintId::of(write::USE_DEBUG),
     ]);
 
     store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
-        LintId::of(&attrs::INLINE_ALWAYS),
-        LintId::of(&await_holding_invalid::AWAIT_HOLDING_LOCK),
-        LintId::of(&await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
-        LintId::of(&bit_mask::VERBOSE_BIT_MASK),
-        LintId::of(&bytecount::NAIVE_BYTECOUNT),
-        LintId::of(&case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS),
-        LintId::of(&casts::CAST_LOSSLESS),
-        LintId::of(&casts::CAST_POSSIBLE_TRUNCATION),
-        LintId::of(&casts::CAST_POSSIBLE_WRAP),
-        LintId::of(&casts::CAST_PRECISION_LOSS),
-        LintId::of(&casts::CAST_PTR_ALIGNMENT),
-        LintId::of(&casts::CAST_SIGN_LOSS),
-        LintId::of(&casts::PTR_AS_PTR),
-        LintId::of(&checked_conversions::CHECKED_CONVERSIONS),
-        LintId::of(&copies::SAME_FUNCTIONS_IN_IF_CONDITION),
-        LintId::of(&copy_iterator::COPY_ITERATOR),
-        LintId::of(&default::DEFAULT_TRAIT_ACCESS),
-        LintId::of(&dereference::EXPLICIT_DEREF_METHODS),
-        LintId::of(&derive::EXPL_IMPL_CLONE_ON_COPY),
-        LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE),
-        LintId::of(&doc::DOC_MARKDOWN),
-        LintId::of(&doc::MISSING_ERRORS_DOC),
-        LintId::of(&doc::MISSING_PANICS_DOC),
-        LintId::of(&empty_enum::EMPTY_ENUM),
-        LintId::of(&enum_variants::MODULE_NAME_REPETITIONS),
-        LintId::of(&enum_variants::PUB_ENUM_VARIANT_NAMES),
-        LintId::of(&eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
-        LintId::of(&excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
-        LintId::of(&excessive_bools::STRUCT_EXCESSIVE_BOOLS),
-        LintId::of(&functions::MUST_USE_CANDIDATE),
-        LintId::of(&functions::TOO_MANY_LINES),
-        LintId::of(&if_not_else::IF_NOT_ELSE),
-        LintId::of(&implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
-        LintId::of(&infinite_iter::MAYBE_INFINITE_ITER),
-        LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS),
-        LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS),
-        LintId::of(&let_underscore::LET_UNDERSCORE_DROP),
-        LintId::of(&literal_representation::LARGE_DIGIT_GROUPS),
-        LintId::of(&literal_representation::UNREADABLE_LITERAL),
-        LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP),
-        LintId::of(&loops::EXPLICIT_ITER_LOOP),
-        LintId::of(&macro_use::MACRO_USE_IMPORTS),
-        LintId::of(&manual_ok_or::MANUAL_OK_OR),
-        LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
-        LintId::of(&matches::MATCH_BOOL),
-        LintId::of(&matches::MATCH_SAME_ARMS),
-        LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
-        LintId::of(&matches::MATCH_WILD_ERR_ARM),
-        LintId::of(&matches::SINGLE_MATCH_ELSE),
-        LintId::of(&methods::FILTER_MAP),
-        LintId::of(&methods::FILTER_MAP_NEXT),
-        LintId::of(&methods::IMPLICIT_CLONE),
-        LintId::of(&methods::INEFFICIENT_TO_STRING),
-        LintId::of(&methods::MAP_FLATTEN),
-        LintId::of(&methods::MAP_UNWRAP_OR),
-        LintId::of(&misc::USED_UNDERSCORE_BINDING),
-        LintId::of(&misc_early::UNSEPARATED_LITERAL_SUFFIX),
-        LintId::of(&mut_mut::MUT_MUT),
-        LintId::of(&needless_continue::NEEDLESS_CONTINUE),
-        LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
-        LintId::of(&non_expressive_names::SIMILAR_NAMES),
-        LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE),
-        LintId::of(&pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
-        LintId::of(&pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),
-        LintId::of(&ranges::RANGE_MINUS_ONE),
-        LintId::of(&ranges::RANGE_PLUS_ONE),
-        LintId::of(&redundant_else::REDUNDANT_ELSE),
-        LintId::of(&ref_option_ref::REF_OPTION_REF),
-        LintId::of(&shadow::SHADOW_UNRELATED),
-        LintId::of(&strings::STRING_ADD_ASSIGN),
-        LintId::of(&trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
-        LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS),
-        LintId::of(&types::IMPLICIT_HASHER),
-        LintId::of(&types::INVALID_UPCAST_COMPARISONS),
-        LintId::of(&types::LINKEDLIST),
-        LintId::of(&types::OPTION_OPTION),
-        LintId::of(&unicode::NON_ASCII_LITERAL),
-        LintId::of(&unicode::UNICODE_NOT_NFC),
-        LintId::of(&unit_types::LET_UNIT_VALUE),
-        LintId::of(&unnecessary_wraps::UNNECESSARY_WRAPS),
-        LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS),
-        LintId::of(&unused_self::UNUSED_SELF),
-        LintId::of(&wildcard_imports::ENUM_GLOB_USE),
-        LintId::of(&wildcard_imports::WILDCARD_IMPORTS),
-        LintId::of(&zero_sized_map_values::ZERO_SIZED_MAP_VALUES),
+        LintId::of(attrs::INLINE_ALWAYS),
+        LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
+        LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
+        LintId::of(bit_mask::VERBOSE_BIT_MASK),
+        LintId::of(bytecount::NAIVE_BYTECOUNT),
+        LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS),
+        LintId::of(casts::CAST_LOSSLESS),
+        LintId::of(casts::CAST_POSSIBLE_TRUNCATION),
+        LintId::of(casts::CAST_POSSIBLE_WRAP),
+        LintId::of(casts::CAST_PRECISION_LOSS),
+        LintId::of(casts::CAST_PTR_ALIGNMENT),
+        LintId::of(casts::CAST_SIGN_LOSS),
+        LintId::of(casts::PTR_AS_PTR),
+        LintId::of(checked_conversions::CHECKED_CONVERSIONS),
+        LintId::of(copies::SAME_FUNCTIONS_IN_IF_CONDITION),
+        LintId::of(copy_iterator::COPY_ITERATOR),
+        LintId::of(default::DEFAULT_TRAIT_ACCESS),
+        LintId::of(dereference::EXPLICIT_DEREF_METHODS),
+        LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY),
+        LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE),
+        LintId::of(doc::DOC_MARKDOWN),
+        LintId::of(doc::MISSING_ERRORS_DOC),
+        LintId::of(doc::MISSING_PANICS_DOC),
+        LintId::of(empty_enum::EMPTY_ENUM),
+        LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
+        LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES),
+        LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
+        LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
+        LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
+        LintId::of(functions::MUST_USE_CANDIDATE),
+        LintId::of(functions::TOO_MANY_LINES),
+        LintId::of(if_not_else::IF_NOT_ELSE),
+        LintId::of(implicit_hasher::IMPLICIT_HASHER),
+        LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
+        LintId::of(infinite_iter::MAYBE_INFINITE_ITER),
+        LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS),
+        LintId::of(items_after_statements::ITEMS_AFTER_STATEMENTS),
+        LintId::of(large_stack_arrays::LARGE_STACK_ARRAYS),
+        LintId::of(let_underscore::LET_UNDERSCORE_DROP),
+        LintId::of(literal_representation::LARGE_DIGIT_GROUPS),
+        LintId::of(literal_representation::UNREADABLE_LITERAL),
+        LintId::of(loops::EXPLICIT_INTO_ITER_LOOP),
+        LintId::of(loops::EXPLICIT_ITER_LOOP),
+        LintId::of(macro_use::MACRO_USE_IMPORTS),
+        LintId::of(manual_ok_or::MANUAL_OK_OR),
+        LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS),
+        LintId::of(matches::MATCH_BOOL),
+        LintId::of(matches::MATCH_SAME_ARMS),
+        LintId::of(matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
+        LintId::of(matches::MATCH_WILD_ERR_ARM),
+        LintId::of(matches::SINGLE_MATCH_ELSE),
+        LintId::of(methods::FILTER_MAP),
+        LintId::of(methods::FILTER_MAP_NEXT),
+        LintId::of(methods::IMPLICIT_CLONE),
+        LintId::of(methods::INEFFICIENT_TO_STRING),
+        LintId::of(methods::MAP_FLATTEN),
+        LintId::of(methods::MAP_UNWRAP_OR),
+        LintId::of(misc::USED_UNDERSCORE_BINDING),
+        LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
+        LintId::of(mut_mut::MUT_MUT),
+        LintId::of(needless_continue::NEEDLESS_CONTINUE),
+        LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
+        LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
+        LintId::of(non_expressive_names::SIMILAR_NAMES),
+        LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
+        LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
+        LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),
+        LintId::of(ranges::RANGE_MINUS_ONE),
+        LintId::of(ranges::RANGE_PLUS_ONE),
+        LintId::of(redundant_else::REDUNDANT_ELSE),
+        LintId::of(ref_option_ref::REF_OPTION_REF),
+        LintId::of(shadow::SHADOW_UNRELATED),
+        LintId::of(strings::STRING_ADD_ASSIGN),
+        LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
+        LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
+        LintId::of(types::LINKEDLIST),
+        LintId::of(types::OPTION_OPTION),
+        LintId::of(unicode::NON_ASCII_LITERAL),
+        LintId::of(unicode::UNICODE_NOT_NFC),
+        LintId::of(unit_types::LET_UNIT_VALUE),
+        LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS),
+        LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS),
+        LintId::of(unused_self::UNUSED_SELF),
+        LintId::of(wildcard_imports::ENUM_GLOB_USE),
+        LintId::of(wildcard_imports::WILDCARD_IMPORTS),
+        LintId::of(zero_sized_map_values::ZERO_SIZED_MAP_VALUES),
     ]);
 
     #[cfg(feature = "internal-lints")]
     store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
-        LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL),
-        LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
-        LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS),
-        LintId::of(&utils::internal_lints::DEFAULT_LINT),
-        LintId::of(&utils::internal_lints::INTERNING_DEFINED_SYMBOL),
-        LintId::of(&utils::internal_lints::INVALID_PATHS),
-        LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS),
-        LintId::of(&utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM),
-        LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA),
-        LintId::of(&utils::internal_lints::PRODUCE_ICE),
-        LintId::of(&utils::internal_lints::UNNECESSARY_SYMBOL_STR),
+        LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL),
+        LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
+        LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS),
+        LintId::of(utils::internal_lints::DEFAULT_LINT),
+        LintId::of(utils::internal_lints::IF_CHAIN_STYLE),
+        LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL),
+        LintId::of(utils::internal_lints::INVALID_PATHS),
+        LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS),
+        LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM),
+        LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA),
+        LintId::of(utils::internal_lints::PRODUCE_ICE),
+        LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR),
     ]);
 
     store.register_group(true, "clippy::all", Some("clippy"), vec![
-        LintId::of(&approx_const::APPROX_CONSTANT),
-        LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
-        LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
-        LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
-        LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC),
-        LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
-        LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
-        LintId::of(&attrs::DEPRECATED_CFG_ATTR),
-        LintId::of(&attrs::DEPRECATED_SEMVER),
-        LintId::of(&attrs::MISMATCHED_TARGET_OS),
-        LintId::of(&attrs::USELESS_ATTRIBUTE),
-        LintId::of(&bit_mask::BAD_BIT_MASK),
-        LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
-        LintId::of(&blacklisted_name::BLACKLISTED_NAME),
-        LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
-        LintId::of(&booleans::LOGIC_BUG),
-        LintId::of(&booleans::NONMINIMAL_BOOL),
-        LintId::of(&casts::CAST_REF_TO_MUT),
-        LintId::of(&casts::CHAR_LIT_AS_U8),
-        LintId::of(&casts::FN_TO_NUMERIC_CAST),
-        LintId::of(&casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
-        LintId::of(&casts::UNNECESSARY_CAST),
-        LintId::of(&collapsible_if::COLLAPSIBLE_ELSE_IF),
-        LintId::of(&collapsible_if::COLLAPSIBLE_IF),
-        LintId::of(&collapsible_match::COLLAPSIBLE_MATCH),
-        LintId::of(&comparison_chain::COMPARISON_CHAIN),
-        LintId::of(&copies::IFS_SAME_COND),
-        LintId::of(&copies::IF_SAME_THEN_ELSE),
-        LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT),
-        LintId::of(&derive::DERIVE_HASH_XOR_EQ),
-        LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD),
-        LintId::of(&doc::MISSING_SAFETY_DOC),
-        LintId::of(&doc::NEEDLESS_DOCTEST_MAIN),
-        LintId::of(&double_comparison::DOUBLE_COMPARISONS),
-        LintId::of(&double_parens::DOUBLE_PARENS),
-        LintId::of(&drop_forget_ref::DROP_COPY),
-        LintId::of(&drop_forget_ref::DROP_REF),
-        LintId::of(&drop_forget_ref::FORGET_COPY),
-        LintId::of(&drop_forget_ref::FORGET_REF),
-        LintId::of(&duration_subsec::DURATION_SUBSEC),
-        LintId::of(&entry::MAP_ENTRY),
-        LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
-        LintId::of(&enum_variants::ENUM_VARIANT_NAMES),
-        LintId::of(&enum_variants::MODULE_INCEPTION),
-        LintId::of(&eq_op::EQ_OP),
-        LintId::of(&eq_op::OP_REF),
-        LintId::of(&erasing_op::ERASING_OP),
-        LintId::of(&escape::BOXED_LOCAL),
-        LintId::of(&eta_reduction::REDUNDANT_CLOSURE),
-        LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION),
-        LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
-        LintId::of(&explicit_write::EXPLICIT_WRITE),
-        LintId::of(&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
-        LintId::of(&float_literal::EXCESSIVE_PRECISION),
-        LintId::of(&format::USELESS_FORMAT),
-        LintId::of(&formatting::POSSIBLE_MISSING_COMMA),
-        LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
-        LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
-        LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
-        LintId::of(&from_over_into::FROM_OVER_INTO),
-        LintId::of(&from_str_radix_10::FROM_STR_RADIX_10),
-        LintId::of(&functions::DOUBLE_MUST_USE),
-        LintId::of(&functions::MUST_USE_UNIT),
-        LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF),
-        LintId::of(&functions::RESULT_UNIT_ERR),
-        LintId::of(&functions::TOO_MANY_ARGUMENTS),
-        LintId::of(&get_last_with_len::GET_LAST_WITH_LEN),
-        LintId::of(&identity_op::IDENTITY_OP),
-        LintId::of(&if_let_mutex::IF_LET_MUTEX),
-        LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
-        LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
-        LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING),
-        LintId::of(&infinite_iter::INFINITE_ITER),
-        LintId::of(&inherent_to_string::INHERENT_TO_STRING),
-        LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
-        LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
-        LintId::of(&int_plus_one::INT_PLUS_ONE),
-        LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
-        LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
-        LintId::of(&len_zero::COMPARISON_TO_EMPTY),
-        LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
-        LintId::of(&len_zero::LEN_ZERO),
-        LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
-        LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
-        LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
-        LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
-        LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
-        LintId::of(&literal_representation::UNUSUAL_BYTE_GROUPINGS),
-        LintId::of(&loops::EMPTY_LOOP),
-        LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
-        LintId::of(&loops::FOR_KV_MAP),
-        LintId::of(&loops::FOR_LOOPS_OVER_FALLIBLES),
-        LintId::of(&loops::ITER_NEXT_LOOP),
-        LintId::of(&loops::MANUAL_FLATTEN),
-        LintId::of(&loops::MANUAL_MEMCPY),
-        LintId::of(&loops::MUT_RANGE_BOUND),
-        LintId::of(&loops::NEEDLESS_COLLECT),
-        LintId::of(&loops::NEEDLESS_RANGE_LOOP),
-        LintId::of(&loops::NEVER_LOOP),
-        LintId::of(&loops::SAME_ITEM_PUSH),
-        LintId::of(&loops::SINGLE_ELEMENT_LOOP),
-        LintId::of(&loops::WHILE_IMMUTABLE_CONDITION),
-        LintId::of(&loops::WHILE_LET_LOOP),
-        LintId::of(&loops::WHILE_LET_ON_ITERATOR),
-        LintId::of(&main_recursion::MAIN_RECURSION),
-        LintId::of(&manual_async_fn::MANUAL_ASYNC_FN),
-        LintId::of(&manual_map::MANUAL_MAP),
-        LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
-        LintId::of(&manual_strip::MANUAL_STRIP),
-        LintId::of(&manual_unwrap_or::MANUAL_UNWRAP_OR),
-        LintId::of(&map_clone::MAP_CLONE),
-        LintId::of(&map_identity::MAP_IDENTITY),
-        LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
-        LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
-        LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
-        LintId::of(&matches::MATCH_AS_REF),
-        LintId::of(&matches::MATCH_LIKE_MATCHES_MACRO),
-        LintId::of(&matches::MATCH_OVERLAPPING_ARM),
-        LintId::of(&matches::MATCH_REF_PATS),
-        LintId::of(&matches::MATCH_SINGLE_BINDING),
-        LintId::of(&matches::REDUNDANT_PATTERN_MATCHING),
-        LintId::of(&matches::SINGLE_MATCH),
-        LintId::of(&matches::WILDCARD_IN_OR_PATTERNS),
-        LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
-        LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
-        LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
-        LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT),
-        LintId::of(&methods::BIND_INSTEAD_OF_MAP),
-        LintId::of(&methods::BYTES_NTH),
-        LintId::of(&methods::CHARS_LAST_CMP),
-        LintId::of(&methods::CHARS_NEXT_CMP),
-        LintId::of(&methods::CLONE_DOUBLE_REF),
-        LintId::of(&methods::CLONE_ON_COPY),
-        LintId::of(&methods::EXPECT_FUN_CALL),
-        LintId::of(&methods::FILTER_MAP_IDENTITY),
-        LintId::of(&methods::FILTER_NEXT),
-        LintId::of(&methods::FLAT_MAP_IDENTITY),
-        LintId::of(&methods::FROM_ITER_INSTEAD_OF_COLLECT),
-        LintId::of(&methods::INSPECT_FOR_EACH),
-        LintId::of(&methods::INTO_ITER_ON_REF),
-        LintId::of(&methods::ITERATOR_STEP_BY_ZERO),
-        LintId::of(&methods::ITER_CLONED_COLLECT),
-        LintId::of(&methods::ITER_COUNT),
-        LintId::of(&methods::ITER_NEXT_SLICE),
-        LintId::of(&methods::ITER_NTH),
-        LintId::of(&methods::ITER_NTH_ZERO),
-        LintId::of(&methods::ITER_SKIP_NEXT),
-        LintId::of(&methods::MANUAL_FILTER_MAP),
-        LintId::of(&methods::MANUAL_FIND_MAP),
-        LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
-        LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
-        LintId::of(&methods::NEW_RET_NO_SELF),
-        LintId::of(&methods::OK_EXPECT),
-        LintId::of(&methods::OPTION_AS_REF_DEREF),
-        LintId::of(&methods::OPTION_MAP_OR_NONE),
-        LintId::of(&methods::OR_FUN_CALL),
-        LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION),
-        LintId::of(&methods::SEARCH_IS_SOME),
-        LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
-        LintId::of(&methods::SINGLE_CHAR_ADD_STR),
-        LintId::of(&methods::SINGLE_CHAR_PATTERN),
-        LintId::of(&methods::SKIP_WHILE_NEXT),
-        LintId::of(&methods::STRING_EXTEND_CHARS),
-        LintId::of(&methods::SUSPICIOUS_MAP),
-        LintId::of(&methods::UNINIT_ASSUMED_INIT),
-        LintId::of(&methods::UNNECESSARY_FILTER_MAP),
-        LintId::of(&methods::UNNECESSARY_FOLD),
-        LintId::of(&methods::UNNECESSARY_LAZY_EVALUATIONS),
-        LintId::of(&methods::USELESS_ASREF),
-        LintId::of(&methods::WRONG_SELF_CONVENTION),
-        LintId::of(&methods::ZST_OFFSET),
-        LintId::of(&minmax::MIN_MAX),
-        LintId::of(&misc::CMP_NAN),
-        LintId::of(&misc::CMP_OWNED),
-        LintId::of(&misc::FLOAT_CMP),
-        LintId::of(&misc::MODULO_ONE),
-        LintId::of(&misc::SHORT_CIRCUIT_STATEMENT),
-        LintId::of(&misc::TOPLEVEL_REF_ARG),
-        LintId::of(&misc::ZERO_PTR),
-        LintId::of(&misc_early::BUILTIN_TYPE_SHADOW),
-        LintId::of(&misc_early::DOUBLE_NEG),
-        LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
-        LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS),
-        LintId::of(&misc_early::REDUNDANT_PATTERN),
-        LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN),
-        LintId::of(&misc_early::ZERO_PREFIXED_LITERAL),
-        LintId::of(&mut_key::MUTABLE_KEY_TYPE),
-        LintId::of(&mut_mutex_lock::MUT_MUTEX_LOCK),
-        LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED),
-        LintId::of(&mutex_atomic::MUTEX_ATOMIC),
-        LintId::of(&needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
-        LintId::of(&needless_bool::BOOL_COMPARISON),
-        LintId::of(&needless_bool::NEEDLESS_BOOL),
-        LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
-        LintId::of(&needless_question_mark::NEEDLESS_QUESTION_MARK),
-        LintId::of(&needless_update::NEEDLESS_UPDATE),
-        LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
-        LintId::of(&neg_multiply::NEG_MULTIPLY),
-        LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT),
-        LintId::of(&no_effect::NO_EFFECT),
-        LintId::of(&no_effect::UNNECESSARY_OPERATION),
-        LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
-        LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
-        LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
-        LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES),
-        LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS),
-        LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP),
-        LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
-        LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
-        LintId::of(&precedence::PRECEDENCE),
-        LintId::of(&ptr::CMP_NULL),
-        LintId::of(&ptr::MUT_FROM_REF),
-        LintId::of(&ptr::PTR_ARG),
-        LintId::of(&ptr_eq::PTR_EQ),
-        LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
-        LintId::of(&question_mark::QUESTION_MARK),
-        LintId::of(&ranges::MANUAL_RANGE_CONTAINS),
-        LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
-        LintId::of(&ranges::REVERSED_EMPTY_RANGES),
-        LintId::of(&redundant_clone::REDUNDANT_CLONE),
-        LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL),
-        LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
-        LintId::of(&redundant_slicing::REDUNDANT_SLICING),
-        LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
-        LintId::of(&reference::DEREF_ADDROF),
-        LintId::of(&reference::REF_IN_DEREF),
-        LintId::of(&regex::INVALID_REGEX),
-        LintId::of(&repeat_once::REPEAT_ONCE),
-        LintId::of(&returns::LET_AND_RETURN),
-        LintId::of(&returns::NEEDLESS_RETURN),
-        LintId::of(&self_assignment::SELF_ASSIGNMENT),
-        LintId::of(&serde_api::SERDE_API_MISUSE),
-        LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
-        LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
-        LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
-        LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE),
-        LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
-        LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
-        LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
-        LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
-        LintId::of(&swap::ALMOST_SWAPPED),
-        LintId::of(&swap::MANUAL_SWAP),
-        LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
-        LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT),
-        LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
-        LintId::of(&to_string_in_display::TO_STRING_IN_DISPLAY),
-        LintId::of(&transmute::CROSSPOINTER_TRANSMUTE),
-        LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
-        LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR),
-        LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT),
-        LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL),
-        LintId::of(&transmute::TRANSMUTE_INT_TO_CHAR),
-        LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT),
-        LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR),
-        LintId::of(&transmute::TRANSMUTE_PTR_TO_REF),
-        LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE),
-        LintId::of(&transmute::WRONG_TRANSMUTE),
-        LintId::of(&transmuting_null::TRANSMUTING_NULL),
-        LintId::of(&try_err::TRY_ERR),
-        LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
-        LintId::of(&types::BORROWED_BOX),
-        LintId::of(&types::BOX_VEC),
-        LintId::of(&types::REDUNDANT_ALLOCATION),
-        LintId::of(&types::TYPE_COMPLEXITY),
-        LintId::of(&types::VEC_BOX),
-        LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
-        LintId::of(&unicode::INVISIBLE_CHARACTERS),
-        LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
-        LintId::of(&unit_types::UNIT_ARG),
-        LintId::of(&unit_types::UNIT_CMP),
-        LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
-        LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
-        LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
-        LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
-        LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
-        LintId::of(&unused_unit::UNUSED_UNIT),
-        LintId::of(&unwrap::PANICKING_UNWRAP),
-        LintId::of(&unwrap::UNNECESSARY_UNWRAP),
-        LintId::of(&upper_case_acronyms::UPPER_CASE_ACRONYMS),
-        LintId::of(&useless_conversion::USELESS_CONVERSION),
-        LintId::of(&vec::USELESS_VEC),
-        LintId::of(&vec_init_then_push::VEC_INIT_THEN_PUSH),
-        LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
-        LintId::of(&write::PRINTLN_EMPTY_STRING),
-        LintId::of(&write::PRINT_LITERAL),
-        LintId::of(&write::PRINT_WITH_NEWLINE),
-        LintId::of(&write::WRITELN_EMPTY_STRING),
-        LintId::of(&write::WRITE_LITERAL),
-        LintId::of(&write::WRITE_WITH_NEWLINE),
-        LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO),
+        LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS),
+        LintId::of(approx_const::APPROX_CONSTANT),
+        LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
+        LintId::of(assign_ops::ASSIGN_OP_PATTERN),
+        LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
+        LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
+        LintId::of(atomic_ordering::INVALID_ATOMIC_ORDERING),
+        LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
+        LintId::of(attrs::DEPRECATED_CFG_ATTR),
+        LintId::of(attrs::DEPRECATED_SEMVER),
+        LintId::of(attrs::MISMATCHED_TARGET_OS),
+        LintId::of(attrs::USELESS_ATTRIBUTE),
+        LintId::of(bit_mask::BAD_BIT_MASK),
+        LintId::of(bit_mask::INEFFECTIVE_BIT_MASK),
+        LintId::of(blacklisted_name::BLACKLISTED_NAME),
+        LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
+        LintId::of(booleans::LOGIC_BUG),
+        LintId::of(booleans::NONMINIMAL_BOOL),
+        LintId::of(casts::CAST_REF_TO_MUT),
+        LintId::of(casts::CHAR_LIT_AS_U8),
+        LintId::of(casts::FN_TO_NUMERIC_CAST),
+        LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
+        LintId::of(casts::UNNECESSARY_CAST),
+        LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF),
+        LintId::of(collapsible_if::COLLAPSIBLE_IF),
+        LintId::of(collapsible_match::COLLAPSIBLE_MATCH),
+        LintId::of(comparison_chain::COMPARISON_CHAIN),
+        LintId::of(copies::BRANCHES_SHARING_CODE),
+        LintId::of(copies::IFS_SAME_COND),
+        LintId::of(copies::IF_SAME_THEN_ELSE),
+        LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
+        LintId::of(derive::DERIVE_HASH_XOR_EQ),
+        LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
+        LintId::of(doc::MISSING_SAFETY_DOC),
+        LintId::of(doc::NEEDLESS_DOCTEST_MAIN),
+        LintId::of(double_comparison::DOUBLE_COMPARISONS),
+        LintId::of(double_parens::DOUBLE_PARENS),
+        LintId::of(drop_forget_ref::DROP_COPY),
+        LintId::of(drop_forget_ref::DROP_REF),
+        LintId::of(drop_forget_ref::FORGET_COPY),
+        LintId::of(drop_forget_ref::FORGET_REF),
+        LintId::of(duration_subsec::DURATION_SUBSEC),
+        LintId::of(entry::MAP_ENTRY),
+        LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
+        LintId::of(enum_variants::ENUM_VARIANT_NAMES),
+        LintId::of(enum_variants::MODULE_INCEPTION),
+        LintId::of(eq_op::EQ_OP),
+        LintId::of(eq_op::OP_REF),
+        LintId::of(erasing_op::ERASING_OP),
+        LintId::of(escape::BOXED_LOCAL),
+        LintId::of(eta_reduction::REDUNDANT_CLOSURE),
+        LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION),
+        LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
+        LintId::of(explicit_write::EXPLICIT_WRITE),
+        LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
+        LintId::of(float_literal::EXCESSIVE_PRECISION),
+        LintId::of(format::USELESS_FORMAT),
+        LintId::of(formatting::POSSIBLE_MISSING_COMMA),
+        LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
+        LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
+        LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(from_over_into::FROM_OVER_INTO),
+        LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
+        LintId::of(functions::DOUBLE_MUST_USE),
+        LintId::of(functions::MUST_USE_UNIT),
+        LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
+        LintId::of(functions::RESULT_UNIT_ERR),
+        LintId::of(functions::TOO_MANY_ARGUMENTS),
+        LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
+        LintId::of(identity_op::IDENTITY_OP),
+        LintId::of(if_let_mutex::IF_LET_MUTEX),
+        LintId::of(if_let_some_result::IF_LET_SOME_RESULT),
+        LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
+        LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
+        LintId::of(infinite_iter::INFINITE_ITER),
+        LintId::of(inherent_to_string::INHERENT_TO_STRING),
+        LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
+        LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
+        LintId::of(int_plus_one::INT_PLUS_ONE),
+        LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
+        LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
+        LintId::of(len_zero::COMPARISON_TO_EMPTY),
+        LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
+        LintId::of(len_zero::LEN_ZERO),
+        LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
+        LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
+        LintId::of(lifetimes::NEEDLESS_LIFETIMES),
+        LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
+        LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
+        LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
+        LintId::of(loops::EMPTY_LOOP),
+        LintId::of(loops::EXPLICIT_COUNTER_LOOP),
+        LintId::of(loops::FOR_KV_MAP),
+        LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
+        LintId::of(loops::ITER_NEXT_LOOP),
+        LintId::of(loops::MANUAL_FLATTEN),
+        LintId::of(loops::MANUAL_MEMCPY),
+        LintId::of(loops::MUT_RANGE_BOUND),
+        LintId::of(loops::NEEDLESS_COLLECT),
+        LintId::of(loops::NEEDLESS_RANGE_LOOP),
+        LintId::of(loops::NEVER_LOOP),
+        LintId::of(loops::SAME_ITEM_PUSH),
+        LintId::of(loops::SINGLE_ELEMENT_LOOP),
+        LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
+        LintId::of(loops::WHILE_LET_LOOP),
+        LintId::of(loops::WHILE_LET_ON_ITERATOR),
+        LintId::of(main_recursion::MAIN_RECURSION),
+        LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
+        LintId::of(manual_map::MANUAL_MAP),
+        LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
+        LintId::of(manual_strip::MANUAL_STRIP),
+        LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR),
+        LintId::of(map_clone::MAP_CLONE),
+        LintId::of(map_identity::MAP_IDENTITY),
+        LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
+        LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
+        LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
+        LintId::of(matches::MATCH_AS_REF),
+        LintId::of(matches::MATCH_LIKE_MATCHES_MACRO),
+        LintId::of(matches::MATCH_OVERLAPPING_ARM),
+        LintId::of(matches::MATCH_REF_PATS),
+        LintId::of(matches::MATCH_SINGLE_BINDING),
+        LintId::of(matches::REDUNDANT_PATTERN_MATCHING),
+        LintId::of(matches::SINGLE_MATCH),
+        LintId::of(matches::WILDCARD_IN_OR_PATTERNS),
+        LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
+        LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
+        LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT),
+        LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
+        LintId::of(methods::BIND_INSTEAD_OF_MAP),
+        LintId::of(methods::BYTES_NTH),
+        LintId::of(methods::CHARS_LAST_CMP),
+        LintId::of(methods::CHARS_NEXT_CMP),
+        LintId::of(methods::CLONE_DOUBLE_REF),
+        LintId::of(methods::CLONE_ON_COPY),
+        LintId::of(methods::EXPECT_FUN_CALL),
+        LintId::of(methods::FILTER_MAP_IDENTITY),
+        LintId::of(methods::FILTER_NEXT),
+        LintId::of(methods::FLAT_MAP_IDENTITY),
+        LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
+        LintId::of(methods::INSPECT_FOR_EACH),
+        LintId::of(methods::INTO_ITER_ON_REF),
+        LintId::of(methods::ITERATOR_STEP_BY_ZERO),
+        LintId::of(methods::ITER_CLONED_COLLECT),
+        LintId::of(methods::ITER_COUNT),
+        LintId::of(methods::ITER_NEXT_SLICE),
+        LintId::of(methods::ITER_NTH),
+        LintId::of(methods::ITER_NTH_ZERO),
+        LintId::of(methods::ITER_SKIP_NEXT),
+        LintId::of(methods::MANUAL_FILTER_MAP),
+        LintId::of(methods::MANUAL_FIND_MAP),
+        LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
+        LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
+        LintId::of(methods::NEW_RET_NO_SELF),
+        LintId::of(methods::OK_EXPECT),
+        LintId::of(methods::OPTION_AS_REF_DEREF),
+        LintId::of(methods::OPTION_FILTER_MAP),
+        LintId::of(methods::OPTION_MAP_OR_NONE),
+        LintId::of(methods::OR_FUN_CALL),
+        LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
+        LintId::of(methods::SEARCH_IS_SOME),
+        LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
+        LintId::of(methods::SINGLE_CHAR_ADD_STR),
+        LintId::of(methods::SINGLE_CHAR_PATTERN),
+        LintId::of(methods::SKIP_WHILE_NEXT),
+        LintId::of(methods::STRING_EXTEND_CHARS),
+        LintId::of(methods::SUSPICIOUS_MAP),
+        LintId::of(methods::UNINIT_ASSUMED_INIT),
+        LintId::of(methods::UNNECESSARY_FILTER_MAP),
+        LintId::of(methods::UNNECESSARY_FOLD),
+        LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
+        LintId::of(methods::USELESS_ASREF),
+        LintId::of(methods::WRONG_SELF_CONVENTION),
+        LintId::of(methods::ZST_OFFSET),
+        LintId::of(minmax::MIN_MAX),
+        LintId::of(misc::CMP_NAN),
+        LintId::of(misc::CMP_OWNED),
+        LintId::of(misc::FLOAT_CMP),
+        LintId::of(misc::MODULO_ONE),
+        LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
+        LintId::of(misc::TOPLEVEL_REF_ARG),
+        LintId::of(misc::ZERO_PTR),
+        LintId::of(misc_early::BUILTIN_TYPE_SHADOW),
+        LintId::of(misc_early::DOUBLE_NEG),
+        LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
+        LintId::of(misc_early::MIXED_CASE_HEX_LITERALS),
+        LintId::of(misc_early::REDUNDANT_PATTERN),
+        LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN),
+        LintId::of(misc_early::ZERO_PREFIXED_LITERAL),
+        LintId::of(mut_key::MUTABLE_KEY_TYPE),
+        LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
+        LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
+        LintId::of(mutex_atomic::MUTEX_ATOMIC),
+        LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
+        LintId::of(needless_bool::BOOL_COMPARISON),
+        LintId::of(needless_bool::NEEDLESS_BOOL),
+        LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
+        LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
+        LintId::of(needless_update::NEEDLESS_UPDATE),
+        LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
+        LintId::of(neg_multiply::NEG_MULTIPLY),
+        LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
+        LintId::of(no_effect::NO_EFFECT),
+        LintId::of(no_effect::UNNECESSARY_OPERATION),
+        LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
+        LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
+        LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
+        LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
+        LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
+        LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
+        LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
+        LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
+        LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
+        LintId::of(precedence::PRECEDENCE),
+        LintId::of(ptr::CMP_NULL),
+        LintId::of(ptr::MUT_FROM_REF),
+        LintId::of(ptr::PTR_ARG),
+        LintId::of(ptr_eq::PTR_EQ),
+        LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
+        LintId::of(question_mark::QUESTION_MARK),
+        LintId::of(ranges::MANUAL_RANGE_CONTAINS),
+        LintId::of(ranges::RANGE_ZIP_WITH_LEN),
+        LintId::of(ranges::REVERSED_EMPTY_RANGES),
+        LintId::of(redundant_clone::REDUNDANT_CLONE),
+        LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
+        LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
+        LintId::of(redundant_slicing::REDUNDANT_SLICING),
+        LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
+        LintId::of(reference::DEREF_ADDROF),
+        LintId::of(reference::REF_IN_DEREF),
+        LintId::of(regex::INVALID_REGEX),
+        LintId::of(repeat_once::REPEAT_ONCE),
+        LintId::of(returns::LET_AND_RETURN),
+        LintId::of(returns::NEEDLESS_RETURN),
+        LintId::of(self_assignment::SELF_ASSIGNMENT),
+        LintId::of(serde_api::SERDE_API_MISUSE),
+        LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
+        LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
+        LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
+        LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
+        LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
+        LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
+        LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
+        LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
+        LintId::of(swap::ALMOST_SWAPPED),
+        LintId::of(swap::MANUAL_SWAP),
+        LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
+        LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
+        LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
+        LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY),
+        LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
+        LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
+        LintId::of(transmute::TRANSMUTE_BYTES_TO_STR),
+        LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT),
+        LintId::of(transmute::TRANSMUTE_INT_TO_BOOL),
+        LintId::of(transmute::TRANSMUTE_INT_TO_CHAR),
+        LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
+        LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
+        LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
+        LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
+        LintId::of(transmute::WRONG_TRANSMUTE),
+        LintId::of(transmuting_null::TRANSMUTING_NULL),
+        LintId::of(try_err::TRY_ERR),
+        LintId::of(types::BORROWED_BOX),
+        LintId::of(types::BOX_VEC),
+        LintId::of(types::REDUNDANT_ALLOCATION),
+        LintId::of(types::TYPE_COMPLEXITY),
+        LintId::of(types::VEC_BOX),
+        LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
+        LintId::of(unicode::INVISIBLE_CHARACTERS),
+        LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
+        LintId::of(unit_types::UNIT_ARG),
+        LintId::of(unit_types::UNIT_CMP),
+        LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
+        LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
+        LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY),
+        LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
+        LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
+        LintId::of(unused_unit::UNUSED_UNIT),
+        LintId::of(unwrap::PANICKING_UNWRAP),
+        LintId::of(unwrap::UNNECESSARY_UNWRAP),
+        LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
+        LintId::of(useless_conversion::USELESS_CONVERSION),
+        LintId::of(vec::USELESS_VEC),
+        LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
+        LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
+        LintId::of(write::PRINTLN_EMPTY_STRING),
+        LintId::of(write::PRINT_LITERAL),
+        LintId::of(write::PRINT_WITH_NEWLINE),
+        LintId::of(write::WRITELN_EMPTY_STRING),
+        LintId::of(write::WRITE_LITERAL),
+        LintId::of(write::WRITE_WITH_NEWLINE),
+        LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO),
     ]);
 
     store.register_group(true, "clippy::style", Some("clippy_style"), vec![
-        LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
-        LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
-        LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
-        LintId::of(&blacklisted_name::BLACKLISTED_NAME),
-        LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
-        LintId::of(&casts::FN_TO_NUMERIC_CAST),
-        LintId::of(&casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
-        LintId::of(&collapsible_if::COLLAPSIBLE_ELSE_IF),
-        LintId::of(&collapsible_if::COLLAPSIBLE_IF),
-        LintId::of(&collapsible_match::COLLAPSIBLE_MATCH),
-        LintId::of(&comparison_chain::COMPARISON_CHAIN),
-        LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT),
-        LintId::of(&doc::MISSING_SAFETY_DOC),
-        LintId::of(&doc::NEEDLESS_DOCTEST_MAIN),
-        LintId::of(&enum_variants::ENUM_VARIANT_NAMES),
-        LintId::of(&enum_variants::MODULE_INCEPTION),
-        LintId::of(&eq_op::OP_REF),
-        LintId::of(&eta_reduction::REDUNDANT_CLOSURE),
-        LintId::of(&float_literal::EXCESSIVE_PRECISION),
-        LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
-        LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
-        LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
-        LintId::of(&from_over_into::FROM_OVER_INTO),
-        LintId::of(&from_str_radix_10::FROM_STR_RADIX_10),
-        LintId::of(&functions::DOUBLE_MUST_USE),
-        LintId::of(&functions::MUST_USE_UNIT),
-        LintId::of(&functions::RESULT_UNIT_ERR),
-        LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
-        LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
-        LintId::of(&inherent_to_string::INHERENT_TO_STRING),
-        LintId::of(&len_zero::COMPARISON_TO_EMPTY),
-        LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
-        LintId::of(&len_zero::LEN_ZERO),
-        LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
-        LintId::of(&literal_representation::UNUSUAL_BYTE_GROUPINGS),
-        LintId::of(&loops::EMPTY_LOOP),
-        LintId::of(&loops::FOR_KV_MAP),
-        LintId::of(&loops::NEEDLESS_RANGE_LOOP),
-        LintId::of(&loops::SAME_ITEM_PUSH),
-        LintId::of(&loops::WHILE_LET_ON_ITERATOR),
-        LintId::of(&main_recursion::MAIN_RECURSION),
-        LintId::of(&manual_async_fn::MANUAL_ASYNC_FN),
-        LintId::of(&manual_map::MANUAL_MAP),
-        LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
-        LintId::of(&map_clone::MAP_CLONE),
-        LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
-        LintId::of(&matches::MATCH_LIKE_MATCHES_MACRO),
-        LintId::of(&matches::MATCH_OVERLAPPING_ARM),
-        LintId::of(&matches::MATCH_REF_PATS),
-        LintId::of(&matches::REDUNDANT_PATTERN_MATCHING),
-        LintId::of(&matches::SINGLE_MATCH),
-        LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
-        LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
-        LintId::of(&methods::BYTES_NTH),
-        LintId::of(&methods::CHARS_LAST_CMP),
-        LintId::of(&methods::CHARS_NEXT_CMP),
-        LintId::of(&methods::FROM_ITER_INSTEAD_OF_COLLECT),
-        LintId::of(&methods::INTO_ITER_ON_REF),
-        LintId::of(&methods::ITER_CLONED_COLLECT),
-        LintId::of(&methods::ITER_NEXT_SLICE),
-        LintId::of(&methods::ITER_NTH_ZERO),
-        LintId::of(&methods::ITER_SKIP_NEXT),
-        LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
-        LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
-        LintId::of(&methods::NEW_RET_NO_SELF),
-        LintId::of(&methods::OK_EXPECT),
-        LintId::of(&methods::OPTION_MAP_OR_NONE),
-        LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION),
-        LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
-        LintId::of(&methods::SINGLE_CHAR_ADD_STR),
-        LintId::of(&methods::STRING_EXTEND_CHARS),
-        LintId::of(&methods::UNNECESSARY_FOLD),
-        LintId::of(&methods::UNNECESSARY_LAZY_EVALUATIONS),
-        LintId::of(&methods::WRONG_SELF_CONVENTION),
-        LintId::of(&misc::TOPLEVEL_REF_ARG),
-        LintId::of(&misc::ZERO_PTR),
-        LintId::of(&misc_early::BUILTIN_TYPE_SHADOW),
-        LintId::of(&misc_early::DOUBLE_NEG),
-        LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
-        LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS),
-        LintId::of(&misc_early::REDUNDANT_PATTERN),
-        LintId::of(&mut_mutex_lock::MUT_MUTEX_LOCK),
-        LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED),
-        LintId::of(&neg_multiply::NEG_MULTIPLY),
-        LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT),
-        LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
-        LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
-        LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
-        LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES),
-        LintId::of(&ptr::CMP_NULL),
-        LintId::of(&ptr::PTR_ARG),
-        LintId::of(&ptr_eq::PTR_EQ),
-        LintId::of(&question_mark::QUESTION_MARK),
-        LintId::of(&ranges::MANUAL_RANGE_CONTAINS),
-        LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
-        LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
-        LintId::of(&returns::LET_AND_RETURN),
-        LintId::of(&returns::NEEDLESS_RETURN),
-        LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
-        LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
-        LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
-        LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
-        LintId::of(&try_err::TRY_ERR),
-        LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
-        LintId::of(&unused_unit::UNUSED_UNIT),
-        LintId::of(&upper_case_acronyms::UPPER_CASE_ACRONYMS),
-        LintId::of(&write::PRINTLN_EMPTY_STRING),
-        LintId::of(&write::PRINT_LITERAL),
-        LintId::of(&write::PRINT_WITH_NEWLINE),
-        LintId::of(&write::WRITELN_EMPTY_STRING),
-        LintId::of(&write::WRITE_LITERAL),
-        LintId::of(&write::WRITE_WITH_NEWLINE),
+        LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
+        LintId::of(assign_ops::ASSIGN_OP_PATTERN),
+        LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
+        LintId::of(blacklisted_name::BLACKLISTED_NAME),
+        LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
+        LintId::of(casts::FN_TO_NUMERIC_CAST),
+        LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
+        LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF),
+        LintId::of(collapsible_if::COLLAPSIBLE_IF),
+        LintId::of(collapsible_match::COLLAPSIBLE_MATCH),
+        LintId::of(comparison_chain::COMPARISON_CHAIN),
+        LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
+        LintId::of(doc::MISSING_SAFETY_DOC),
+        LintId::of(doc::NEEDLESS_DOCTEST_MAIN),
+        LintId::of(enum_variants::ENUM_VARIANT_NAMES),
+        LintId::of(enum_variants::MODULE_INCEPTION),
+        LintId::of(eq_op::OP_REF),
+        LintId::of(eta_reduction::REDUNDANT_CLOSURE),
+        LintId::of(float_literal::EXCESSIVE_PRECISION),
+        LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
+        LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
+        LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(from_over_into::FROM_OVER_INTO),
+        LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
+        LintId::of(functions::DOUBLE_MUST_USE),
+        LintId::of(functions::MUST_USE_UNIT),
+        LintId::of(functions::RESULT_UNIT_ERR),
+        LintId::of(if_let_some_result::IF_LET_SOME_RESULT),
+        LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
+        LintId::of(inherent_to_string::INHERENT_TO_STRING),
+        LintId::of(len_zero::COMPARISON_TO_EMPTY),
+        LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
+        LintId::of(len_zero::LEN_ZERO),
+        LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
+        LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
+        LintId::of(loops::EMPTY_LOOP),
+        LintId::of(loops::FOR_KV_MAP),
+        LintId::of(loops::NEEDLESS_RANGE_LOOP),
+        LintId::of(loops::SAME_ITEM_PUSH),
+        LintId::of(loops::WHILE_LET_ON_ITERATOR),
+        LintId::of(main_recursion::MAIN_RECURSION),
+        LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
+        LintId::of(manual_map::MANUAL_MAP),
+        LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
+        LintId::of(map_clone::MAP_CLONE),
+        LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
+        LintId::of(matches::MATCH_LIKE_MATCHES_MACRO),
+        LintId::of(matches::MATCH_OVERLAPPING_ARM),
+        LintId::of(matches::MATCH_REF_PATS),
+        LintId::of(matches::REDUNDANT_PATTERN_MATCHING),
+        LintId::of(matches::SINGLE_MATCH),
+        LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
+        LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT),
+        LintId::of(methods::BYTES_NTH),
+        LintId::of(methods::CHARS_LAST_CMP),
+        LintId::of(methods::CHARS_NEXT_CMP),
+        LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
+        LintId::of(methods::INTO_ITER_ON_REF),
+        LintId::of(methods::ITER_CLONED_COLLECT),
+        LintId::of(methods::ITER_NEXT_SLICE),
+        LintId::of(methods::ITER_NTH_ZERO),
+        LintId::of(methods::ITER_SKIP_NEXT),
+        LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
+        LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
+        LintId::of(methods::NEW_RET_NO_SELF),
+        LintId::of(methods::OK_EXPECT),
+        LintId::of(methods::OPTION_MAP_OR_NONE),
+        LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
+        LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
+        LintId::of(methods::SINGLE_CHAR_ADD_STR),
+        LintId::of(methods::STRING_EXTEND_CHARS),
+        LintId::of(methods::UNNECESSARY_FOLD),
+        LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
+        LintId::of(methods::WRONG_SELF_CONVENTION),
+        LintId::of(misc::TOPLEVEL_REF_ARG),
+        LintId::of(misc::ZERO_PTR),
+        LintId::of(misc_early::BUILTIN_TYPE_SHADOW),
+        LintId::of(misc_early::DOUBLE_NEG),
+        LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
+        LintId::of(misc_early::MIXED_CASE_HEX_LITERALS),
+        LintId::of(misc_early::REDUNDANT_PATTERN),
+        LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
+        LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
+        LintId::of(neg_multiply::NEG_MULTIPLY),
+        LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
+        LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
+        LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
+        LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
+        LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
+        LintId::of(ptr::CMP_NULL),
+        LintId::of(ptr::PTR_ARG),
+        LintId::of(ptr_eq::PTR_EQ),
+        LintId::of(question_mark::QUESTION_MARK),
+        LintId::of(ranges::MANUAL_RANGE_CONTAINS),
+        LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
+        LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
+        LintId::of(returns::LET_AND_RETURN),
+        LintId::of(returns::NEEDLESS_RETURN),
+        LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
+        LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
+        LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
+        LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
+        LintId::of(try_err::TRY_ERR),
+        LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
+        LintId::of(unused_unit::UNUSED_UNIT),
+        LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
+        LintId::of(write::PRINTLN_EMPTY_STRING),
+        LintId::of(write::PRINT_LITERAL),
+        LintId::of(write::PRINT_WITH_NEWLINE),
+        LintId::of(write::WRITELN_EMPTY_STRING),
+        LintId::of(write::WRITE_LITERAL),
+        LintId::of(write::WRITE_WITH_NEWLINE),
     ]);
 
     store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
-        LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
-        LintId::of(&attrs::DEPRECATED_CFG_ATTR),
-        LintId::of(&booleans::NONMINIMAL_BOOL),
-        LintId::of(&casts::CHAR_LIT_AS_U8),
-        LintId::of(&casts::UNNECESSARY_CAST),
-        LintId::of(&double_comparison::DOUBLE_COMPARISONS),
-        LintId::of(&double_parens::DOUBLE_PARENS),
-        LintId::of(&duration_subsec::DURATION_SUBSEC),
-        LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION),
-        LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
-        LintId::of(&explicit_write::EXPLICIT_WRITE),
-        LintId::of(&format::USELESS_FORMAT),
-        LintId::of(&functions::TOO_MANY_ARGUMENTS),
-        LintId::of(&get_last_with_len::GET_LAST_WITH_LEN),
-        LintId::of(&identity_op::IDENTITY_OP),
-        LintId::of(&int_plus_one::INT_PLUS_ONE),
-        LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
-        LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
-        LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
-        LintId::of(&loops::MANUAL_FLATTEN),
-        LintId::of(&loops::MUT_RANGE_BOUND),
-        LintId::of(&loops::SINGLE_ELEMENT_LOOP),
-        LintId::of(&loops::WHILE_LET_LOOP),
-        LintId::of(&manual_strip::MANUAL_STRIP),
-        LintId::of(&manual_unwrap_or::MANUAL_UNWRAP_OR),
-        LintId::of(&map_identity::MAP_IDENTITY),
-        LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
-        LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
-        LintId::of(&matches::MATCH_AS_REF),
-        LintId::of(&matches::MATCH_SINGLE_BINDING),
-        LintId::of(&matches::WILDCARD_IN_OR_PATTERNS),
-        LintId::of(&methods::BIND_INSTEAD_OF_MAP),
-        LintId::of(&methods::CLONE_ON_COPY),
-        LintId::of(&methods::FILTER_MAP_IDENTITY),
-        LintId::of(&methods::FILTER_NEXT),
-        LintId::of(&methods::FLAT_MAP_IDENTITY),
-        LintId::of(&methods::INSPECT_FOR_EACH),
-        LintId::of(&methods::ITER_COUNT),
-        LintId::of(&methods::MANUAL_FILTER_MAP),
-        LintId::of(&methods::MANUAL_FIND_MAP),
-        LintId::of(&methods::OPTION_AS_REF_DEREF),
-        LintId::of(&methods::SEARCH_IS_SOME),
-        LintId::of(&methods::SKIP_WHILE_NEXT),
-        LintId::of(&methods::SUSPICIOUS_MAP),
-        LintId::of(&methods::UNNECESSARY_FILTER_MAP),
-        LintId::of(&methods::USELESS_ASREF),
-        LintId::of(&misc::SHORT_CIRCUIT_STATEMENT),
-        LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN),
-        LintId::of(&misc_early::ZERO_PREFIXED_LITERAL),
-        LintId::of(&needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
-        LintId::of(&needless_bool::BOOL_COMPARISON),
-        LintId::of(&needless_bool::NEEDLESS_BOOL),
-        LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
-        LintId::of(&needless_question_mark::NEEDLESS_QUESTION_MARK),
-        LintId::of(&needless_update::NEEDLESS_UPDATE),
-        LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
-        LintId::of(&no_effect::NO_EFFECT),
-        LintId::of(&no_effect::UNNECESSARY_OPERATION),
-        LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
-        LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
-        LintId::of(&precedence::PRECEDENCE),
-        LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
-        LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
-        LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL),
-        LintId::of(&redundant_slicing::REDUNDANT_SLICING),
-        LintId::of(&reference::DEREF_ADDROF),
-        LintId::of(&reference::REF_IN_DEREF),
-        LintId::of(&repeat_once::REPEAT_ONCE),
-        LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
-        LintId::of(&swap::MANUAL_SWAP),
-        LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT),
-        LintId::of(&transmute::CROSSPOINTER_TRANSMUTE),
-        LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
-        LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR),
-        LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT),
-        LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL),
-        LintId::of(&transmute::TRANSMUTE_INT_TO_CHAR),
-        LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT),
-        LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR),
-        LintId::of(&transmute::TRANSMUTE_PTR_TO_REF),
-        LintId::of(&types::BORROWED_BOX),
-        LintId::of(&types::TYPE_COMPLEXITY),
-        LintId::of(&types::VEC_BOX),
-        LintId::of(&unit_types::UNIT_ARG),
-        LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
-        LintId::of(&unwrap::UNNECESSARY_UNWRAP),
-        LintId::of(&useless_conversion::USELESS_CONVERSION),
-        LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO),
+        LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
+        LintId::of(attrs::DEPRECATED_CFG_ATTR),
+        LintId::of(booleans::NONMINIMAL_BOOL),
+        LintId::of(casts::CHAR_LIT_AS_U8),
+        LintId::of(casts::UNNECESSARY_CAST),
+        LintId::of(copies::BRANCHES_SHARING_CODE),
+        LintId::of(double_comparison::DOUBLE_COMPARISONS),
+        LintId::of(double_parens::DOUBLE_PARENS),
+        LintId::of(duration_subsec::DURATION_SUBSEC),
+        LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION),
+        LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
+        LintId::of(explicit_write::EXPLICIT_WRITE),
+        LintId::of(format::USELESS_FORMAT),
+        LintId::of(functions::TOO_MANY_ARGUMENTS),
+        LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
+        LintId::of(identity_op::IDENTITY_OP),
+        LintId::of(int_plus_one::INT_PLUS_ONE),
+        LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
+        LintId::of(lifetimes::NEEDLESS_LIFETIMES),
+        LintId::of(loops::EXPLICIT_COUNTER_LOOP),
+        LintId::of(loops::MANUAL_FLATTEN),
+        LintId::of(loops::MUT_RANGE_BOUND),
+        LintId::of(loops::SINGLE_ELEMENT_LOOP),
+        LintId::of(loops::WHILE_LET_LOOP),
+        LintId::of(manual_strip::MANUAL_STRIP),
+        LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR),
+        LintId::of(map_identity::MAP_IDENTITY),
+        LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
+        LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
+        LintId::of(matches::MATCH_AS_REF),
+        LintId::of(matches::MATCH_SINGLE_BINDING),
+        LintId::of(matches::WILDCARD_IN_OR_PATTERNS),
+        LintId::of(methods::BIND_INSTEAD_OF_MAP),
+        LintId::of(methods::CLONE_ON_COPY),
+        LintId::of(methods::FILTER_MAP_IDENTITY),
+        LintId::of(methods::FILTER_NEXT),
+        LintId::of(methods::FLAT_MAP_IDENTITY),
+        LintId::of(methods::INSPECT_FOR_EACH),
+        LintId::of(methods::ITER_COUNT),
+        LintId::of(methods::MANUAL_FILTER_MAP),
+        LintId::of(methods::MANUAL_FIND_MAP),
+        LintId::of(methods::OPTION_AS_REF_DEREF),
+        LintId::of(methods::OPTION_FILTER_MAP),
+        LintId::of(methods::SEARCH_IS_SOME),
+        LintId::of(methods::SKIP_WHILE_NEXT),
+        LintId::of(methods::SUSPICIOUS_MAP),
+        LintId::of(methods::UNNECESSARY_FILTER_MAP),
+        LintId::of(methods::USELESS_ASREF),
+        LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
+        LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN),
+        LintId::of(misc_early::ZERO_PREFIXED_LITERAL),
+        LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
+        LintId::of(needless_bool::BOOL_COMPARISON),
+        LintId::of(needless_bool::NEEDLESS_BOOL),
+        LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
+        LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
+        LintId::of(needless_update::NEEDLESS_UPDATE),
+        LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
+        LintId::of(no_effect::NO_EFFECT),
+        LintId::of(no_effect::UNNECESSARY_OPERATION),
+        LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
+        LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
+        LintId::of(precedence::PRECEDENCE),
+        LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
+        LintId::of(ranges::RANGE_ZIP_WITH_LEN),
+        LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
+        LintId::of(redundant_slicing::REDUNDANT_SLICING),
+        LintId::of(reference::DEREF_ADDROF),
+        LintId::of(reference::REF_IN_DEREF),
+        LintId::of(repeat_once::REPEAT_ONCE),
+        LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
+        LintId::of(swap::MANUAL_SWAP),
+        LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
+        LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
+        LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
+        LintId::of(transmute::TRANSMUTE_BYTES_TO_STR),
+        LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT),
+        LintId::of(transmute::TRANSMUTE_INT_TO_BOOL),
+        LintId::of(transmute::TRANSMUTE_INT_TO_CHAR),
+        LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
+        LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
+        LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
+        LintId::of(types::BORROWED_BOX),
+        LintId::of(types::TYPE_COMPLEXITY),
+        LintId::of(types::VEC_BOX),
+        LintId::of(unit_types::UNIT_ARG),
+        LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY),
+        LintId::of(unwrap::UNNECESSARY_UNWRAP),
+        LintId::of(useless_conversion::USELESS_CONVERSION),
+        LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO),
     ]);
 
     store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![
-        LintId::of(&approx_const::APPROX_CONSTANT),
-        LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC),
-        LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
-        LintId::of(&attrs::DEPRECATED_SEMVER),
-        LintId::of(&attrs::MISMATCHED_TARGET_OS),
-        LintId::of(&attrs::USELESS_ATTRIBUTE),
-        LintId::of(&bit_mask::BAD_BIT_MASK),
-        LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
-        LintId::of(&booleans::LOGIC_BUG),
-        LintId::of(&casts::CAST_REF_TO_MUT),
-        LintId::of(&copies::IFS_SAME_COND),
-        LintId::of(&copies::IF_SAME_THEN_ELSE),
-        LintId::of(&derive::DERIVE_HASH_XOR_EQ),
-        LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD),
-        LintId::of(&drop_forget_ref::DROP_COPY),
-        LintId::of(&drop_forget_ref::DROP_REF),
-        LintId::of(&drop_forget_ref::FORGET_COPY),
-        LintId::of(&drop_forget_ref::FORGET_REF),
-        LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
-        LintId::of(&eq_op::EQ_OP),
-        LintId::of(&erasing_op::ERASING_OP),
-        LintId::of(&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
-        LintId::of(&formatting::POSSIBLE_MISSING_COMMA),
-        LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF),
-        LintId::of(&if_let_mutex::IF_LET_MUTEX),
-        LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING),
-        LintId::of(&infinite_iter::INFINITE_ITER),
-        LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
-        LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
-        LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
-        LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
-        LintId::of(&loops::FOR_LOOPS_OVER_FALLIBLES),
-        LintId::of(&loops::ITER_NEXT_LOOP),
-        LintId::of(&loops::NEVER_LOOP),
-        LintId::of(&loops::WHILE_IMMUTABLE_CONDITION),
-        LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
-        LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT),
-        LintId::of(&methods::CLONE_DOUBLE_REF),
-        LintId::of(&methods::ITERATOR_STEP_BY_ZERO),
-        LintId::of(&methods::UNINIT_ASSUMED_INIT),
-        LintId::of(&methods::ZST_OFFSET),
-        LintId::of(&minmax::MIN_MAX),
-        LintId::of(&misc::CMP_NAN),
-        LintId::of(&misc::FLOAT_CMP),
-        LintId::of(&misc::MODULO_ONE),
-        LintId::of(&mut_key::MUTABLE_KEY_TYPE),
-        LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS),
-        LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP),
-        LintId::of(&ptr::MUT_FROM_REF),
-        LintId::of(&ranges::REVERSED_EMPTY_RANGES),
-        LintId::of(&regex::INVALID_REGEX),
-        LintId::of(&self_assignment::SELF_ASSIGNMENT),
-        LintId::of(&serde_api::SERDE_API_MISUSE),
-        LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
-        LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
-        LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
-        LintId::of(&swap::ALMOST_SWAPPED),
-        LintId::of(&to_string_in_display::TO_STRING_IN_DISPLAY),
-        LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE),
-        LintId::of(&transmute::WRONG_TRANSMUTE),
-        LintId::of(&transmuting_null::TRANSMUTING_NULL),
-        LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
-        LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
-        LintId::of(&unicode::INVISIBLE_CHARACTERS),
-        LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
-        LintId::of(&unit_types::UNIT_CMP),
-        LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
-        LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
-        LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
-        LintId::of(&unwrap::PANICKING_UNWRAP),
-        LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
+        LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS),
+        LintId::of(approx_const::APPROX_CONSTANT),
+        LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
+        LintId::of(atomic_ordering::INVALID_ATOMIC_ORDERING),
+        LintId::of(attrs::DEPRECATED_SEMVER),
+        LintId::of(attrs::MISMATCHED_TARGET_OS),
+        LintId::of(attrs::USELESS_ATTRIBUTE),
+        LintId::of(bit_mask::BAD_BIT_MASK),
+        LintId::of(bit_mask::INEFFECTIVE_BIT_MASK),
+        LintId::of(booleans::LOGIC_BUG),
+        LintId::of(casts::CAST_REF_TO_MUT),
+        LintId::of(copies::IFS_SAME_COND),
+        LintId::of(copies::IF_SAME_THEN_ELSE),
+        LintId::of(derive::DERIVE_HASH_XOR_EQ),
+        LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
+        LintId::of(drop_forget_ref::DROP_COPY),
+        LintId::of(drop_forget_ref::DROP_REF),
+        LintId::of(drop_forget_ref::FORGET_COPY),
+        LintId::of(drop_forget_ref::FORGET_REF),
+        LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
+        LintId::of(eq_op::EQ_OP),
+        LintId::of(erasing_op::ERASING_OP),
+        LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
+        LintId::of(formatting::POSSIBLE_MISSING_COMMA),
+        LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
+        LintId::of(if_let_mutex::IF_LET_MUTEX),
+        LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
+        LintId::of(infinite_iter::INFINITE_ITER),
+        LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
+        LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
+        LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
+        LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
+        LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
+        LintId::of(loops::ITER_NEXT_LOOP),
+        LintId::of(loops::NEVER_LOOP),
+        LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
+        LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
+        LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
+        LintId::of(methods::CLONE_DOUBLE_REF),
+        LintId::of(methods::ITERATOR_STEP_BY_ZERO),
+        LintId::of(methods::UNINIT_ASSUMED_INIT),
+        LintId::of(methods::ZST_OFFSET),
+        LintId::of(minmax::MIN_MAX),
+        LintId::of(misc::CMP_NAN),
+        LintId::of(misc::FLOAT_CMP),
+        LintId::of(misc::MODULO_ONE),
+        LintId::of(mut_key::MUTABLE_KEY_TYPE),
+        LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
+        LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
+        LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
+        LintId::of(ptr::MUT_FROM_REF),
+        LintId::of(ranges::REVERSED_EMPTY_RANGES),
+        LintId::of(regex::INVALID_REGEX),
+        LintId::of(self_assignment::SELF_ASSIGNMENT),
+        LintId::of(serde_api::SERDE_API_MISUSE),
+        LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
+        LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
+        LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
+        LintId::of(swap::ALMOST_SWAPPED),
+        LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY),
+        LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
+        LintId::of(transmute::WRONG_TRANSMUTE),
+        LintId::of(transmuting_null::TRANSMUTING_NULL),
+        LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
+        LintId::of(unicode::INVISIBLE_CHARACTERS),
+        LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
+        LintId::of(unit_types::UNIT_CMP),
+        LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
+        LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
+        LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
+        LintId::of(unwrap::PANICKING_UNWRAP),
+        LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
     ]);
 
     store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
-        LintId::of(&entry::MAP_ENTRY),
-        LintId::of(&escape::BOXED_LOCAL),
-        LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
-        LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
-        LintId::of(&loops::MANUAL_MEMCPY),
-        LintId::of(&loops::NEEDLESS_COLLECT),
-        LintId::of(&methods::EXPECT_FUN_CALL),
-        LintId::of(&methods::ITER_NTH),
-        LintId::of(&methods::OR_FUN_CALL),
-        LintId::of(&methods::SINGLE_CHAR_PATTERN),
-        LintId::of(&misc::CMP_OWNED),
-        LintId::of(&mutex_atomic::MUTEX_ATOMIC),
-        LintId::of(&redundant_clone::REDUNDANT_CLONE),
-        LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
-        LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE),
-        LintId::of(&types::BOX_VEC),
-        LintId::of(&types::REDUNDANT_ALLOCATION),
-        LintId::of(&vec::USELESS_VEC),
-        LintId::of(&vec_init_then_push::VEC_INIT_THEN_PUSH),
+        LintId::of(entry::MAP_ENTRY),
+        LintId::of(escape::BOXED_LOCAL),
+        LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
+        LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
+        LintId::of(loops::MANUAL_MEMCPY),
+        LintId::of(loops::NEEDLESS_COLLECT),
+        LintId::of(methods::EXPECT_FUN_CALL),
+        LintId::of(methods::ITER_NTH),
+        LintId::of(methods::OR_FUN_CALL),
+        LintId::of(methods::SINGLE_CHAR_PATTERN),
+        LintId::of(misc::CMP_OWNED),
+        LintId::of(mutex_atomic::MUTEX_ATOMIC),
+        LintId::of(redundant_clone::REDUNDANT_CLONE),
+        LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
+        LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
+        LintId::of(types::BOX_VEC),
+        LintId::of(types::REDUNDANT_ALLOCATION),
+        LintId::of(vec::USELESS_VEC),
+        LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
     ]);
 
     store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![
-        LintId::of(&cargo_common_metadata::CARGO_COMMON_METADATA),
-        LintId::of(&multiple_crate_versions::MULTIPLE_CRATE_VERSIONS),
-        LintId::of(&wildcard_dependencies::WILDCARD_DEPENDENCIES),
+        LintId::of(cargo_common_metadata::CARGO_COMMON_METADATA),
+        LintId::of(multiple_crate_versions::MULTIPLE_CRATE_VERSIONS),
+        LintId::of(wildcard_dependencies::WILDCARD_DEPENDENCIES),
     ]);
 
     store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
-        LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
-        LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
-        LintId::of(&disallowed_method::DISALLOWED_METHOD),
-        LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
-        LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
-        LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
-        LintId::of(&future_not_send::FUTURE_NOT_SEND),
-        LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
-        LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN),
-        LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
-        LintId::of(&mutex_atomic::MUTEX_INTEGER),
-        LintId::of(&needless_borrow::NEEDLESS_BORROW),
-        LintId::of(&path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
-        LintId::of(&redundant_pub_crate::REDUNDANT_PUB_CRATE),
-        LintId::of(&regex::TRIVIAL_REGEX),
-        LintId::of(&strings::STRING_LIT_AS_BYTES),
-        LintId::of(&transmute::USELESS_TRANSMUTE),
-        LintId::of(&use_self::USE_SELF),
+        LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
+        LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
+        LintId::of(disallowed_method::DISALLOWED_METHOD),
+        LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
+        LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
+        LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS),
+        LintId::of(future_not_send::FUTURE_NOT_SEND),
+        LintId::of(let_if_seq::USELESS_LET_IF_SEQ),
+        LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
+        LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
+        LintId::of(mutex_atomic::MUTEX_INTEGER),
+        LintId::of(needless_borrow::NEEDLESS_BORROW),
+        LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
+        LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
+        LintId::of(regex::TRIVIAL_REGEX),
+        LintId::of(strings::STRING_LIT_AS_BYTES),
+        LintId::of(transmute::USELESS_TRANSMUTE),
+        LintId::of(use_self::USE_SELF),
     ]);
 }
 
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index e3b3fa21cab..116ad072837 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -81,7 +81,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
 impl<'tcx> LateLintPass<'tcx> for Lifetimes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if let ItemKind::Fn(ref sig, ref generics, id) = item.kind {
-            check_fn_inner(cx, &sig.decl, Some(id), generics, item.span, true);
+            check_fn_inner(cx, sig.decl, Some(id), generics, item.span, true);
         }
     }
 
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
             let report_extra_lifetimes = trait_ref_of_method(cx, item.hir_id()).is_none();
             check_fn_inner(
                 cx,
-                &sig.decl,
+                sig.decl,
                 Some(id),
                 &item.generics,
                 item.span,
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
                 TraitFn::Required(_) => None,
                 TraitFn::Provided(id) => Some(id),
             };
-            check_fn_inner(cx, &sig.decl, body, &item.generics, item.span, true);
+            check_fn_inner(cx, sig.decl, body, &item.generics, item.span, true);
         }
     }
 }
@@ -149,7 +149,7 @@ fn check_fn_inner<'tcx>(
                     .last()
                     .expect("a path must have at least one segment")
                     .args;
-                if let Some(ref params) = *params {
+                if let Some(params) = *params {
                     let lifetimes = params.args.iter().filter_map(|arg| match arg {
                         GenericArg::Lifetime(lt) => Some(lt),
                         _ => None,
@@ -163,7 +163,7 @@ fn check_fn_inner<'tcx>(
             }
         }
     }
-    if could_use_elision(cx, decl, body, &generics.params) {
+    if could_use_elision(cx, decl, body, generics.params) {
         span_lint(
             cx,
             NEEDLESS_LIFETIMES,
@@ -201,7 +201,7 @@ fn could_use_elision<'tcx>(
         input_visitor.visit_ty(arg);
     }
     // extract lifetimes in output type
-    if let Return(ref ty) = func.output {
+    if let Return(ty) = func.output {
         output_visitor.visit_ty(ty);
     }
     for lt in named_generics {
@@ -416,12 +416,12 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl
                 // a predicate like F: Trait or F: for<'a> Trait<'a>
                 let mut visitor = RefVisitor::new(cx);
                 // walk the type F, it may not contain LT refs
-                walk_ty(&mut visitor, &pred.bounded_ty);
+                walk_ty(&mut visitor, pred.bounded_ty);
                 if !visitor.all_lts().is_empty() {
                     return true;
                 }
                 // if the bounds define new lifetimes, they are fine to occur
-                let allowed_lts = allowed_lts_from(&pred.bound_generic_params);
+                let allowed_lts = allowed_lts_from(pred.bound_generic_params);
                 // now walk the bounds
                 for bound in pred.bounds.iter() {
                     walk_param_bound(&mut visitor, bound);
@@ -433,8 +433,8 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl
             },
             WherePredicate::EqPredicate(ref pred) => {
                 let mut visitor = RefVisitor::new(cx);
-                walk_ty(&mut visitor, &pred.lhs_ty);
-                walk_ty(&mut visitor, &pred.rhs_ty);
+                walk_ty(&mut visitor, pred.lhs_ty);
+                walk_ty(&mut visitor, pred.rhs_ty);
                 if !visitor.lts.is_empty() {
                     return true;
                 }
diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index 54470519260..e93b2e36b86 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/clippy_lints/src/literal_representation.rs
@@ -249,7 +249,7 @@ impl LiteralDigitGrouping {
     fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
         if_chain! {
             if let Some(src) = snippet_opt(cx, lit.span);
-            if let Some(mut num_lit) = NumericLiteral::from_lit(&src, &lit);
+            if let Some(mut num_lit) = NumericLiteral::from_lit(&src, lit);
             then {
                 if !Self::check_for_mistyped_suffix(cx, lit.span, &mut num_lit) {
                     return;
@@ -439,7 +439,7 @@ impl DecimalLiteralRepresentation {
         if_chain! {
             if let LitKind::Int(val, _) = lit.kind;
             if let Some(src) = snippet_opt(cx, lit.span);
-            if let Some(num_lit) = NumericLiteral::from_lit(&src, &lit);
+            if let Some(num_lit) = NumericLiteral::from_lit(&src, lit);
             if num_lit.radix == Radix::Decimal;
             if val >= u128::from(self.threshold);
             then {
diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs
index f14dbb1d642..98e60f7ed85 100644
--- a/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -26,7 +26,7 @@ pub(super) fn check<'tcx>(
 
     // For each candidate, check the parent block to see if
     // it's initialized to zero at the start of the loop.
-    if let Some(block) = get_enclosing_block(&cx, expr.hir_id) {
+    if let Some(block) = get_enclosing_block(cx, expr.hir_id) {
         for id in increment_visitor.into_results() {
             let mut initialize_visitor = InitializeVisitor::new(cx, expr, id);
             walk_block(&mut initialize_visitor, block);
diff --git a/clippy_lints/src/loops/for_kv_map.rs b/clippy_lints/src/loops/for_kv_map.rs
index 8f18f54119b..666b8c58728 100644
--- a/clippy_lints/src/loops/for_kv_map.rs
+++ b/clippy_lints/src/loops/for_kv_map.rs
@@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
 ) {
     let pat_span = pat.span;
 
-    if let PatKind::Tuple(ref pat, _) = pat.kind {
+    if let PatKind::Tuple(pat, _) = pat.kind {
         if pat.len() == 2 {
             let arg_span = arg.span;
             let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() {
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
                 Mutability::Mut => "_mut",
             };
             let arg = match arg.kind {
-                ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) => &**expr,
+                ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr,
                 _ => arg,
             };
 
diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs
index 8d2b9cccba4..94743cfcf46 100644
--- a/clippy_lints/src/loops/manual_flatten.rs
+++ b/clippy_lints/src/loops/manual_flatten.rs
@@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
     body: &'tcx Expr<'_>,
     span: Span,
 ) {
-    if let ExprKind::Block(ref block, _) = body.kind {
+    if let ExprKind::Block(block, _) = body.kind {
         // Ensure the `if let` statement is the only expression or statement in the for-loop
         let inner_expr = if block.stmts.len() == 1 && block.expr.is_none() {
             let match_stmt = &block.stmts[0];
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
         if_chain! {
             if let Some(inner_expr) = inner_expr;
             if let ExprKind::Match(
-                ref match_expr, ref match_arms, MatchSource::IfLetDesugar{ contains_else_clause: false }
+                match_expr, match_arms, MatchSource::IfLetDesugar{ contains_else_clause: false }
             ) = inner_expr.kind;
             // Ensure match_expr in `if let` statement is the same as the pat from the for-loop
             if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind;
@@ -46,9 +46,8 @@ pub(super) fn check<'tcx>(
             let some_ctor = is_some_ctor(cx, path.res);
             let ok_ctor = is_ok_ctor(cx, path.res);
             if some_ctor || ok_ctor;
-            let if_let_type = if some_ctor { "Some" } else { "Ok" };
-
             then {
+                let if_let_type = if some_ctor { "Some" } else { "Ok" };
                 // Prepare the error message
                 let msg = format!("unnecessary `if let` since only the `{}` variant of the iterator element is used", if_let_type);
 
diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs
index f5758b68f60..47005aba388 100644
--- a/clippy_lints/src/loops/manual_memcpy.rs
+++ b/clippy_lints/src/loops/manual_memcpy.rs
@@ -61,10 +61,10 @@ pub(super) fn check<'tcx>(
                         if_chain! {
                             if let ExprKind::Index(base_left, idx_left) = lhs.kind;
                             if let ExprKind::Index(base_right, idx_right) = rhs.kind;
-                            if is_slice_like(cx, cx.typeck_results().expr_ty(base_left))
-                                && is_slice_like(cx, cx.typeck_results().expr_ty(base_right));
-                            if let Some((start_left, offset_left)) = get_details_from_idx(cx, &idx_left, &starts);
-                            if let Some((start_right, offset_right)) = get_details_from_idx(cx, &idx_right, &starts);
+                            if is_slice_like(cx, cx.typeck_results().expr_ty(base_left));
+                            if is_slice_like(cx, cx.typeck_results().expr_ty(base_right));
+                            if let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts);
+                            if let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts);
 
                             // Source and destination must be different
                             if path_to_local(base_left) != path_to_local(base_right);
@@ -168,8 +168,8 @@ fn build_manual_memcpy_suggestion<'tcx>(
         },
     };
 
-    let (dst_offset, dst_limit) = print_offset_and_limit(&dst);
-    let (src_offset, src_limit) = print_offset_and_limit(&src);
+    let (dst_offset, dst_limit) = print_offset_and_limit(dst);
+    let (src_offset, src_limit) = print_offset_and_limit(src);
 
     let dst_base_str = snippet(cx, dst.base.span, "???");
     let src_base_str = snippet(cx, src.base.span, "???");
@@ -204,11 +204,8 @@ struct MinifyingSugg<'a>(Sugg<'a>);
 
 impl<'a> MinifyingSugg<'a> {
     fn as_str(&self) -> &str {
-        // HACK: Don't sync to Clippy! Required because something with the `or_patterns` feature
-        // changed and this would now require parentheses.
-        match &self.0 {
-            Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) => s.as_ref(),
-        }
+        let (Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s)) = &self.0;
+        s.as_ref()
     }
 
     fn into_sugg(self) -> Sugg<'a> {
@@ -438,7 +435,7 @@ fn get_loop_counters<'a, 'tcx>(
 
     // For each candidate, check the parent block to see if
     // it's initialized to zero at the start of the loop.
-    get_enclosing_block(&cx, expr.hir_id).and_then(|block| {
+    get_enclosing_block(cx, expr.hir_id).and_then(|block| {
         increment_visitor
             .into_results()
             .filter_map(move |var_id| {
diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index 20291491998..28acefd51fe 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/clippy_lints/src/loops/mod.rs
@@ -562,7 +562,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
         // check for `loop { if let {} else break }` that could be `while let`
         // (also matches an explicit "match" instead of "if let")
         // (even if the "match" or "if let" is used for declaration)
-        if let ExprKind::Loop(ref block, _, LoopSource::Loop, _) = expr.kind {
+        if let ExprKind::Loop(block, _, LoopSource::Loop, _) = expr.kind {
             // also check for empty `loop {}` statements, skipping those in #[panic_handler]
             empty_loop::check(cx, expr, block);
             while_let_loop::check(cx, expr, block);
@@ -570,7 +570,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
 
         while_let_on_iterator::check(cx, expr);
 
-        if let Some((cond, body)) = higher::while_loop(&expr) {
+        if let Some((cond, body)) = higher::while_loop(expr) {
             while_immutable_condition::check(cx, cond, body);
         }
 
@@ -602,7 +602,7 @@ fn check_for_loop<'tcx>(
 fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
     let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
 
-    if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind {
+    if let ExprKind::MethodCall(method, _, args, _) = arg.kind {
         // just the receiver, no arguments
         if args.len() == 1 {
             let method_name = &*method.ident.as_str();
diff --git a/clippy_lints/src/loops/needless_collect.rs b/clippy_lints/src/loops/needless_collect.rs
index 5594fc7b046..4d73aef76e8 100644
--- a/clippy_lints/src/loops/needless_collect.rs
+++ b/clippy_lints/src/loops/needless_collect.rs
@@ -10,8 +10,8 @@ use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, GenericArg, HirId, Local, Pat, PatKind, QPath, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
-use rustc_span::source_map::Span;
 use rustc_span::symbol::{sym, Ident};
+use rustc_span::{MultiSpan, Span};
 
 const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
 
@@ -21,88 +21,60 @@ pub(super) fn check<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
 }
 fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
     if_chain! {
-        if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
-        if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind;
+        if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
+        if let ExprKind::MethodCall(chain_method, method0_span, _, _) = args[0].kind;
         if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
-        if let Some(ref generic_args) = chain_method.args;
+        if let Some(generic_args) = chain_method.args;
         if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
-        then {
-            let ty = cx.typeck_results().node_type(ty.hir_id);
-            if is_type_diagnostic_item(cx, ty, sym::vec_type) ||
-                is_type_diagnostic_item(cx, ty, sym::vecdeque_type) ||
-                match_type(cx, ty, &paths::BTREEMAP) ||
-                is_type_diagnostic_item(cx, ty, sym::hashmap_type) {
-                if method.ident.name == sym!(len) {
-                    let span = shorten_needless_collect_span(expr);
-                    span_lint_and_sugg(
-                        cx,
-                        NEEDLESS_COLLECT,
-                        span,
-                        NEEDLESS_COLLECT_MSG,
-                        "replace with",
-                        "count()".to_string(),
-                        Applicability::MachineApplicable,
-                    );
-                }
-                if method.ident.name == sym!(is_empty) {
-                    let span = shorten_needless_collect_span(expr);
-                    span_lint_and_sugg(
-                        cx,
-                        NEEDLESS_COLLECT,
-                        span,
-                        NEEDLESS_COLLECT_MSG,
-                        "replace with",
-                        "next().is_none()".to_string(),
-                        Applicability::MachineApplicable,
-                    );
-                }
-                if method.ident.name == sym!(contains) {
-                    let contains_arg = snippet(cx, args[1].span, "??");
-                    let span = shorten_needless_collect_span(expr);
-                    span_lint_and_then(
-                        cx,
-                        NEEDLESS_COLLECT,
-                        span,
-                        NEEDLESS_COLLECT_MSG,
-                        |diag| {
-                            let (arg, pred) = contains_arg
-                                    .strip_prefix('&')
-                                    .map_or(("&x", &*contains_arg), |s| ("x", s));
-                            diag.span_suggestion(
-                                span,
-                                "replace with",
-                                format!(
-                                    "any(|{}| x == {})",
-                                    arg, pred
-                                ),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    );
-                }
+        let ty = cx.typeck_results().node_type(ty.hir_id);
+        if is_type_diagnostic_item(cx, ty, sym::vec_type)
+            || is_type_diagnostic_item(cx, ty, sym::vecdeque_type)
+            || match_type(cx, ty, &paths::BTREEMAP)
+            || is_type_diagnostic_item(cx, ty, sym::hashmap_type);
+        if let Some(sugg) = match &*method.ident.name.as_str() {
+            "len" => Some("count()".to_string()),
+            "is_empty" => Some("next().is_none()".to_string()),
+            "contains" => {
+                let contains_arg = snippet(cx, args[1].span, "??");
+                let (arg, pred) = contains_arg
+                    .strip_prefix('&')
+                    .map_or(("&x", &*contains_arg), |s| ("x", s));
+                Some(format!("any(|{}| x == {})", arg, pred))
             }
+            _ => None,
+        };
+        then {
+            span_lint_and_sugg(
+                cx,
+                NEEDLESS_COLLECT,
+                method0_span.with_hi(expr.span.hi()),
+                NEEDLESS_COLLECT_MSG,
+                "replace with",
+                sugg,
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
 
 fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
-    if let ExprKind::Block(ref block, _) = expr.kind {
-        for ref stmt in block.stmts {
+    if let ExprKind::Block(block, _) = expr.kind {
+        for stmt in block.stmts {
             if_chain! {
                 if let StmtKind::Local(
                     Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. },
-                    init: Some(ref init_expr), .. }
+                    init: Some(init_expr), .. }
                 ) = stmt.kind;
-                if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind;
-                if method_name.ident.name == sym!(collect) && is_trait_method(cx, &init_expr, sym::Iterator);
-                if let Some(ref generic_args) = method_name.args;
+                if let ExprKind::MethodCall(method_name, collect_span, &[ref iter_source], ..) = init_expr.kind;
+                if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
+                if let Some(generic_args) = method_name.args;
                 if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
                 if let ty = cx.typeck_results().node_type(ty.hir_id);
                 if is_type_diagnostic_item(cx, ty, sym::vec_type) ||
                     is_type_diagnostic_item(cx, ty, sym::vecdeque_type) ||
                     match_type(cx, ty, &paths::LINKED_LIST);
                 if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident);
-                if iter_calls.len() == 1;
+                if let [iter_call] = &*iter_calls;
                 then {
                     let mut used_count_visitor = UsedCountVisitor {
                         cx,
@@ -115,11 +87,12 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                     }
 
                     // Suggest replacing iter_call with iter_replacement, and removing stmt
-                    let iter_call = &iter_calls[0];
+                    let mut span = MultiSpan::from_span(collect_span);
+                    span.push_span_label(iter_call.span, "the iterator could be used here instead".into());
                     span_lint_and_then(
                         cx,
                         super::NEEDLESS_COLLECT,
-                        stmt.span.until(iter_call.span),
+                        span,
                         NEEDLESS_COLLECT_MSG,
                         |diag| {
                             let iter_replacement = format!("{}{}", Sugg::hir(cx, iter_source, ".."), iter_call.get_iter_method(cx));
@@ -130,7 +103,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                                     (iter_call.span, iter_replacement)
                                 ],
                                 Applicability::MachineApplicable,// MaybeIncorrect,
-                            ).emit();
+                            );
                         },
                     );
                 }
@@ -192,8 +165,8 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor {
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // Check function calls on our collection
         if_chain! {
-            if let ExprKind::MethodCall(method_name, _, ref args, _) = &expr.kind;
-            if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. }) = args.get(0);
+            if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
+            if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. }) = args.get(0);
             if let &[name] = &path.segments;
             if name.ident == self.target;
             then {
@@ -220,7 +193,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor {
         }
         // Check if the collection is used for anything else
         if_chain! {
-            if let Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. } = expr;
+            if let Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. } = expr;
             if let &[name] = &path.segments;
             if name.ident == self.target;
             then {
@@ -270,14 +243,3 @@ fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident)
     visitor.visit_block(block);
     if visitor.seen_other { None } else { Some(visitor.uses) }
 }
-
-fn shorten_needless_collect_span(expr: &Expr<'_>) -> Span {
-    if_chain! {
-        if let ExprKind::MethodCall(.., args, _) = &expr.kind;
-        if let ExprKind::MethodCall(_, span, ..) = &args[0].kind;
-        then {
-            return expr.span.with_lo(span.lo());
-        }
-    }
-    unreachable!();
-}
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index 64ab3b6bfec..3065bcc3e6c 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -96,7 +96,7 @@ pub(super) fn check<'tcx>(
                 let take = if let Some(end) = *end {
                     let mut take_expr = end;
 
-                    if let ExprKind::Binary(ref op, ref left, ref right) = end.kind {
+                    if let ExprKind::Binary(ref op, left, right) = end.kind {
                         if let BinOpKind::Add = op.node {
                             let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
                             let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
@@ -190,10 +190,10 @@ pub(super) fn check<'tcx>(
 
 fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(ref method, _, ref len_args, _) = expr.kind;
+        if let ExprKind::MethodCall(method, _, len_args, _) = expr.kind;
         if len_args.len() == 1;
         if method.ident.name == sym!(len);
-        if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].kind;
+        if let ExprKind::Path(QPath::Resolved(_, path)) = len_args[0].kind;
         if path.segments.len() == 1;
         if path.segments[0].ident.name == var;
         then {
@@ -254,51 +254,49 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
         if_chain! {
             // the indexed container is referenced by a name
             if let ExprKind::Path(ref seqpath) = seqexpr.kind;
-            if let QPath::Resolved(None, ref seqvar) = *seqpath;
+            if let QPath::Resolved(None, seqvar) = *seqpath;
             if seqvar.segments.len() == 1;
+            let index_used_directly = path_to_local_id(idx, self.var);
+            let indexed_indirectly = {
+                let mut used_visitor = LocalUsedVisitor::new(self.cx, self.var);
+                walk_expr(&mut used_visitor, idx);
+                used_visitor.used
+            };
+            if indexed_indirectly || index_used_directly;
             then {
-                let index_used_directly = path_to_local_id(idx, self.var);
-                let indexed_indirectly = {
-                    let mut used_visitor = LocalUsedVisitor::new(self.cx, self.var);
-                    walk_expr(&mut used_visitor, idx);
-                    used_visitor.used
-                };
-
-                if indexed_indirectly || index_used_directly {
-                    if self.prefer_mutable {
-                        self.indexed_mut.insert(seqvar.segments[0].ident.name);
+                if self.prefer_mutable {
+                    self.indexed_mut.insert(seqvar.segments[0].ident.name);
+                }
+                let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
+                match res {
+                    Res::Local(hir_id) => {
+                        let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
+                        let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id);
+                        let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
+                        if indexed_indirectly {
+                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent));
+                        }
+                        if index_used_directly {
+                            self.indexed_directly.insert(
+                                seqvar.segments[0].ident.name,
+                                (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
+                            );
+                        }
+                        return false;  // no need to walk further *on the variable*
                     }
-                    let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
-                    match res {
-                        Res::Local(hir_id) => {
-                            let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
-                            let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id);
-                            let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
-                            if indexed_indirectly {
-                                self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent));
-                            }
-                            if index_used_directly {
-                                self.indexed_directly.insert(
-                                    seqvar.segments[0].ident.name,
-                                    (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
-                                );
-                            }
-                            return false;  // no need to walk further *on the variable*
+                    Res::Def(DefKind::Static | DefKind::Const, ..) => {
+                        if indexed_indirectly {
+                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
                         }
-                        Res::Def(DefKind::Static | DefKind::Const, ..) => {
-                            if indexed_indirectly {
-                                self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
-                            }
-                            if index_used_directly {
-                                self.indexed_directly.insert(
-                                    seqvar.segments[0].ident.name,
-                                    (None, self.cx.typeck_results().node_type(seqexpr.hir_id)),
-                                );
-                            }
-                            return false;  // no need to walk further *on the variable*
+                        if index_used_directly {
+                            self.indexed_directly.insert(
+                                seqvar.segments[0].ident.name,
+                                (None, self.cx.typeck_results().node_type(seqexpr.hir_id)),
+                            );
                         }
-                        _ => (),
+                        return false;  // no need to walk further *on the variable*
                     }
+                    _ => (),
                 }
             }
         }
@@ -312,7 +310,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             // a range index op
-            if let ExprKind::MethodCall(ref meth, _, ref args, _) = expr.kind;
+            if let ExprKind::MethodCall(meth, _, args, _) = expr.kind;
             if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX))
                 || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
             if !self.check(&args[1], &args[0], expr);
@@ -321,7 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
 
         if_chain! {
             // an index op
-            if let ExprKind::Index(ref seqexpr, ref idx) = expr.kind;
+            if let ExprKind::Index(seqexpr, idx) = expr.kind;
             if !self.check(idx, seqexpr, expr);
             then { return }
         }
@@ -342,19 +340,19 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
 
         let old = self.prefer_mutable;
         match expr.kind {
-            ExprKind::AssignOp(_, ref lhs, ref rhs) | ExprKind::Assign(ref lhs, ref rhs, _) => {
+            ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
                 self.prefer_mutable = true;
                 self.visit_expr(lhs);
                 self.prefer_mutable = false;
                 self.visit_expr(rhs);
             },
-            ExprKind::AddrOf(BorrowKind::Ref, mutbl, ref expr) => {
+            ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => {
                 if mutbl == Mutability::Mut {
                     self.prefer_mutable = true;
                 }
                 self.visit_expr(expr);
             },
-            ExprKind::Call(ref f, args) => {
+            ExprKind::Call(f, args) => {
                 self.visit_expr(f);
                 for expr in args {
                     let ty = self.cx.typeck_results().expr_ty_adjusted(expr);
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index 01a7627fc7f..96720764e16 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -5,7 +5,7 @@ use rustc_lint::LateContext;
 use std::iter::{once, Iterator};
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    if let ExprKind::Loop(ref block, _, _, _) = expr.kind {
+    if let ExprKind::Loop(block, _, _, _) = expr.kind {
         match never_loop_block(block, expr.hir_id) {
             NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
             NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
@@ -76,36 +76,36 @@ fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_lo
 
 fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     match stmt.kind {
-        StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e),
-        StmtKind::Local(ref local) => local.init.as_deref(),
+        StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some(e),
+        StmtKind::Local(local) => local.init.as_deref(),
         StmtKind::Item(..) => None,
     }
 }
 
 fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
     match expr.kind {
-        ExprKind::Box(ref e)
-        | ExprKind::Unary(_, ref e)
-        | ExprKind::Cast(ref e, _)
-        | ExprKind::Type(ref e, _)
-        | ExprKind::Field(ref e, _)
-        | ExprKind::AddrOf(_, _, ref e)
-        | ExprKind::Struct(_, _, Some(ref e))
-        | ExprKind::Repeat(ref e, _)
-        | ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id),
-        ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es, _) | ExprKind::Tup(ref es) => {
+        ExprKind::Box(e)
+        | ExprKind::Unary(_, e)
+        | ExprKind::Cast(e, _)
+        | ExprKind::Type(e, _)
+        | ExprKind::Field(e, _)
+        | ExprKind::AddrOf(_, _, e)
+        | ExprKind::Struct(_, _, Some(e))
+        | ExprKind::Repeat(e, _)
+        | ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id),
+        ExprKind::Array(es) | ExprKind::MethodCall(_, _, es, _) | ExprKind::Tup(es) => {
             never_loop_expr_all(&mut es.iter(), main_loop_id)
         },
-        ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
-        ExprKind::Binary(_, ref e1, ref e2)
-        | ExprKind::Assign(ref e1, ref e2, _)
-        | ExprKind::AssignOp(_, ref e1, ref e2)
-        | ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
-        ExprKind::Loop(ref b, _, _, _) => {
+        ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), main_loop_id),
+        ExprKind::Binary(_, e1, e2)
+        | ExprKind::Assign(e1, e2, _)
+        | ExprKind::AssignOp(_, e1, e2)
+        | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().cloned(), main_loop_id),
+        ExprKind::Loop(b, _, _, _) => {
             // Break can come from the inner loop so remove them.
             absorb_break(&never_loop_block(b, main_loop_id))
         },
-        ExprKind::If(ref e, ref e2, ref e3) => {
+        ExprKind::If(e, e2, ref e3) => {
             let e1 = never_loop_expr(e, main_loop_id);
             let e2 = never_loop_expr(e2, main_loop_id);
             let e3 = e3
@@ -113,7 +113,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
                 .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
             combine_seq(e1, combine_branches(e2, e3))
         },
-        ExprKind::Match(ref e, ref arms, _) => {
+        ExprKind::Match(e, arms, _) => {
             let e = never_loop_expr(e, main_loop_id);
             if arms.is_empty() {
                 e
@@ -122,7 +122,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
                 combine_seq(e, arms)
             }
         },
-        ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id),
+        ExprKind::Block(b, _) => never_loop_block(b, main_loop_id),
         ExprKind::Continue(d) => {
             let id = d
                 .target_id
@@ -136,7 +136,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         ExprKind::Break(_, ref e) | ExprKind::Ret(ref e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| {
             combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)
         }),
-        ExprKind::InlineAsm(ref asm) => asm
+        ExprKind::InlineAsm(asm) => asm
             .operands
             .iter()
             .map(|(o, _)| match o {
diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs
index 849d7ec718c..cb2c83e9029 100644
--- a/clippy_lints/src/loops/same_item_push.rs
+++ b/clippy_lints/src/loops/same_item_push.rs
@@ -1,11 +1,13 @@
 use super::SAME_ITEM_PUSH;
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::path_to_local;
 use clippy_utils::source::snippet_with_macro_callsite;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
-use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Node, Pat, PatKind, Stmt, StmtKind};
+use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
 use rustc_span::symbol::sym;
@@ -41,59 +43,55 @@ pub(super) fn check<'tcx>(
     }
 
     // Determine whether it is safe to lint the body
-    let mut same_item_push_visitor = SameItemPushVisitor {
-        should_lint: true,
-        vec_push: None,
-        cx,
-    };
+    let mut same_item_push_visitor = SameItemPushVisitor::new(cx);
     walk_expr(&mut same_item_push_visitor, body);
-    if same_item_push_visitor.should_lint {
-        if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push {
-            let vec_ty = cx.typeck_results().expr_ty(vec);
-            let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
-            if cx
-                .tcx
-                .lang_items()
-                .clone_trait()
-                .map_or(false, |id| implements_trait(cx, ty, id, &[]))
-            {
-                // Make sure that the push does not involve possibly mutating values
-                match pushed_item.kind {
-                    ExprKind::Path(ref qpath) => {
-                        match cx.qpath_res(qpath, pushed_item.hir_id) {
-                            // immutable bindings that are initialized with literal or constant
-                            Res::Local(hir_id) => {
-                                if_chain! {
-                                    let node = cx.tcx.hir().get(hir_id);
-                                    if let Node::Binding(pat) = node;
-                                    if let PatKind::Binding(bind_ann, ..) = pat.kind;
-                                    if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
-                                    let parent_node = cx.tcx.hir().get_parent_node(hir_id);
-                                    if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
-                                    if let Some(init) = parent_let_expr.init;
-                                    then {
-                                        match init.kind {
-                                            // immutable bindings that are initialized with literal
-                                            ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
-                                            // immutable bindings that are initialized with constant
-                                            ExprKind::Path(ref path) => {
-                                                if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
-                                                    emit_lint(cx, vec, pushed_item);
-                                                }
+    if_chain! {
+        if same_item_push_visitor.should_lint();
+        if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push;
+        let vec_ty = cx.typeck_results().expr_ty(vec);
+        let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
+        if cx
+            .tcx
+            .lang_items()
+            .clone_trait()
+            .map_or(false, |id| implements_trait(cx, ty, id, &[]));
+        then {
+            // Make sure that the push does not involve possibly mutating values
+            match pushed_item.kind {
+                ExprKind::Path(ref qpath) => {
+                    match cx.qpath_res(qpath, pushed_item.hir_id) {
+                        // immutable bindings that are initialized with literal or constant
+                        Res::Local(hir_id) => {
+                            let node = cx.tcx.hir().get(hir_id);
+                            if_chain! {
+                                if let Node::Binding(pat) = node;
+                                if let PatKind::Binding(bind_ann, ..) = pat.kind;
+                                if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
+                                let parent_node = cx.tcx.hir().get_parent_node(hir_id);
+                                if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
+                                if let Some(init) = parent_let_expr.init;
+                                then {
+                                    match init.kind {
+                                        // immutable bindings that are initialized with literal
+                                        ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
+                                        // immutable bindings that are initialized with constant
+                                        ExprKind::Path(ref path) => {
+                                            if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
+                                                emit_lint(cx, vec, pushed_item);
                                             }
-                                            _ => {},
                                         }
+                                        _ => {},
                                     }
                                 }
-                            },
-                            // constant
-                            Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item),
-                            _ => {},
-                        }
-                    },
-                    ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
-                    _ => {},
-                }
+                            }
+                        },
+                        // constant
+                        Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item),
+                        _ => {},
+                    }
+                },
+                ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
+                _ => {},
             }
         }
     }
@@ -101,10 +99,38 @@ pub(super) fn check<'tcx>(
 
 // Scans the body of the for loop and determines whether lint should be given
 struct SameItemPushVisitor<'a, 'tcx> {
-    should_lint: bool,
+    non_deterministic_expr: bool,
+    multiple_pushes: bool,
     // this field holds the last vec push operation visited, which should be the only push seen
     vec_push: Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>,
     cx: &'a LateContext<'tcx>,
+    used_locals: FxHashSet<HirId>,
+}
+
+impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> {
+    fn new(cx: &'a LateContext<'tcx>) -> Self {
+        Self {
+            non_deterministic_expr: false,
+            multiple_pushes: false,
+            vec_push: None,
+            cx,
+            used_locals: FxHashSet::default(),
+        }
+    }
+
+    fn should_lint(&self) -> bool {
+        if_chain! {
+            if !self.non_deterministic_expr;
+            if !self.multiple_pushes;
+            if let Some((vec, _)) = self.vec_push;
+            if let Some(hir_id) = path_to_local(vec);
+            then {
+                !self.used_locals.contains(&hir_id)
+            } else {
+                false
+            }
+        }
+    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
@@ -113,9 +139,14 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         match &expr.kind {
             // Non-determinism may occur ... don't give a lint
-            ExprKind::Loop(..) | ExprKind::Match(..) => self.should_lint = false,
+            ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::If(..) => self.non_deterministic_expr = true,
             ExprKind::Block(block, _) => self.visit_block(block),
-            _ => {},
+            _ => {
+                if let Some(hir_id) = path_to_local(expr) {
+                    self.used_locals.insert(hir_id);
+                }
+                walk_expr(self, expr);
+            },
         }
     }
 
@@ -130,7 +161,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
         if vec_push_option.is_none() {
             // Current statement is not a push so visit inside
             match &s.kind {
-                StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(&expr),
+                StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(expr),
                 _ => {},
             }
         } else {
@@ -140,7 +171,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
                 self.vec_push = vec_push_option;
             } else {
                 // There are multiple pushes ... don't lint
-                self.should_lint = false;
+                self.multiple_pushes = true;
             }
         }
     }
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs
index 8451c1c6130..fc067e81bca 100644
--- a/clippy_lints/src/loops/single_element_loop.rs
+++ b/clippy_lints/src/loops/single_element_loop.rs
@@ -15,12 +15,12 @@ pub(super) fn check<'tcx>(
     expr: &'tcx Expr<'_>,
 ) {
     if_chain! {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg_expr) = arg.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, arg_expr) = arg.kind;
         if let PatKind::Binding(.., target, _) = pat.kind;
         if let ExprKind::Array([arg_expression]) = arg_expr.kind;
         if let ExprKind::Path(ref list_item) = arg_expression.kind;
         if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
-        if let ExprKind::Block(ref block, _) = body.kind;
+        if let ExprKind::Block(block, _) = body.kind;
         if !block.stmts.is_empty();
 
         then {
diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs
index bb409c48532..4db6644b9d7 100644
--- a/clippy_lints/src/loops/utils.rs
+++ b/clippy_lints/src/loops/utils.rs
@@ -1,9 +1,9 @@
 use clippy_utils::ty::{has_iter_method, implements_trait};
 use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
 use if_chain::if_chain;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
+use rustc_hir::HirIdMap;
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
@@ -20,9 +20,9 @@ enum IncrementVisitorVarState {
 
 /// Scan a for loop for variables that are incremented exactly once and not used after that.
 pub(super) struct IncrementVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,                          // context reference
-    states: FxHashMap<HirId, IncrementVisitorVarState>, // incremented variables
-    depth: u32,                                         // depth of conditional expressions
+    cx: &'a LateContext<'tcx>,                  // context reference
+    states: HirIdMap<IncrementVisitorVarState>, // incremented variables
+    depth: u32,                                 // depth of conditional expressions
     done: bool,
 }
 
@@ -30,7 +30,7 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
     pub(super) fn new(cx: &'a LateContext<'tcx>) -> Self {
         Self {
             cx,
-            states: FxHashMap::default(),
+            states: HirIdMap::default(),
             depth: 0,
             done: false,
         }
@@ -65,7 +65,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
                 }
 
                 match parent.kind {
-                    ExprKind::AssignOp(op, ref lhs, ref rhs) => {
+                    ExprKind::AssignOp(op, lhs, rhs) => {
                         if lhs.hir_id == expr.hir_id {
                             *state = if op.node == BinOpKind::Add
                                 && is_integer_const(self.cx, rhs, 1)
@@ -79,7 +79,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
                             };
                         }
                     },
-                    ExprKind::Assign(ref lhs, _, _) if lhs.hir_id == expr.hir_id => {
+                    ExprKind::Assign(lhs, _, _) if lhs.hir_id == expr.hir_id => {
                         *state = IncrementVisitorVarState::DontWarn
                     },
                     ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
@@ -153,7 +153,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         // Look for declarations of the variable
         if_chain! {
-            if let StmtKind::Local(ref local) = stmt.kind;
+            if let StmtKind::Local(local) = stmt.kind;
             if local.pat.hir_id == self.var_id;
             if let PatKind::Binding(.., ident, _) = local.pat.kind;
             then {
@@ -191,10 +191,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
 
             if let Some(parent) = get_parent_expr(self.cx, expr) {
                 match parent.kind {
-                    ExprKind::AssignOp(_, ref lhs, _) if lhs.hir_id == expr.hir_id => {
+                    ExprKind::AssignOp(_, lhs, _) if lhs.hir_id == expr.hir_id => {
                         self.state = InitializeVisitorState::DontWarn;
                     },
-                    ExprKind::Assign(ref lhs, ref rhs, _) if lhs.hir_id == expr.hir_id => {
+                    ExprKind::Assign(lhs, rhs, _) if lhs.hir_id == expr.hir_id => {
                         self.state = if_chain! {
                             if self.depth == 0;
                             if let InitializeVisitorState::Declared(name)
@@ -273,7 +273,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
             return;
         }
         match expr.kind {
-            ExprKind::Assign(ref path, _, _) | ExprKind::AssignOp(_, ref path, _) => {
+            ExprKind::Assign(path, _, _) | ExprKind::AssignOp(_, path, _) => {
                 if path_to_local_id(path, self.iterator) {
                     self.nesting = RuledOut;
                 }
@@ -327,7 +327,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
         // (&mut x).into_iter() ==> x.iter_mut()
         match &arg.kind {
             ExprKind::AddrOf(BorrowKind::Ref, mutability, arg_inner)
-                if has_iter_method(cx, cx.typeck_results().expr_ty(&arg_inner)).is_some() =>
+                if has_iter_method(cx, cx.typeck_results().expr_ty(arg_inner)).is_some() =>
             {
                 let meth_name = match mutability {
                     Mutability::Mut => "iter_mut",
@@ -335,7 +335,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
                 };
                 format!(
                     "{}.{}()",
-                    sugg::Sugg::hir_with_applicability(cx, &arg_inner, "_", applic_ref).maybe_par(),
+                    sugg::Sugg::hir_with_applicability(cx, arg_inner, "_", applic_ref).maybe_par(),
                     meth_name,
                 )
             }
diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs
index cad9ff8489a..de267cc77d2 100644
--- a/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/clippy_lints/src/loops/while_immutable_condition.rs
@@ -3,13 +3,13 @@ use crate::consts::constant;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::usage::mutated_variables;
 use if_chain::if_chain;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefIdMap;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
-use rustc_hir::{def_id, Expr, ExprKind, HirId, QPath};
+use rustc_hir::HirIdSet;
+use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
-use std::iter::Iterator;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
     if constant(cx, cx.typeck_results(), cond).is_some() {
@@ -19,8 +19,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'
 
     let mut var_visitor = VarCollectorVisitor {
         cx,
-        ids: FxHashSet::default(),
-        def_ids: FxHashMap::default(),
+        ids: HirIdSet::default(),
+        def_ids: DefIdMap::default(),
         skip: false,
     };
     var_visitor.visit_expr(cond);
@@ -93,8 +93,8 @@ impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
 /// All variables definition IDs are collected
 struct VarCollectorVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    ids: FxHashSet<HirId>,
-    def_ids: FxHashMap<def_id::DefId, bool>,
+    ids: HirIdSet,
+    def_ids: DefIdMap<bool>,
     skip: bool,
 }
 
@@ -103,9 +103,8 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
         if_chain! {
             if let ExprKind::Path(ref qpath) = ex.kind;
             if let QPath::Resolved(None, _) = *qpath;
-            let res = self.cx.qpath_res(qpath, ex.hir_id);
             then {
-                match res {
+                match self.cx.qpath_res(qpath, ex.hir_id) {
                     Res::Local(hir_id) => {
                         self.ids.insert(hir_id);
                     },
diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs
index ffe8c0c5494..9c172079852 100644
--- a/clippy_lints/src/loops/while_let_loop.rs
+++ b/clippy_lints/src/loops/while_let_loop.rs
@@ -11,14 +11,14 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'
     let inner_stmt_expr = extract_expr_from_first_stmt(loop_block);
     // or extract the first expression (if any) from the block
     if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(loop_block)) {
-        if let ExprKind::Match(ref matchexpr, ref arms, ref source) = inner.kind {
+        if let ExprKind::Match(matchexpr, arms, ref source) = inner.kind {
             // ensure "if let" compatible match structure
             match *source {
                 MatchSource::Normal | MatchSource::IfLetDesugar { .. } => {
                     if arms.len() == 2
                         && arms[0].guard.is_none()
                         && arms[1].guard.is_none()
-                        && is_simple_break_expr(&arms[1].body)
+                        && is_simple_break_expr(arms[1].body)
                     {
                         if in_external_macro(cx.sess(), expr.span) {
                             return;
@@ -57,7 +57,7 @@ fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<
     if block.stmts.is_empty() {
         return None;
     }
-    if let StmtKind::Local(ref local) = block.stmts[0].kind {
+    if let StmtKind::Local(local) = block.stmts[0].kind {
         local.init //.map(|expr| expr)
     } else {
         None
@@ -67,9 +67,9 @@ fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<
 /// If a block begins with an expression (with or without semicolon), return it.
 fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     match block.expr {
-        Some(ref expr) if block.stmts.is_empty() => Some(expr),
+        Some(expr) if block.stmts.is_empty() => Some(expr),
         None if !block.stmts.is_empty() => match block.stmts[0].kind {
-            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => Some(expr),
+            StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some(expr),
             StmtKind::Local(..) | StmtKind::Item(..) => None,
         },
         _ => None,
@@ -82,7 +82,7 @@ fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 fn is_simple_break_expr(expr: &Expr<'_>) -> bool {
     match expr.kind {
         ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true,
-        ExprKind::Block(ref b, _) => extract_first_expr(b).map_or(false, |subexpr| is_simple_break_expr(subexpr)),
+        ExprKind::Block(b, _) => extract_first_expr(b).map_or(false, |subexpr| is_simple_break_expr(subexpr)),
         _ => false,
     }
 }
diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs
index 57fc6250a9a..82715d9bafa 100644
--- a/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -16,12 +16,10 @@ use rustc_middle::hir::map::Map;
 use rustc_span::symbol::sym;
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    if let ExprKind::Match(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.kind {
+    if let ExprKind::Match(match_expr, arms, MatchSource::WhileLetDesugar) = expr.kind {
         let pat = &arms[0].pat.kind;
-        if let (
-            &PatKind::TupleStruct(ref qpath, ref pat_args, _),
-            &ExprKind::MethodCall(ref method_path, _, ref method_args, _),
-        ) = (pat, &match_expr.kind)
+        if let (&PatKind::TupleStruct(ref qpath, pat_args, _), &ExprKind::MethodCall(method_path, _, method_args, _)) =
+            (pat, &match_expr.kind)
         {
             let iter_expr = &method_args[0];
 
@@ -40,8 +38,8 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 && is_trait_method(cx, match_expr, sym::Iterator)
                 && lhs_constructor.ident.name == sym::Some
                 && (pat_args.is_empty()
-                    || !is_refutable(cx, &pat_args[0])
-                        && !is_used_inside(cx, iter_expr, &arms[0].body)
+                    || !is_refutable(cx, pat_args[0])
+                        && !is_used_inside(cx, iter_expr, arms[0].body)
                         && !is_iterator_used_after_while_let(cx, iter_expr)
                         && !is_nested(cx, expr, &method_args[0]))
             {
diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs
index d573c297838..c506d52e746 100644
--- a/clippy_lints/src/macro_use.rs
+++ b/clippy_lints/src/macro_use.rs
@@ -9,7 +9,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{edition::Edition, Span};
+use rustc_span::{edition::Edition, sym, Span};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for `#[macro_use] use...`.
@@ -110,9 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
             if cx.sess().opts.edition >= Edition::Edition2018;
             if let hir::ItemKind::Use(path, _kind) = &item.kind;
             let attrs = cx.tcx.hir().attrs(item.hir_id());
-            if let Some(mac_attr) = attrs
-                .iter()
-                .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
+            if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use));
             if let Res::Def(DefKind::Mod, id) = path.res;
             then {
                 for kid in cx.tcx.item_children(id).iter() {
diff --git a/clippy_lints/src/manual_map.rs b/clippy_lints/src/manual_map.rs
index ed157783b72..8c9e3af62f4 100644
--- a/clippy_lints/src/manual_map.rs
+++ b/clippy_lints/src/manual_map.rs
@@ -2,7 +2,7 @@ use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::ty::{can_partially_move_ty, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
-use clippy_utils::{is_allowed, is_else_clause_of_if_let_else, match_def_path, match_var, paths, peel_hir_expr_refs};
+use clippy_utils::{in_constant, is_allowed, is_else_clause, match_def_path, match_var, paths, peel_hir_expr_refs};
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -47,16 +47,16 @@ declare_lint_pass!(ManualMap => [MANUAL_MAP]);
 impl LateLintPass<'_> for ManualMap {
     #[allow(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if in_external_macro(cx.sess(), expr.span) {
-            return;
-        }
-
         if let ExprKind::Match(
             scrutinee,
             [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }],
             match_kind,
         ) = expr.kind
         {
+            if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) {
+                return;
+            }
+
             let (scrutinee_ty, ty_ref_count, ty_mutability) =
                 peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee));
             if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::option_type)
@@ -181,8 +181,7 @@ impl LateLintPass<'_> for ManualMap {
                 expr.span,
                 "manual implementation of `Option::map`",
                 "try this",
-                if matches!(match_kind, MatchSource::IfLetDesugar { .. }) && is_else_clause_of_if_let_else(cx.tcx, expr)
-                {
+                if matches!(match_kind, MatchSource::IfLetDesugar { .. }) && is_else_clause(cx.tcx, expr) {
                     format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str)
                 } else {
                     format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str)
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 95261580b8e..dc19805b50a 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,9 +1,9 @@
+use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::meets_msrv;
 use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
-use rustc_ast::ast::{Attribute, FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind};
-use rustc_attr as attr;
+use rustc_ast::ast::{FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_semver::RustcVersion;
@@ -102,19 +102,11 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants
     fn is_non_exhaustive_marker(variant: &Variant) -> bool {
         matches!(variant.data, VariantData::Unit(_))
             && variant.ident.as_str().starts_with('_')
-            && variant.attrs.iter().any(|a| is_doc_hidden(a))
-    }
-
-    fn is_doc_hidden(attr: &Attribute) -> bool {
-        attr.has_name(sym::doc)
-            && match attr.meta_item_list() {
-                Some(l) => attr::list_contains_name(&l, sym::hidden),
-                None => false,
-            }
+            && is_doc_hidden(&variant.attrs)
     }
 
+    let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v));
     if_chain! {
-        let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v));
         if let Some(marker) = markers.next();
         if markers.count() == 0 && variants.len() > 1;
         then {
diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs
index 9da37efddac..dfa464ddb81 100644
--- a/clippy_lints/src/manual_strip.rs
+++ b/clippy_lints/src/manual_strip.rs
@@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
                 } else {
                     return;
                 };
-                let target_res = cx.qpath_res(&target_path, target_arg.hir_id);
+                let target_res = cx.qpath_res(target_path, target_arg.hir_id);
                 if target_res == Res::Err {
                     return;
                 };
@@ -174,7 +174,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t
 
 // Tests if `expr` is a `&str`.
 fn is_ref_str(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    match cx.typeck_results().expr_ty_adjusted(&expr).kind() {
+    match cx.typeck_results().expr_ty_adjusted(expr).kind() {
         ty::Ref(_, ty, _) => ty.is_str(),
         _ => false,
     }
diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs
index cfcc705eabc..99c35ae3bbf 100644
--- a/clippy_lints/src/map_clone.rs
+++ b/clippy_lints/src/map_clone.rs
@@ -52,17 +52,17 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
         }
 
         if_chain! {
-            if let hir::ExprKind::MethodCall(ref method, _, ref args, _) = e.kind;
+            if let hir::ExprKind::MethodCall(method, _, args, _) = e.kind;
             if args.len() == 2;
             if method.ident.name == sym::map;
             let ty = cx.typeck_results().expr_ty(&args[0]);
             if is_type_diagnostic_item(cx, ty, sym::option_type) || is_trait_method(cx, e, sym::Iterator);
             if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind;
-            let closure_body = cx.tcx.hir().body(body_id);
-            let closure_expr = remove_blocks(&closure_body.value);
             then {
+                let closure_body = cx.tcx.hir().body(body_id);
+                let closure_expr = remove_blocks(&closure_body.value);
                 match closure_body.params[0].pat.kind {
-                    hir::PatKind::Ref(ref inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
+                    hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
                         hir::BindingAnnotation::Unannotated, .., name, None
                     ) = inner.kind {
                         if ident_eq(name, closure_expr) {
@@ -71,14 +71,14 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
                     },
                     hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => {
                         match closure_expr.kind {
-                            hir::ExprKind::Unary(hir::UnOp::Deref, ref inner) => {
+                            hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
                                 if ident_eq(name, inner) {
                                     if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() {
                                         lint(cx, e.span, args[0].span, true);
                                     }
                                 }
                             },
-                            hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! {
+                            hir::ExprKind::MethodCall(method, _, [obj], _) => if_chain! {
                                 if ident_eq(name, obj) && method.ident.name == sym::clone;
                                 if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id);
                                 if let Some(trait_id) = cx.tcx.trait_of_item(fn_id);
@@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
 }
 
 fn ident_eq(name: Ident, path: &hir::Expr<'_>) -> bool {
-    if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.kind {
+    if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = path.kind {
         path.segments.len() == 1 && path.segments[0].ident == name
     } else {
         false
diff --git a/clippy_lints/src/map_err_ignore.rs b/clippy_lints/src/map_err_ignore.rs
index a6a63961be5..425a9734e5f 100644
--- a/clippy_lints/src/map_err_ignore.rs
+++ b/clippy_lints/src/map_err_ignore.rs
@@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
         }
 
         // check if this is a method call (e.g. x.foo())
-        if let ExprKind::MethodCall(ref method, _t_span, ref args, _) = e.kind {
+        if let ExprKind::MethodCall(method, _t_span, args, _) = e.kind {
             // only work if the method name is `map_err` and there are only 2 arguments (e.g. x.map_err(|_|[1]
             // Enum::Variant[2]))
             if method.ident.as_str() == "map_err" && args.len() == 2 {
diff --git a/clippy_lints/src/map_identity.rs b/clippy_lints/src/map_identity.rs
index 75191e1f9ee..e7719e7663d 100644
--- a/clippy_lints/src/map_identity.rs
+++ b/clippy_lints/src/map_identity.rs
@@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for MapIdentity {
 /// map(). Otherwise, returns None.
 fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> {
     if_chain! {
-        if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
+        if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
         if args.len() == 2 && method.ident.name == sym::map;
         let caller_ty = cx.typeck_results().expr_ty(&args[0]);
         if is_trait_method(cx, expr, sym::Iterator)
@@ -80,7 +80,7 @@ fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a
 fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match expr.kind {
         ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
-        ExprKind::Path(QPath::Resolved(_, ref path)) => match_path(path, &paths::STD_CONVERT_IDENTITY),
+        ExprKind::Path(QPath::Resolved(_, path)) => match_path(path, &paths::STD_CONVERT_IDENTITY),
         _ => false,
     }
 }
@@ -99,12 +99,12 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
 
     match body.kind {
         ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat),
-        ExprKind::Ret(Some(ref ret_val)) => match_expr_param(cx, ret_val, params[0].pat),
-        ExprKind::Block(ref block, _) => {
+        ExprKind::Ret(Some(ret_val)) => match_expr_param(cx, ret_val, params[0].pat),
+        ExprKind::Block(block, _) => {
             if_chain! {
                 if block.stmts.len() == 1;
-                if let StmtKind::Semi(ref expr) | StmtKind::Expr(ref expr) = block.stmts[0].kind;
-                if let ExprKind::Ret(Some(ref ret_val)) = expr.kind;
+                if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = block.stmts[0].kind;
+                if let ExprKind::Ret(Some(ret_val)) = expr.kind;
                 then {
                     match_expr_param(cx, ret_val, params[0].pat)
                 } else {
diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index d4764b5ccff..57cd907e77e 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/clippy_lints/src/map_unit_fn.rs
@@ -133,7 +133,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) ->
             // Calls can't be reduced any more
             Some(expr.span)
         },
-        hir::ExprKind::Block(ref block, _) => {
+        hir::ExprKind::Block(block, _) => {
             match (block.stmts, block.expr.as_ref()) {
                 (&[], Some(inner_expr)) => {
                     // If block only contains an expression,
@@ -144,8 +144,8 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) ->
                     // If block only contains statements,
                     // reduce `{ X; }` to `X` or `X;`
                     match inner_stmt.kind {
-                        hir::StmtKind::Local(ref local) => Some(local.span),
-                        hir::StmtKind::Expr(ref e) => Some(e.span),
+                        hir::StmtKind::Local(local) => Some(local.span),
+                        hir::StmtKind::Expr(e) => Some(e.span),
                         hir::StmtKind::Semi(..) => Some(inner_stmt.span),
                         hir::StmtKind::Item(..) => None,
                     }
@@ -168,17 +168,15 @@ fn unit_closure<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &hir::Expr<'_>,
 ) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
-    if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.kind {
+    if_chain! {
+        if let hir::ExprKind::Closure(_, decl, inner_expr_id, _, _) = expr.kind;
         let body = cx.tcx.hir().body(inner_expr_id);
         let body_expr = &body.value;
-
-        if_chain! {
-            if decl.inputs.len() == 1;
-            if is_unit_expression(cx, body_expr);
-            if let Some(binding) = iter_input_pats(&decl, body).next();
-            then {
-                return Some((binding, body_expr));
-            }
+        if decl.inputs.len() == 1;
+        if is_unit_expression(cx, body_expr);
+        if let Some(binding) = iter_input_pats(decl, body).next();
+        then {
+            return Some((binding, body_expr));
         }
     }
     None
@@ -269,7 +267,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnit {
             return;
         }
 
-        if let hir::StmtKind::Semi(ref expr) = stmt.kind {
+        if let hir::StmtKind::Semi(expr) = stmt.kind {
             if let Some(arglists) = method_chain_args(expr, &["map"]) {
                 lint_map_unit_fn(cx, stmt, expr, arglists[0]);
             }
diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs
index ccaa5e98c83..ca6fb0831fe 100644
--- a/clippy_lints/src/match_on_vec_items.rs
+++ b/clippy_lints/src/match_on_vec_items.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchOnVecItems {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if_chain! {
             if !in_external_macro(cx.sess(), expr.span);
-            if let ExprKind::Match(ref match_expr, _, MatchSource::Normal) = expr.kind;
+            if let ExprKind::Match(match_expr, _, MatchSource::Normal) = expr.kind;
             if let Some(idx_expr) = is_vec_indexing(cx, match_expr);
             if let ExprKind::Index(vec, idx) = idx_expr.kind;
 
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchOnVecItems {
 
 fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     if_chain! {
-        if let ExprKind::Index(ref array, ref index) = expr.kind;
+        if let ExprKind::Index(array, index) = expr.kind;
         if is_vector(cx, array);
         if !is_full_range(cx, index);
 
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 2f2dc4cfc6b..c8ee0abd3df 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -13,13 +13,13 @@ use clippy_utils::{
 use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::{
     self as hir, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, HirId, Local, MatchSource,
     Mutability, Node, Pat, PatKind, PathSegment, QPath, RangeEnd, TyKind,
 };
+use rustc_hir::{HirIdMap, HirIdSet};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty, TyS, VariantDef};
@@ -590,7 +590,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
             lint_match_arms(cx, expr);
         }
 
-        if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.kind {
+        if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind {
             check_single_match(cx, ex, arms, expr);
             check_match_bool(cx, ex, arms, expr);
             check_overlapping_arms(cx, ex, arms);
@@ -605,7 +605,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
                 check_match_single_binding(cx, ex, arms, expr);
             }
         }
-        if let ExprKind::Match(ref ex, ref arms, _) = expr.kind {
+        if let ExprKind::Match(ex, arms, _) = expr.kind {
             check_match_ref_pats(cx, ex, arms, expr);
         }
     }
@@ -614,14 +614,14 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
         if_chain! {
             if !in_external_macro(cx.sess(), local.span);
             if !in_macro(local.span);
-            if let Some(ref expr) = local.init;
-            if let ExprKind::Match(ref target, ref arms, MatchSource::Normal) = expr.kind;
+            if let Some(expr) = local.init;
+            if let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind;
             if arms.len() == 1 && arms[0].guard.is_none();
             if let PatKind::TupleStruct(
-                QPath::Resolved(None, ref variant_name), ref args, _) = arms[0].pat.kind;
+                QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind;
             if args.len() == 1;
-            if let PatKind::Binding(_, arg, ..) = strip_pat_refs(&args[0]).kind;
-            let body = remove_blocks(&arms[0].body);
+            if let PatKind::Binding(_, arg, ..) = strip_pat_refs(args[0]).kind;
+            let body = remove_blocks(arms[0].body);
             if path_to_local_id(body, arg);
 
             then {
@@ -650,7 +650,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
         if_chain! {
             if !in_external_macro(cx.sess(), pat.span);
             if !in_macro(pat.span);
-            if let PatKind::Struct(QPath::Resolved(_, ref path), fields, true) = pat.kind;
+            if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind;
             if let Some(def_id) = path.res.opt_def_id();
             let ty = cx.tcx.type_of(def_id);
             if let ty::Adt(def, _) = ty.kind();
@@ -733,8 +733,8 @@ fn report_single_match_single_pattern(
         format!(" else {}", expr_block(cx, els, None, "..", Some(expr.span)))
     });
 
+    let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat);
     let (msg, sugg) = if_chain! {
-        let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat);
         if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind;
         let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex));
         if let Some(trait_id) = cx.tcx.lang_items().structural_peq_trait();
@@ -762,7 +762,7 @@ fn report_single_match_single_pattern(
                 // PartialEq for different reference counts may not exist.
                 "&".repeat(ref_count_diff),
                 snippet(cx, arms[0].pat.span, ".."),
-                expr_block(cx, &arms[0].body, None, "..", Some(expr.span)),
+                expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
                 els_str,
             );
             (msg, sugg)
@@ -772,7 +772,7 @@ fn report_single_match_single_pattern(
                 "if let {} = {} {}{}",
                 snippet(cx, arms[0].pat.span, ".."),
                 snippet(cx, ex.span, ".."),
-                expr_block(cx, &arms[0].body, None, "..", Some(expr.span)),
+                expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
                 els_str,
             );
             (msg, sugg)
@@ -810,7 +810,7 @@ fn check_single_match_opt_like(
     ];
 
     let path = match arms[1].pat.kind {
-        PatKind::TupleStruct(ref path, ref inner, _) => {
+        PatKind::TupleStruct(ref path, inner, _) => {
             // Contains any non wildcard patterns (e.g., `Err(err)`)?
             if !inner.iter().all(is_wild) {
                 return;
@@ -842,7 +842,7 @@ fn check_match_bool(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
             move |diag| {
                 if arms.len() == 2 {
                     // no guards
-                    let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pat.kind {
+                    let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
                         if let ExprKind::Lit(ref lit) = arm_bool.kind {
                             match lit.node {
                                 LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)),
@@ -918,14 +918,14 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
     let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs();
     if is_type_diagnostic_item(cx, ex_ty, sym::result_type) {
         for arm in arms {
-            if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pat.kind {
+            if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
                 let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false));
                 if path_str == "Err" {
                     let mut matching_wild = inner.iter().any(is_wild);
                     let mut ident_bind_name = String::from("_");
                     if !matching_wild {
                         // Looking for unused bindings (i.e.: `_e`)
-                        inner.iter().for_each(|pat| {
+                        for pat in inner.iter() {
                             if let PatKind::Binding(_, id, ident, None) = pat.kind {
                                 if ident.as_str().starts_with('_')
                                     && !LocalUsedVisitor::new(cx, id).check_expr(arm.body)
@@ -934,11 +934,11 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
                                     matching_wild = true;
                                 }
                             }
-                        });
+                        }
                     }
                     if_chain! {
                         if matching_wild;
-                        if let ExprKind::Block(ref block, _) = arm.body.kind;
+                        if let ExprKind::Block(block, _) = arm.body.kind;
                         if is_panic_block(block);
                         then {
                             // `Err(_)` or `Err(_e)` arm with `panic!` found
@@ -984,6 +984,11 @@ impl CommonPrefixSearcher<'a> {
     }
 }
 
+fn is_doc_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool {
+    let attrs = cx.tcx.get_attrs(variant_def.def_id);
+    clippy_utils::attrs::is_doc_hidden(attrs)
+}
+
 #[allow(clippy::too_many_lines)]
 fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
     let ty = cx.typeck_results().expr_ty(ex).peel_refs();
@@ -1042,16 +1047,18 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                     path
                 },
                 PatKind::TupleStruct(path, patterns, ..) => {
-                    if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
-                        let id = cx.qpath_res(path, pat.hir_id).def_id();
-                        missing_variants.retain(|e| e.ctor_def_id != Some(id));
+                    if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
+                        if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
+                            missing_variants.retain(|e| e.ctor_def_id != Some(id));
+                        }
                     }
                     path
                 },
                 PatKind::Struct(path, patterns, ..) => {
-                    if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p.pat)) {
-                        let id = cx.qpath_res(path, pat.hir_id).def_id();
-                        missing_variants.retain(|e| e.def_id != id);
+                    if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
+                        if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p.pat)) {
+                            missing_variants.retain(|e| e.def_id != id);
+                        }
                     }
                     path
                 },
@@ -1103,7 +1110,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 
     match missing_variants.as_slice() {
         [] => (),
-        [x] if !adt_def.is_variant_list_non_exhaustive() => span_lint_and_sugg(
+        [x] if !adt_def.is_variant_list_non_exhaustive() && !is_doc_hidden(cx, x) => span_lint_and_sugg(
             cx,
             MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
             wildcard_span,
@@ -1137,9 +1144,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
 // If the block contains only a `panic!` macro (as expression or statement)
 fn is_panic_block(block: &Block<'_>) -> bool {
     match (&block.expr, block.stmts.len(), block.stmts.first()) {
-        (&Some(ref exp), 0, _) => {
-            is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none()
-        },
+        (&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(),
         (&None, 1, Some(stmt)) => {
             is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
         },
@@ -1150,7 +1155,7 @@ fn is_panic_block(block: &Block<'_>) -> bool {
 fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if has_only_ref_pats(arms) {
         let mut suggs = Vec::with_capacity(arms.len() + 1);
-        let (title, msg) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = ex.kind {
+        let (title, msg) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind {
             let span = ex.span.source_callsite();
             suggs.push((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string()));
             (
@@ -1167,7 +1172,7 @@ fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], e
         };
 
         suggs.extend(arms.iter().filter_map(|a| {
-            if let PatKind::Ref(ref refp, _) = a.pat.kind {
+            if let PatKind::Ref(refp, _) = a.pat.kind {
                 Some((a.pat.span, snippet(cx, refp.span, "..").to_string()))
             } else {
                 None
@@ -1236,7 +1241,7 @@ fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
 
 fn check_wild_in_or_pats(cx: &LateContext<'_>, arms: &[Arm<'_>]) {
     for arm in arms {
-        if let PatKind::Or(ref fields) = arm.pat.kind {
+        if let PatKind::Or(fields) = arm.pat.kind {
             // look for multiple fields in this arm that contains at least one Wild pattern
             if fields.len() > 1 && fields.iter().any(is_wild) {
                 span_lint_and_help(
@@ -1302,7 +1307,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
             // strip potential borrows (#6503), but only if the type is a reference
             let mut ex_new = ex;
             if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind {
-                if let ty::Ref(..) = cx.typeck_results().expr_ty(&ex_inner).kind() {
+                if let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() {
                     ex_new = ex_inner;
                 }
             };
@@ -1379,7 +1384,7 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A
 
     let matched_vars = ex.span;
     let bind_names = arms[0].pat.span;
-    let match_body = remove_blocks(&arms[0].body);
+    let match_body = remove_blocks(arms[0].body);
     let mut snippet_body = if match_body.span.from_expansion() {
         Sugg::hir_with_macro_callsite(cx, match_body, "..").to_string()
     } else {
@@ -1390,13 +1395,13 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A
     match match_body.kind {
         ExprKind::Block(block, _) => {
             // macro + expr_ty(body) == ()
-            if block.span.from_expansion() && cx.typeck_results().expr_ty(&match_body).is_unit() {
+            if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() {
                 snippet_body.push(';');
             }
         },
         _ => {
             // expr_ty(body) == ()
-            if cx.typeck_results().expr_ty(&match_body).is_unit() {
+            if cx.typeck_results().expr_ty(match_body).is_unit() {
                 snippet_body.push(';');
             }
         },
@@ -1481,8 +1486,8 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A
 
 /// Returns true if the `ex` match expression is in a local (`let`) statement
 fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'a>> {
+    let map = &cx.tcx.hir();
     if_chain! {
-        let map = &cx.tcx.hir();
         if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id));
         if let Some(Node::Local(parent_let_expr)) = map.find(map.get_parent_node(parent_arm_expr.hir_id));
         then {
@@ -1496,10 +1501,7 @@ fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'
 fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<Constant>> {
     arms.iter()
         .flat_map(|arm| {
-            if let Arm {
-                ref pat, guard: None, ..
-            } = *arm
-            {
+            if let Arm { pat, guard: None, .. } = *arm {
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs = match lhs {
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
@@ -1519,7 +1521,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                     });
                 }
 
-                if let PatKind::Lit(ref value) = pat.kind {
+                if let PatKind::Lit(value) = pat.kind {
                     let value = constant(cx, cx.typeck_results(), value)?.0;
                     return Some(SpannedRange {
                         span: pat.span,
@@ -1566,8 +1568,8 @@ fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges {
 
 fn is_unit_expr(expr: &Expr<'_>) -> bool {
     match expr.kind {
-        ExprKind::Tup(ref v) if v.is_empty() => true,
-        ExprKind::Block(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true,
+        ExprKind::Tup(v) if v.is_empty() => true,
+        ExprKind::Block(b, _) if b.stmts.is_empty() && b.expr.is_none() => true,
         _ => false,
     }
 }
@@ -1580,14 +1582,14 @@ fn is_none_arm(arm: &Arm<'_>) -> bool {
 // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
 fn is_ref_some_arm(arm: &Arm<'_>) -> Option<BindingAnnotation> {
     if_chain! {
-        if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pat.kind;
+        if let PatKind::TupleStruct(ref path, pats, _) = arm.pat.kind;
         if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME);
         if let PatKind::Binding(rb, .., ident, _) = pats[0].kind;
         if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
-        if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).kind;
+        if let ExprKind::Call(e, args) = remove_blocks(arm.body).kind;
         if let ExprKind::Path(ref some_path) = e.kind;
         if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1;
-        if let ExprKind::Path(QPath::Resolved(_, ref path2)) = args[0].kind;
+        if let ExprKind::Path(QPath::Resolved(_, path2)) = args[0].kind;
         if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
         then {
             return Some(rb)
@@ -1669,7 +1671,7 @@ where
 
     values.sort();
 
-    for (a, b) in iter::zip(&values, &values[1..]) {
+    for (a, b) in iter::zip(&values, values.iter().skip(1)) {
         match (a, b) {
             (&Kind::Start(_, ra), &Kind::End(_, rb)) => {
                 if ra.node != rb.node {
@@ -1679,7 +1681,7 @@ where
             (&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (),
             _ => {
                 // skip if the range `a` is completely included into the range `b`
-                if let Ordering::Equal | Ordering::Less = a.cmp(&b) {
+                if let Ordering::Equal | Ordering::Less = a.cmp(b) {
                     let kind_a = Kind::End(a.range().node.1, a.range());
                     let kind_b = Kind::End(b.range().node.1, b.range());
                     if let Ordering::Equal | Ordering::Greater = kind_a.cmp(&kind_b) {
@@ -1724,8 +1726,14 @@ mod redundant_pattern_match {
         arms: &[Arm<'_>],
         keyword: &'static str,
     ) {
-        let good_method = match arms[0].pat.kind {
-            PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => {
+        // also look inside refs
+        let mut kind = &arms[0].pat.kind;
+        // if we have &None for example, peel it so we can detect "if let None = x"
+        if let PatKind::Ref(inner, _mutability) = kind {
+            kind = &inner.kind;
+        }
+        let good_method = match kind {
+            PatKind::TupleStruct(ref path, patterns, _) if patterns.len() == 1 => {
                 if let PatKind::Wild = patterns[0].kind {
                     if match_qpath(path, &paths::RESULT_OK) {
                         "is_ok()"
@@ -1806,8 +1814,8 @@ mod redundant_pattern_match {
 
             let found_good_method = match node_pair {
                 (
-                    PatKind::TupleStruct(ref path_left, ref patterns_left, _),
-                    PatKind::TupleStruct(ref path_right, ref patterns_right, _),
+                    PatKind::TupleStruct(ref path_left, patterns_left, _),
+                    PatKind::TupleStruct(ref path_right, patterns_right, _),
                 ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
                     if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
                         find_good_method_for_match(
@@ -1834,8 +1842,8 @@ mod redundant_pattern_match {
                         None
                     }
                 },
-                (PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right))
-                | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, ref patterns, _))
+                (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
+                | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
                     if patterns.len() == 1 =>
                 {
                     if let PatKind::Wild = patterns[0].kind {
@@ -1957,10 +1965,10 @@ fn test_overlapping() {
 
 /// Implementation of `MATCH_SAME_ARMS`.
 fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) {
-    if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind {
+    if let ExprKind::Match(_, arms, MatchSource::Normal) = expr.kind {
         let hash = |&(_, arm): &(usize, &Arm<'_>)| -> u64 {
             let mut h = SpanlessHash::new(cx);
-            h.hash_expr(&arm.body);
+            h.hash_expr(arm.body);
             h.finish()
         };
 
@@ -1968,7 +1976,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) {
             let min_index = usize::min(lindex, rindex);
             let max_index = usize::max(lindex, rindex);
 
-            let mut local_map: FxHashMap<HirId, HirId> = FxHashMap::default();
+            let mut local_map: HirIdMap<HirId> = HirIdMap::default();
             let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
                 if_chain! {
                     if let Some(a_id) = path_to_local(a);
@@ -1996,7 +2004,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) {
             (min_index..=max_index).all(|index| arms[index].guard.is_none())
                 && SpanlessEq::new(cx)
                     .expr_fallback(eq_fallback)
-                    .eq_expr(&lhs.body, &rhs.body)
+                    .eq_expr(lhs.body, rhs.body)
                 // these checks could be removed to allow unused bindings
                 && bindings_eq(lhs.pat, local_map.keys().copied().collect())
                 && bindings_eq(rhs.pat, local_map.values().copied().collect())
@@ -2052,7 +2060,7 @@ fn pat_contains_local(pat: &Pat<'_>, id: HirId) -> bool {
 }
 
 /// Returns true if all the bindings in the `Pat` are in `ids` and vice versa
-fn bindings_eq(pat: &Pat<'_>, mut ids: FxHashSet<HirId>) -> bool {
+fn bindings_eq(pat: &Pat<'_>, mut ids: HirIdSet) -> bool {
     let mut result = true;
     pat.each_binding_or_first(&mut |_, id, _, _| result &= ids.remove(&id));
     result && ids.is_empty()
diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs
index 7895ba9f1e0..a735c616f6e 100644
--- a/clippy_lints/src/mem_discriminant.rs
+++ b/clippy_lints/src/mem_discriminant.rs
@@ -34,7 +34,7 @@ declare_lint_pass!(MemDiscriminant => [MEM_DISCRIMINANT_NON_ENUM]);
 impl<'tcx> LateLintPass<'tcx> for MemDiscriminant {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::Call(ref func, ref func_args) = expr.kind;
+            if let ExprKind::Call(func, func_args) = expr.kind;
             // is `mem::discriminant`
             if let ExprKind::Path(ref func_qpath) = func.kind;
             if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant {
                             let mut derefs_needed = ptr_depth;
                             let mut cur_expr = param;
                             while derefs_needed > 0  {
-                                if let ExprKind::AddrOf(BorrowKind::Ref, _, ref inner_expr) = cur_expr.kind {
+                                if let ExprKind::AddrOf(BorrowKind::Ref, _, inner_expr) = cur_expr.kind {
                                     derefs_needed -= 1;
                                     cur_expr = inner_expr;
                                 } else {
diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs
index c13802e3953..a28cb5f32fe 100644
--- a/clippy_lints/src/mem_forget.rs
+++ b/clippy_lints/src/mem_forget.rs
@@ -28,7 +28,7 @@ declare_lint_pass!(MemForget => [MEM_FORGET]);
 
 impl<'tcx> LateLintPass<'tcx> for MemForget {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Call(ref path_expr, ref args) = e.kind {
+        if let ExprKind::Call(path_expr, args) = e.kind {
             if let ExprKind::Path(ref qpath) = path_expr.kind {
                 if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
                     if match_def_path(cx, def_id, &paths::MEM_FORGET) {
diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index 426c108d89f..e1d351aee45 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/clippy_lints/src/mem_replace.rs
@@ -109,14 +109,14 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &E
             // argument's type. All that's left is to get
             // replacee's path.
             let replaced_path = match dest.kind {
-                ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, ref replaced) => {
-                    if let ExprKind::Path(QPath::Resolved(None, ref replaced_path)) = replaced.kind {
+                ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
+                    if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
                         replaced_path
                     } else {
                         return;
                     }
                 },
-                ExprKind::Path(QPath::Resolved(None, ref replaced_path)) => replaced_path,
+                ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
                 _ => return,
             };
 
@@ -161,7 +161,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
     }
 
     if_chain! {
-        if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind;
+        if let ExprKind::Call(repl_func, repl_args) = src.kind;
         if repl_args.is_empty();
         if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
         if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
@@ -214,7 +214,7 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
         .iter()
         .any(|symbol| is_diagnostic_assoc_item(cx, def_id, *symbol))
     {
-        if let QPath::TypeRelative(_, ref method) = path {
+        if let QPath::TypeRelative(_, method) = path {
             if method.ident.name == sym::new {
                 return true;
             }
@@ -225,34 +225,33 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
 }
 
 fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
-    if let ExprKind::Call(ref repl_func, _) = src.kind {
-        if_chain! {
-            if !in_external_macro(cx.tcx.sess, expr_span);
-            if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
-            if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
-            if is_diagnostic_assoc_item(cx, repl_def_id, sym::Default)
-                || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
+    if_chain! {
+        if let ExprKind::Call(repl_func, _) = src.kind;
+        if !in_external_macro(cx.tcx.sess, expr_span);
+        if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
+        if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
+        if is_diagnostic_assoc_item(cx, repl_def_id, sym::Default)
+            || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
 
-            then {
-                span_lint_and_then(
-                    cx,
-                    MEM_REPLACE_WITH_DEFAULT,
-                    expr_span,
-                    "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`",
-                    |diag| {
-                        if !in_macro(expr_span) {
-                            let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, ""));
+        then {
+            span_lint_and_then(
+                cx,
+                MEM_REPLACE_WITH_DEFAULT,
+                expr_span,
+                "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`",
+                |diag| {
+                    if !in_macro(expr_span) {
+                        let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, ""));
 
-                            diag.span_suggestion(
-                                expr_span,
-                                "consider using",
-                                suggestion,
-                                Applicability::MachineApplicable
-                            );
-                        }
+                        diag.span_suggestion(
+                            expr_span,
+                            "consider using",
+                            suggestion,
+                            Applicability::MachineApplicable
+                        );
                     }
-                );
-            }
+                }
+            );
         }
     }
 }
@@ -274,11 +273,11 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // Check that `expr` is a call to `mem::replace()`
-            if let ExprKind::Call(ref func, ref func_args) = expr.kind;
+            if let ExprKind::Call(func, func_args) = expr.kind;
             if let ExprKind::Path(ref func_qpath) = func.kind;
             if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
             if match_def_path(cx, def_id, &paths::MEM_REPLACE);
-            if let [dest, src] = &**func_args;
+            if let [dest, src] = func_args;
             then {
                 check_replace_option_with_none(cx, src, dest, expr.span);
                 check_replace_with_uninit(cx, src, dest, expr.span);
diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs
index 0ba8a98a018..287bff886bf 100644
--- a/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -1,101 +1,82 @@
 use super::{contains_return, BIND_INSTEAD_OF_MAP};
 use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_with_macro_callsite};
-use clippy_utils::ty::match_type;
-use clippy_utils::{in_macro, match_qpath, method_calls, paths, remove_blocks, visitors::find_all_ret_expressions};
+use clippy_utils::{in_macro, remove_blocks, visitors::find_all_ret_expressions};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::{LangItem, QPath};
 use rustc_lint::LateContext;
+use rustc_middle::ty::DefIdTree;
 use rustc_span::Span;
 
 pub(crate) struct OptionAndThenSome;
 
 impl BindInsteadOfMap for OptionAndThenSome {
-    const TYPE_NAME: &'static str = "Option";
-    const TYPE_QPATH: &'static [&'static str] = &paths::OPTION;
-
+    const VARIANT_LANG_ITEM: LangItem = LangItem::OptionSome;
     const BAD_METHOD_NAME: &'static str = "and_then";
-    const BAD_VARIANT_NAME: &'static str = "Some";
-    const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::OPTION_SOME;
-
     const GOOD_METHOD_NAME: &'static str = "map";
 }
 
 pub(crate) struct ResultAndThenOk;
 
 impl BindInsteadOfMap for ResultAndThenOk {
-    const TYPE_NAME: &'static str = "Result";
-    const TYPE_QPATH: &'static [&'static str] = &paths::RESULT;
-
+    const VARIANT_LANG_ITEM: LangItem = LangItem::ResultOk;
     const BAD_METHOD_NAME: &'static str = "and_then";
-    const BAD_VARIANT_NAME: &'static str = "Ok";
-    const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::RESULT_OK;
-
     const GOOD_METHOD_NAME: &'static str = "map";
 }
 
 pub(crate) struct ResultOrElseErrInfo;
 
 impl BindInsteadOfMap for ResultOrElseErrInfo {
-    const TYPE_NAME: &'static str = "Result";
-    const TYPE_QPATH: &'static [&'static str] = &paths::RESULT;
-
+    const VARIANT_LANG_ITEM: LangItem = LangItem::ResultErr;
     const BAD_METHOD_NAME: &'static str = "or_else";
-    const BAD_VARIANT_NAME: &'static str = "Err";
-    const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::RESULT_ERR;
-
     const GOOD_METHOD_NAME: &'static str = "map_err";
 }
 
 pub(crate) trait BindInsteadOfMap {
-    const TYPE_NAME: &'static str;
-    const TYPE_QPATH: &'static [&'static str];
-
+    const VARIANT_LANG_ITEM: LangItem;
     const BAD_METHOD_NAME: &'static str;
-    const BAD_VARIANT_NAME: &'static str;
-    const BAD_VARIANT_QPATH: &'static [&'static str];
-
     const GOOD_METHOD_NAME: &'static str;
 
-    fn no_op_msg() -> String {
-        format!(
+    fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
+        let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
+        let item_id = cx.tcx.parent(variant_id)?;
+        Some(format!(
             "using `{}.{}({})`, which is a no-op",
-            Self::TYPE_NAME,
+            cx.tcx.item_name(item_id),
             Self::BAD_METHOD_NAME,
-            Self::BAD_VARIANT_NAME
-        )
+            cx.tcx.item_name(variant_id),
+        ))
     }
 
-    fn lint_msg() -> String {
-        format!(
+    fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
+        let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
+        let item_id = cx.tcx.parent(variant_id)?;
+        Some(format!(
             "using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
-            Self::TYPE_NAME,
+            cx.tcx.item_name(item_id),
             Self::BAD_METHOD_NAME,
-            Self::BAD_VARIANT_NAME,
+            cx.tcx.item_name(variant_id),
             Self::GOOD_METHOD_NAME
-        )
+        ))
     }
 
     fn lint_closure_autofixable(
         cx: &LateContext<'_>,
         expr: &hir::Expr<'_>,
-        args: &[hir::Expr<'_>],
+        recv: &hir::Expr<'_>,
         closure_expr: &hir::Expr<'_>,
         closure_args_span: Span,
     ) -> bool {
         if_chain! {
-            if let hir::ExprKind::Call(ref some_expr, ref some_args) = closure_expr.kind;
-            if let hir::ExprKind::Path(ref qpath) = some_expr.kind;
-            if match_qpath(qpath, Self::BAD_VARIANT_QPATH);
-            if some_args.len() == 1;
+            if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind;
+            if let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind;
+            if Self::is_variant(cx, path.res);
+            if !contains_return(inner_expr);
+            if let Some(msg) = Self::lint_msg(cx);
             then {
-                let inner_expr = &some_args[0];
-
-                if contains_return(inner_expr) {
-                    return false;
-                }
-
                 let some_inner_snip = if inner_expr.span.from_expansion() {
                     snippet_with_macro_callsite(cx, inner_expr.span, "_")
                 } else {
@@ -103,13 +84,13 @@ pub(crate) trait BindInsteadOfMap {
                 };
 
                 let closure_args_snip = snippet(cx, closure_args_span, "..");
-                let option_snip = snippet(cx, args[0].span, "..");
+                let option_snip = snippet(cx, recv.span, "..");
                 let note = format!("{}.{}({} {})", option_snip, Self::GOOD_METHOD_NAME, closure_args_snip, some_inner_snip);
                 span_lint_and_sugg(
                     cx,
                     BIND_INSTEAD_OF_MAP,
                     expr.span,
-                    Self::lint_msg().as_ref(),
+                    &msg,
                     "try this",
                     note,
                     Applicability::MachineApplicable,
@@ -126,68 +107,84 @@ pub(crate) trait BindInsteadOfMap {
         let can_sugg: bool = find_all_ret_expressions(cx, closure_expr, |ret_expr| {
             if_chain! {
                 if !in_macro(ret_expr.span);
-                if let hir::ExprKind::Call(ref func_path, ref args) = ret_expr.kind;
-                if let hir::ExprKind::Path(ref qpath) = func_path.kind;
-                if match_qpath(qpath, Self::BAD_VARIANT_QPATH);
-                if args.len() == 1;
-                if !contains_return(&args[0]);
+                if let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind;
+                if let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind;
+                if Self::is_variant(cx, path.res);
+                if !contains_return(arg);
                 then {
-                    suggs.push((ret_expr.span, args[0].span.source_callsite()));
+                    suggs.push((ret_expr.span, arg.span.source_callsite()));
                     true
                 } else {
                     false
                 }
             }
         });
-
-        if can_sugg {
-            span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, Self::lint_msg().as_ref(), |diag| {
-                multispan_sugg_with_applicability(
-                    diag,
-                    "try this",
-                    Applicability::MachineApplicable,
-                    std::iter::once((*method_calls(expr, 1).2.get(0).unwrap(), Self::GOOD_METHOD_NAME.into())).chain(
-                        suggs
-                            .into_iter()
-                            .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
-                    ),
-                )
-            });
-        }
-        can_sugg
+        let (span, msg) = if_chain! {
+            if can_sugg;
+            if let hir::ExprKind::MethodCall(_, span, ..) = expr.kind;
+            if let Some(msg) = Self::lint_msg(cx);
+            then { (span, msg) } else { return false; }
+        };
+        span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| {
+            multispan_sugg_with_applicability(
+                diag,
+                "try this",
+                Applicability::MachineApplicable,
+                std::iter::once((span, Self::GOOD_METHOD_NAME.into())).chain(
+                    suggs
+                        .into_iter()
+                        .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
+                ),
+            )
+        });
+        true
     }
 
     /// Lint use of `_.and_then(|x| Some(y))` for `Option`s
-    fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) -> bool {
-        if !match_type(cx, cx.typeck_results().expr_ty(&args[0]), Self::TYPE_QPATH) {
-            return false;
+    fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
+        if_chain! {
+            if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
+            if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM);
+            if Some(adt.did) == cx.tcx.parent(vid);
+            then {} else { return false; }
         }
 
-        match args[1].kind {
+        match arg.kind {
             hir::ExprKind::Closure(_, _, body_id, closure_args_span, _) => {
                 let closure_body = cx.tcx.hir().body(body_id);
                 let closure_expr = remove_blocks(&closure_body.value);
 
-                if Self::lint_closure_autofixable(cx, expr, args, closure_expr, closure_args_span) {
+                if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, closure_args_span) {
                     true
                 } else {
                     Self::lint_closure(cx, expr, closure_expr)
                 }
             },
             // `_.and_then(Some)` case, which is no-op.
-            hir::ExprKind::Path(ref qpath) if match_qpath(qpath, Self::BAD_VARIANT_QPATH) => {
-                span_lint_and_sugg(
-                    cx,
-                    BIND_INSTEAD_OF_MAP,
-                    expr.span,
-                    Self::no_op_msg().as_ref(),
-                    "use the expression directly",
-                    snippet(cx, args[0].span, "..").into(),
-                    Applicability::MachineApplicable,
-                );
+            hir::ExprKind::Path(QPath::Resolved(_, path)) if Self::is_variant(cx, path.res) => {
+                if let Some(msg) = Self::no_op_msg(cx) {
+                    span_lint_and_sugg(
+                        cx,
+                        BIND_INSTEAD_OF_MAP,
+                        expr.span,
+                        &msg,
+                        "use the expression directly",
+                        snippet(cx, recv.span, "..").into(),
+                        Applicability::MachineApplicable,
+                    );
+                }
                 true
             },
             _ => false,
         }
     }
+
+    fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
+        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
+            if let Ok(variant_id) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM) {
+                return cx.tcx.parent(id) == Some(variant_id);
+            }
+        }
+        false
+    }
 }
diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs
index 4f88f80a304..2ad3e673c57 100644
--- a/clippy_lints/src/methods/bytes_nth.rs
+++ b/clippy_lints/src/methods/bytes_nth.rs
@@ -1,41 +1,34 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
 use super::BYTES_NTH;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'tcx [Expr<'tcx>]) {
-    if_chain! {
-        if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind;
-        let ty = cx.typeck_results().expr_ty(&iter_args[0]).peel_refs();
-        let caller_type = if is_type_diagnostic_item(cx, ty, sym::string_type) {
-            Some("String")
-        } else if ty.is_str() {
-            Some("str")
-        } else {
-            None
-        };
-        if let Some(caller_type) = caller_type;
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                BYTES_NTH,
-                expr.span,
-                &format!("called `.byte().nth()` on a `{}`", caller_type),
-                "try",
-                format!(
-                    "{}.as_bytes().get({})",
-                    snippet_with_applicability(cx, iter_args[0].span, "..", &mut applicability),
-                    snippet_with_applicability(cx, args[1].span, "..", &mut applicability)
-                ),
-                applicability,
-            );
-        }
-    }
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, n_arg: &'tcx Expr<'tcx>) {
+    let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+    let caller_type = if ty.is_str() {
+        "str"
+    } else if is_type_diagnostic_item(cx, ty, sym::string_type) {
+        "String"
+    } else {
+        return;
+    };
+    let mut applicability = Applicability::MachineApplicable;
+    span_lint_and_sugg(
+        cx,
+        BYTES_NTH,
+        expr.span,
+        &format!("called `.byte().nth()` on a `{}`", caller_type),
+        "try",
+        format!(
+            "{}.as_bytes().get({})",
+            snippet_with_applicability(cx, recv.span, "..", &mut applicability),
+            snippet_with_applicability(cx, n_arg.span, "..", &mut applicability)
+        ),
+        applicability,
+    );
 }
diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs
index c668fe52781..514c4118765 100644
--- a/clippy_lints/src/methods/chars_cmp.rs
+++ b/clippy_lints/src/methods/chars_cmp.rs
@@ -19,7 +19,7 @@ pub(super) fn check(
 ) -> bool {
     if_chain! {
         if let Some(args) = method_chain_args(info.chain, chain_methods);
-        if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.kind;
+        if let hir::ExprKind::Call(fun, arg_char) = info.other.kind;
         if arg_char.len() == 1;
         if let hir::ExprKind::Path(ref qpath) = fun.kind;
         if let Some(segment) = single_segment_path(qpath);
diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs
index edb6649b87b..ce2e8fa8b10 100644
--- a/clippy_lints/src/methods/clone_on_copy.rs
+++ b/clippy_lints/src/methods/clone_on_copy.rs
@@ -1,10 +1,12 @@
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::get_parent_node;
+use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg;
 use clippy_utils::ty::is_copy;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, adjustment::Adjust};
 use rustc_span::symbol::{sym, Symbol};
 use std::iter;
 
@@ -12,12 +14,26 @@ use super::CLONE_DOUBLE_REF;
 use super::CLONE_ON_COPY;
 
 /// Checks for the `CLONE_ON_COPY` lint.
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
-    if !(args.len() == 1 && method_name == sym::clone) {
+#[allow(clippy::too_many_lines)]
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, args: &[Expr<'_>]) {
+    let arg = match args {
+        [arg] if method_name == sym::clone => arg,
+        _ => return,
+    };
+    if cx
+        .typeck_results()
+        .type_dependent_def_id(expr.hir_id)
+        .and_then(|id| cx.tcx.trait_of_item(id))
+        .zip(cx.tcx.lang_items().clone_trait())
+        .map_or(true, |(x, y)| x != y)
+    {
         return;
     }
-    let arg = &args[0];
-    let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
+    let arg_adjustments = cx.typeck_results().expr_adjustments(arg);
+    let arg_ty = arg_adjustments
+        .last()
+        .map_or_else(|| cx.typeck_results().expr_ty(arg), |a| a.target);
+
     let ty = cx.typeck_results().expr_ty(expr);
     if let ty::Ref(_, inner, _) = arg_ty.kind() {
         if let ty::Ref(_, innermost, _) = inner.kind() {
@@ -61,57 +77,57 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Sym
     }
 
     if is_copy(cx, ty) {
-        let snip;
-        if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) {
-            let parent = cx.tcx.hir().get_parent_node(expr.hir_id);
-            match &cx.tcx.hir().get(parent) {
-                hir::Node::Expr(parent) => match parent.kind {
-                    // &*x is a nop, &x.clone() is not
-                    hir::ExprKind::AddrOf(..) => return,
-                    // (*x).func() is useless, x.clone().func() can work in case func borrows mutably
-                    hir::ExprKind::MethodCall(_, _, parent_args, _) if expr.hir_id == parent_args[0].hir_id => {
-                        return;
-                    },
-
-                    _ => {},
-                },
-                hir::Node::Stmt(stmt) => {
-                    if let hir::StmtKind::Local(ref loc) = stmt.kind {
-                        if let hir::PatKind::Ref(..) = loc.pat.kind {
-                            // let ref y = *x borrows x, let ref y = x.clone() does not
-                            return;
-                        }
-                    }
-                },
-                _ => {},
+        let parent_is_suffix_expr = match get_parent_node(cx.tcx, expr.hir_id) {
+            Some(Node::Expr(parent)) => match parent.kind {
+                // &*x is a nop, &x.clone() is not
+                ExprKind::AddrOf(..) => return,
+                // (*x).func() is useless, x.clone().func() can work in case func borrows self
+                ExprKind::MethodCall(_, _, [self_arg, ..], _)
+                    if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
+                {
+                    return;
+                }
+                ExprKind::MethodCall(_, _, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
+                ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
+                | ExprKind::Field(..)
+                | ExprKind::Index(..) => true,
+                _ => false,
+            },
+            // local binding capturing a reference
+            Some(Node::Local(l))
+                if matches!(
+                    l.pat.kind,
+                    PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..)
+                ) =>
+            {
+                return;
             }
+            _ => false,
+        };
 
-            // x.clone() might have dereferenced x, possibly through Deref impls
-            if cx.typeck_results().expr_ty(arg) == ty {
-                snip = Some(("try removing the `clone` call", format!("{}", snippet)));
-            } else {
-                let deref_count = cx
-                    .typeck_results()
-                    .expr_adjustments(arg)
-                    .iter()
-                    .filter(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_)))
-                    .count();
-                let derefs: String = iter::repeat('*').take(deref_count).collect();
-                snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet)));
-            }
+        let mut app = Applicability::MachineApplicable;
+        let snip = snippet_with_context(cx, arg.span, expr.span.ctxt(), "_", &mut app).0;
+
+        let deref_count = arg_adjustments
+            .iter()
+            .take_while(|adj| matches!(adj.kind, Adjust::Deref(_)))
+            .count();
+        let (help, sugg) = if deref_count == 0 {
+            ("try removing the `clone` call", snip.into())
+        } else if parent_is_suffix_expr {
+            ("try dereferencing it", format!("({}{})", "*".repeat(deref_count), snip))
         } else {
-            snip = None;
-        }
-        span_lint_and_then(
+            ("try dereferencing it", format!("{}{}", "*".repeat(deref_count), snip))
+        };
+
+        span_lint_and_sugg(
             cx,
             CLONE_ON_COPY,
             expr.span,
             &format!("using `clone` on type `{}` which implements the `Copy` trait", ty),
-            |diag| {
-                if let Some((text, snip)) = snip {
-                    diag.span_suggestion(expr.span, text, snip, Applicability::MachineApplicable);
-                }
-            },
+            help,
+            sugg,
+            app,
         );
     }
 }
diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs
index e7bffa66b3f..03cb41697d5 100644
--- a/clippy_lints/src/methods/expect_fun_call.rs
+++ b/clippy_lints/src/methods/expect_fun_call.rs
@@ -100,9 +100,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa
         applicability: &mut Applicability,
     ) -> Vec<String> {
         if_chain! {
-            if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref format_arg) = a.kind;
-            if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.kind;
-            if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.kind;
+            if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, format_arg) = a.kind;
+            if let hir::ExprKind::Match(format_arg_expr, _, _) = format_arg.kind;
+            if let hir::ExprKind::Tup(format_arg_expr_tup) = format_arg_expr.kind;
 
             then {
                 format_arg_expr_tup
@@ -155,7 +155,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa
         if block.stmts.len() == 1;
         if let hir::StmtKind::Local(local) = &block.stmts[0].kind;
         if let Some(arg_root) = &local.init;
-        if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg_root.kind;
+        if let hir::ExprKind::Call(inner_fun, inner_args) = arg_root.kind;
         if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1;
         if let hir::ExprKind::Call(_, format_args) = &inner_args[0].kind;
         then {
diff --git a/clippy_lints/src/methods/expect_used.rs b/clippy_lints/src/methods/expect_used.rs
index 64531b29ade..63a834fdce0 100644
--- a/clippy_lints/src/methods/expect_used.rs
+++ b/clippy_lints/src/methods/expect_used.rs
@@ -7,8 +7,8 @@ use rustc_span::sym;
 use super::EXPECT_USED;
 
 /// lint use of `expect()` for `Option`s and `Result`s
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) {
-    let obj_ty = cx.typeck_results().expr_ty(&expect_args[0]).peel_refs();
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
+    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
 
     let mess = if is_type_diagnostic_item(cx, obj_ty, sym::option_type) {
         Some((EXPECT_USED, "an Option", "None"))
diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs
index 39d2f15dbc8..7b2967feb0f 100644
--- a/clippy_lints/src/methods/filetype_is_file.rs
+++ b/clippy_lints/src/methods/filetype_is_file.rs
@@ -8,8 +8,8 @@ use rustc_span::source_map::Span;
 
 use super::FILETYPE_IS_FILE;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
-    let ty = cx.typeck_results().expr_ty(&args[0]);
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
+    let ty = cx.typeck_results().expr_ty(recv);
 
     if !match_type(cx, ty, &paths::FILE_TYPE) {
         return;
diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs
index 2cb476acb2b..35fae450eeb 100644
--- a/clippy_lints/src/methods/filter_map.rs
+++ b/clippy_lints/src/methods/filter_map.rs
@@ -1,87 +1,174 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
-use clippy_utils::{is_trait_method, path_to_local_id, SpanlessEq};
+use clippy_utils::source::{indent_of, reindent_multiline, snippet};
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_trait_method, path_to_local_id, remove_blocks, SpanlessEq};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::{Expr, ExprKind, PatKind, UnOp};
+use rustc_hir::def::Res;
+use rustc_hir::{Expr, ExprKind, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::TyS;
-use rustc_span::symbol::sym;
+use rustc_span::source_map::Span;
+use rustc_span::symbol::{sym, Symbol};
+use std::borrow::Cow;
 
 use super::MANUAL_FILTER_MAP;
 use super::MANUAL_FIND_MAP;
+use super::OPTION_FILTER_MAP;
+
+fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
+    match &expr.kind {
+        hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name,
+        hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
+            segments.segments.last().unwrap().ident.name == method_name
+        },
+        hir::ExprKind::Closure(_, _, c, _, _) => {
+            let body = cx.tcx.hir().body(*c);
+            let closure_expr = remove_blocks(&body.value);
+            let arg_id = body.params[0].pat.hir_id;
+            match closure_expr.kind {
+                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, _, args, _) => {
+                    if_chain! {
+                    if ident.name == method_name;
+                    if let hir::ExprKind::Path(path) = &args[0].kind;
+                    if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id);
+                    then {
+                        return arg_id == *local
+                    }
+                    }
+                    false
+                },
+                _ => false,
+            }
+        },
+        _ => false,
+    }
+}
+
+fn is_option_filter_map<'tcx>(cx: &LateContext<'tcx>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool {
+    is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some))
+}
+
+/// lint use of `filter().map()` for `Iterators`
+fn lint_filter_some_map_unwrap(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    filter_recv: &hir::Expr<'_>,
+    filter_arg: &hir::Expr<'_>,
+    map_arg: &hir::Expr<'_>,
+    target_span: Span,
+    methods_span: Span,
+) {
+    let iterator = is_trait_method(cx, expr, sym::Iterator);
+    let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::option_type);
+    if (iterator || option) && is_option_filter_map(cx, filter_arg, map_arg) {
+        let msg = "`filter` for `Some` followed by `unwrap`";
+        let help = "consider using `flatten` instead";
+        let sugg = format!(
+            "{}",
+            reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, target_span),)
+        );
+        span_lint_and_sugg(
+            cx,
+            OPTION_FILTER_MAP,
+            methods_span,
+            msg,
+            help,
+            sugg,
+            Applicability::MachineApplicable,
+        );
+    }
+}
 
 /// lint use of `filter().map()` or `find().map()` for `Iterators`
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, is_find: bool) {
+#[allow(clippy::too_many_arguments)]
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &hir::Expr<'_>,
+    filter_recv: &hir::Expr<'_>,
+    filter_arg: &hir::Expr<'_>,
+    filter_span: Span,
+    map_recv: &hir::Expr<'_>,
+    map_arg: &hir::Expr<'_>,
+    map_span: Span,
+    is_find: bool,
+) {
+    lint_filter_some_map_unwrap(
+        cx,
+        expr,
+        filter_recv,
+        filter_arg,
+        map_arg,
+        map_span,
+        filter_span.with_hi(expr.span.hi()),
+    );
     if_chain! {
-        if let ExprKind::MethodCall(_, _, [map_recv, map_arg], map_span) = expr.kind;
-        if let ExprKind::MethodCall(_, _, [_, filter_arg], filter_span) = map_recv.kind;
-        if is_trait_method(cx, map_recv, sym::Iterator);
+            if is_trait_method(cx, map_recv, sym::Iterator);
 
-        // filter(|x| ...is_some())...
-        if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind;
-        let filter_body = cx.tcx.hir().body(filter_body_id);
-        if let [filter_param] = filter_body.params;
-        // optional ref pattern: `filter(|&x| ..)`
-        let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
-            (ref_pat, true)
-        } else {
-            (filter_param.pat, false)
-        };
-        // closure ends with is_some() or is_ok()
-        if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
-        if let ExprKind::MethodCall(path, _, [filter_arg], _) = filter_body.value.kind;
-        if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).ty_adt_def();
-        if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::option_type, opt_ty.did) {
-            Some(false)
-        } else if cx.tcx.is_diagnostic_item(sym::result_type, opt_ty.did) {
-            Some(true)
-        } else {
-            None
-        };
-        if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
+            // filter(|x| ...is_some())...
+            if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind;
+            let filter_body = cx.tcx.hir().body(filter_body_id);
+            if let [filter_param] = filter_body.params;
+            // optional ref pattern: `filter(|&x| ..)`
+            let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
+                (ref_pat, true)
+            } else {
+                (filter_param.pat, false)
+            };
+            // closure ends with is_some() or is_ok()
+            if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
+            if let ExprKind::MethodCall(path, _, [filter_arg], _) = filter_body.value.kind;
+            if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).ty_adt_def();
+            if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::option_type, opt_ty.did) {
+                Some(false)
+            } else if cx.tcx.is_diagnostic_item(sym::result_type, opt_ty.did) {
+                Some(true)
+            } else {
+                None
+            };
+            if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
 
-        // ...map(|x| ...unwrap())
-        if let ExprKind::Closure(_, _, map_body_id, ..) = map_arg.kind;
-        let map_body = cx.tcx.hir().body(map_body_id);
-        if let [map_param] = map_body.params;
-        if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
-        // closure ends with expect() or unwrap()
-        if let ExprKind::MethodCall(seg, _, [map_arg, ..], _) = map_body.value.kind;
-        if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
+            // ...map(|x| ...unwrap())
+            if let ExprKind::Closure(_, _, map_body_id, ..) = map_arg.kind;
+            let map_body = cx.tcx.hir().body(map_body_id);
+            if let [map_param] = map_body.params;
+            if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
+            // closure ends with expect() or unwrap()
+            if let ExprKind::MethodCall(seg, _, [map_arg, ..], _) = map_body.value.kind;
+            if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
 
-        let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
-            // in `filter(|x| ..)`, replace `*x` with `x`
-            let a_path = if_chain! {
-                if !is_filter_param_ref;
-                if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
-                then { expr_path } else { a }
-            };
-            // let the filter closure arg and the map closure arg be equal
-            if_chain! {
-                if path_to_local_id(a_path, filter_param_id);
-                if path_to_local_id(b, map_param_id);
-                if TyS::same_type(cx.typeck_results().expr_ty_adjusted(a), cx.typeck_results().expr_ty_adjusted(b));
-                then {
-                    return true;
+            let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
+                // in `filter(|x| ..)`, replace `*x` with `x`
+                let a_path = if_chain! {
+                    if !is_filter_param_ref;
+                    if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
+                    then { expr_path } else { a }
+                };
+                // let the filter closure arg and the map closure arg be equal
+                if_chain! {
+                    if path_to_local_id(a_path, filter_param_id);
+                    if path_to_local_id(b, map_param_id);
+                    if TyS::same_type(cx.typeck_results().expr_ty_adjusted(a), cx.typeck_results().expr_ty_adjusted(b));
+                    then {
+                        return true;
+                    }
                 }
-            }
-            false
-        };
-        if SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg);
-        then {
-            let span = filter_span.to(map_span);
-            let (filter_name, lint) = if is_find {
-                ("find", MANUAL_FIND_MAP)
-            } else {
-                ("filter", MANUAL_FILTER_MAP)
+                false
             };
-            let msg = format!("`{}(..).map(..)` can be simplified as `{0}_map(..)`", filter_name);
-            let to_opt = if is_result { ".ok()" } else { "" };
-            let sugg = format!("{}_map(|{}| {}{})", filter_name, map_param_ident,
-                snippet(cx, map_arg.span, ".."), to_opt);
-            span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
-        }
+            if SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg);
+            then {
+                let span = filter_span.with_hi(expr.span.hi());
+                let (filter_name, lint) = if is_find {
+                    ("find", MANUAL_FIND_MAP)
+                } else {
+                    ("filter", MANUAL_FILTER_MAP)
+                };
+                let msg = format!("`{}(..).map(..)` can be simplified as `{0}_map(..)`", filter_name);
+                let to_opt = if is_result { ".ok()" } else { "" };
+                let sugg = format!("{}_map(|{}| {}{})", filter_name, map_param_ident,
+                    snippet(cx, map_arg.span, ".."), to_opt);
+                span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
+            }
     }
 }
diff --git a/clippy_lints/src/methods/filter_map_identity.rs b/clippy_lints/src/methods/filter_map_identity.rs
index 80598d88508..3a61f4ccad7 100644
--- a/clippy_lints/src/methods/filter_map_identity.rs
+++ b/clippy_lints/src/methods/filter_map_identity.rs
@@ -8,15 +8,8 @@ use rustc_span::{source_map::Span, sym};
 
 use super::FILTER_MAP_IDENTITY;
 
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    filter_map_args: &[hir::Expr<'_>],
-    filter_map_span: Span,
-) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: &hir::Expr<'_>, filter_map_span: Span) {
     if is_trait_method(cx, expr, sym::Iterator) {
-        let arg_node = &filter_map_args[1].kind;
-
         let apply_lint = |message: &str| {
             span_lint_and_sugg(
                 cx,
@@ -30,8 +23,8 @@ pub(super) fn check(
         };
 
         if_chain! {
-            if let hir::ExprKind::Closure(_, _, body_id, _, _) = arg_node;
-            let body = cx.tcx.hir().body(*body_id);
+            if let hir::ExprKind::Closure(_, _, body_id, _, _) = filter_map_arg.kind;
+            let body = cx.tcx.hir().body(body_id);
 
             if let hir::PatKind::Binding(_, binding_id, ..) = body.params[0].pat.kind;
             if path_to_local_id(&body.value, binding_id);
@@ -41,7 +34,7 @@ pub(super) fn check(
         }
 
         if_chain! {
-            if let hir::ExprKind::Path(ref qpath) = arg_node;
+            if let hir::ExprKind::Path(ref qpath) = filter_map_arg.kind;
 
             if match_qpath(qpath, &paths::STD_CONVERT_IDENTITY);
 
diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs
index ba57abd16c9..2b19e4ee8c0 100644
--- a/clippy_lints/src/methods/filter_map_next.rs
+++ b/clippy_lints/src/methods/filter_map_next.rs
@@ -14,7 +14,8 @@ const FILTER_MAP_NEXT_MSRV: RustcVersion = RustcVersion::new(1, 30, 0);
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx hir::Expr<'_>,
-    filter_args: &'tcx [hir::Expr<'_>],
+    recv: &'tcx hir::Expr<'_>,
+    arg: &'tcx hir::Expr<'_>,
     msrv: Option<&RustcVersion>,
 ) {
     if is_trait_method(cx, expr, sym::Iterator) {
@@ -24,9 +25,9 @@ pub(super) fn check<'tcx>(
 
         let msg = "called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
                    `.find_map(..)` instead";
-        let filter_snippet = snippet(cx, filter_args[1].span, "..");
+        let filter_snippet = snippet(cx, arg.span, "..");
         if filter_snippet.lines().count() <= 1 {
-            let iter_snippet = snippet(cx, filter_args[0].span, "..");
+            let iter_snippet = snippet(cx, recv.span, "..");
             span_lint_and_sugg(
                 cx,
                 FILTER_MAP_NEXT,
diff --git a/clippy_lints/src/methods/filter_next.rs b/clippy_lints/src/methods/filter_next.rs
index 6cd24334414..172714f6b01 100644
--- a/clippy_lints/src/methods/filter_next.rs
+++ b/clippy_lints/src/methods/filter_next.rs
@@ -9,14 +9,19 @@ use rustc_span::sym;
 use super::FILTER_NEXT;
 
 /// lint use of `filter().next()` for `Iterators`
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) {
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'_>,
+    filter_arg: &'tcx hir::Expr<'_>,
+) {
     // lint if caller of `.filter().next()` is an Iterator
     if is_trait_method(cx, expr, sym::Iterator) {
         let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
                    `.find(..)` instead";
-        let filter_snippet = snippet(cx, filter_args[1].span, "..");
+        let filter_snippet = snippet(cx, filter_arg.span, "..");
         if filter_snippet.lines().count() <= 1 {
-            let iter_snippet = snippet(cx, filter_args[0].span, "..");
+            let iter_snippet = snippet(cx, recv.span, "..");
             // add note if not multi-line
             span_lint_and_sugg(
                 cx,
diff --git a/clippy_lints/src/methods/flat_map_identity.rs b/clippy_lints/src/methods/flat_map_identity.rs
index 034ea6c6562..dd613d0cd63 100644
--- a/clippy_lints/src/methods/flat_map_identity.rs
+++ b/clippy_lints/src/methods/flat_map_identity.rs
@@ -12,11 +12,11 @@ use super::FLAT_MAP_IDENTITY;
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx hir::Expr<'_>,
-    flat_map_args: &'tcx [hir::Expr<'_>],
+    flat_map_arg: &'tcx hir::Expr<'_>,
     flat_map_span: Span,
 ) {
     if is_trait_method(cx, expr, sym::Iterator) {
-        let arg_node = &flat_map_args[1].kind;
+        let arg_node = &flat_map_arg.kind;
 
         let apply_lint = |message: &str| {
             span_lint_and_sugg(
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
             let body = cx.tcx.hir().body(*body_id);
 
             if let hir::PatKind::Binding(_, _, binding_ident, _) = body.params[0].pat.kind;
-            if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = body.value.kind;
+            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = body.value.kind;
 
             if path.segments.len() == 1;
             if path.segments[0].ident.name == binding_ident.name;
diff --git a/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index 15cf5674313..707c54f7a3c 100644
--- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -40,8 +40,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
 }
 
 fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String {
+    let call_site = expr.span.source_callsite();
     if_chain! {
-        let call_site = expr.span.source_callsite();
         if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
         let snippet_split = snippet.split("::").collect::<Vec<_>>();
         if let Some((_, elements)) = snippet_split.split_last();
diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs
index b3a9743c614..54f28064384 100644
--- a/clippy_lints/src/methods/get_unwrap.rs
+++ b/clippy_lints/src/methods/get_unwrap.rs
@@ -11,18 +11,20 @@ use rustc_span::sym;
 
 use super::GET_UNWRAP;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args: &'tcx [hir::Expr<'_>], is_mut: bool) {
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'tcx>,
+    get_arg: &'tcx hir::Expr<'_>,
+    is_mut: bool,
+) {
     // Note: we don't want to lint `get_mut().unwrap` for `HashMap` or `BTreeMap`,
     // because they do not implement `IndexMut`
     let mut applicability = Applicability::MachineApplicable;
-    let expr_ty = cx.typeck_results().expr_ty(&get_args[0]);
-    let get_args_str = if get_args.len() > 1 {
-        snippet_with_applicability(cx, get_args[1].span, "..", &mut applicability)
-    } else {
-        return; // not linting on a .get().unwrap() chain or variant
-    };
+    let expr_ty = cx.typeck_results().expr_ty(recv);
+    let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability);
     let mut needs_ref;
-    let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() {
+    let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() {
         needs_ref = get_args_str.parse::<usize>().is_ok();
         "slice"
     } else if is_type_diagnostic_item(cx, expr_ty, sym::vec_type) {
@@ -77,7 +79,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args
         format!(
             "{}{}[{}]",
             borrow_str,
-            snippet_with_applicability(cx, get_args[0].span, "..", &mut applicability),
+            snippet_with_applicability(cx, recv.span, "..", &mut applicability),
             get_args_str
         ),
         applicability,
diff --git a/clippy_lints/src/methods/implicit_clone.rs b/clippy_lints/src/methods/implicit_clone.rs
index 04461ad5c3a..1211e2f2bf7 100644
--- a/clippy_lints/src/methods/implicit_clone.rs
+++ b/clippy_lints/src/methods/implicit_clone.rs
@@ -13,7 +13,7 @@ use clippy_utils::is_diagnostic_assoc_item;
 pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, trait_diagnostic: Symbol) {
     if_chain! {
         if let ExprKind::MethodCall(method_path, _, [arg], _) = &expr.kind;
-        let return_type = cx.typeck_results().expr_ty(&expr);
+        let return_type = cx.typeck_results().expr_ty(expr);
         let input_type = cx.typeck_results().expr_ty(arg).peel_refs();
         if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did));
diff --git a/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs
index 848f47e39f6..739f313716e 100644
--- a/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -9,10 +9,10 @@ use rustc_span::sym;
 
 use super::ITER_CLONED_COLLECT;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) {
     if_chain! {
         if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type);
-        if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.typeck_results().expr_ty(&iter_args[0]));
+        if let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv));
         if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite());
 
         then {
diff --git a/clippy_lints/src/methods/iter_count.rs b/clippy_lints/src/methods/iter_count.rs
index e394a8fe819..c6b7c7cd179 100644
--- a/clippy_lints/src/methods/iter_count.rs
+++ b/clippy_lints/src/methods/iter_count.rs
@@ -10,9 +10,9 @@ use rustc_span::sym;
 
 use super::ITER_COUNT;
 
-pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'tcx [Expr<'tcx>], iter_method: &str) {
-    let ty = cx.typeck_results().expr_ty(&iter_args[0]);
-    let caller_type = if derefs_to_slice(cx, &iter_args[0], ty).is_some() {
+pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, iter_method: &str) {
+    let ty = cx.typeck_results().expr_ty(recv);
+    let caller_type = if derefs_to_slice(cx, recv, ty).is_some() {
         "slice"
     } else if is_type_diagnostic_item(cx, ty, sym::vec_type) {
         "Vec"
@@ -42,7 +42,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'
         "try",
         format!(
             "{}.len()",
-            snippet_with_applicability(cx, iter_args[0].span, "..", &mut applicability),
+            snippet_with_applicability(cx, recv.span, "..", &mut applicability),
         ),
         applicability,
     );
diff --git a/clippy_lints/src/methods/iter_next_slice.rs b/clippy_lints/src/methods/iter_next_slice.rs
index e9b37b6f2bd..a49851de38e 100644
--- a/clippy_lints/src/methods/iter_next_slice.rs
+++ b/clippy_lints/src/methods/iter_next_slice.rs
@@ -13,9 +13,7 @@ use rustc_span::symbol::sym;
 
 use super::ITER_NEXT_SLICE;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) {
-    let caller_expr = &iter_args[0];
-
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, caller_expr: &'tcx hir::Expr<'_>) {
     // Skip lint if the `iter().next()` expression is a for loop argument,
     // since it is already covered by `&loops::ITER_NEXT_LOOP`
     let mut parent_expr_opt = get_parent_expr(cx, expr);
@@ -29,7 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite
     if derefs_to_slice(cx, caller_expr, cx.typeck_results().expr_ty(caller_expr)).is_some() {
         // caller is a Slice
         if_chain! {
-            if let hir::ExprKind::Index(ref caller_var, ref index_expr) = &caller_expr.kind;
+            if let hir::ExprKind::Index(caller_var, index_expr) = &caller_expr.kind;
             if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen })
                 = higher::range(index_expr);
             if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind;
diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs
index c46af427b3c..c2232239fe4 100644
--- a/clippy_lints/src/methods/iter_nth.rs
+++ b/clippy_lints/src/methods/iter_nth.rs
@@ -11,20 +11,20 @@ use super::ITER_NTH;
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &hir::Expr<'_>,
-    nth_and_iter_args: &[&'tcx [hir::Expr<'tcx>]],
+    iter_recv: &'tcx hir::Expr<'tcx>,
+    nth_recv: &hir::Expr<'_>,
+    nth_arg: &hir::Expr<'_>,
     is_mut: bool,
 ) {
-    let iter_args = nth_and_iter_args[1];
     let mut_str = if is_mut { "_mut" } else { "" };
-    let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.typeck_results().expr_ty(&iter_args[0])).is_some() {
+    let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() {
         "slice"
-    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vec_type) {
+    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::vec_type) {
         "Vec"
-    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vecdeque_type) {
+    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::vecdeque_type) {
         "VecDeque"
     } else {
-        let nth_args = nth_and_iter_args[0];
-        iter_nth_zero::check(cx, expr, &nth_args);
+        iter_nth_zero::check(cx, expr, nth_recv, nth_arg);
         return; // caller is not a type that we want to lint
     };
 
diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs
index a12f672739c..52d7c15332e 100644
--- a/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/clippy_lints/src/methods/iter_nth_zero.rs
@@ -10,10 +10,10 @@ use rustc_span::sym;
 
 use super::ITER_NTH_ZERO;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
     if_chain! {
         if is_trait_method(cx, expr, sym::Iterator);
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &nth_args[1]);
+        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg);
         then {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args
                 expr.span,
                 "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
                 "try calling `.next()` instead of `.nth(0)`",
-                format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)),
+                format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)),
                 applicability,
             );
         }
diff --git a/clippy_lints/src/methods/iter_skip_next.rs b/clippy_lints/src/methods/iter_skip_next.rs
index b1d398876d3..e32594757d0 100644
--- a/clippy_lints/src/methods/iter_skip_next.rs
+++ b/clippy_lints/src/methods/iter_skip_next.rs
@@ -8,19 +8,17 @@ use rustc_span::sym;
 
 use super::ITER_SKIP_NEXT;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
     // lint if caller of skip is an Iterator
     if is_trait_method(cx, expr, sym::Iterator) {
-        if let [caller, n] = skip_args {
-            span_lint_and_sugg(
-                cx,
-                ITER_SKIP_NEXT,
-                expr.span.trim_start(caller.span).unwrap(),
-                "called `skip(..).next()` on an iterator",
-                "use `nth` instead",
-                format!(".nth({})", snippet(cx, n.span, "..")),
-                Applicability::MachineApplicable,
-            );
-        }
+        span_lint_and_sugg(
+            cx,
+            ITER_SKIP_NEXT,
+            expr.span.trim_start(recv.span).unwrap(),
+            "called `skip(..).next()` on an iterator",
+            "use `nth` instead",
+            format!(".nth({})", snippet(cx, arg.span, "..")),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/iterator_step_by_zero.rs b/clippy_lints/src/methods/iterator_step_by_zero.rs
index 3baa580314f..06b12998b1a 100644
--- a/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -7,9 +7,9 @@ use rustc_span::sym;
 
 use super::ITERATOR_STEP_BY_ZERO;
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
     if is_trait_method(cx, expr, sym::Iterator) {
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &args[1]) {
+        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg) {
             span_lint(
                 cx,
                 ITERATOR_STEP_BY_ZERO,
diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index f16699322d1..ecb8b72ef46 100644
--- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -8,11 +8,14 @@ use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_target::abi::LayoutOf;
 
-pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_>]], arith: &str) {
-    let unwrap_arg = &args[0][1];
-    let arith_lhs = &args[1][0];
-    let arith_rhs = &args[1][1];
-
+pub fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    arith_lhs: &hir::Expr<'_>,
+    arith_rhs: &hir::Expr<'_>,
+    unwrap_arg: &hir::Expr<'_>,
+    arith: &str,
+) {
     let ty = cx.typeck_results().expr_ty(arith_lhs);
     if !ty.is_integral() {
         return;
@@ -41,44 +44,28 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_>
             // "mul" is omitted because lhs can be negative.
             _ => return,
         }
-
-        let mut applicability = Applicability::MachineApplicable;
-        span_lint_and_sugg(
-            cx,
-            super::MANUAL_SATURATING_ARITHMETIC,
-            expr.span,
-            "manual saturating arithmetic",
-            &format!("try using `saturating_{}`", arith),
-            format!(
-                "{}.saturating_{}({})",
-                snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
-                arith,
-                snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
-            ),
-            applicability,
-        );
     } else {
         match (mm, arith) {
             (MinMax::Max, "add" | "mul") | (MinMax::Min, "sub") => (),
             _ => return,
         }
-
-        let mut applicability = Applicability::MachineApplicable;
-        span_lint_and_sugg(
-            cx,
-            super::MANUAL_SATURATING_ARITHMETIC,
-            expr.span,
-            "manual saturating arithmetic",
-            &format!("try using `saturating_{}`", arith),
-            format!(
-                "{}.saturating_{}({})",
-                snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
-                arith,
-                snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
-            ),
-            applicability,
-        );
     }
+
+    let mut applicability = Applicability::MachineApplicable;
+    span_lint_and_sugg(
+        cx,
+        super::MANUAL_SATURATING_ARITHMETIC,
+        expr.span,
+        "manual saturating arithmetic",
+        &format!("try using `saturating_{}`", arith),
+        format!(
+            "{}.saturating_{}({})",
+            snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
+            arith,
+            snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
+        ),
+        applicability,
+    );
 }
 
 #[derive(PartialEq, Eq)]
diff --git a/clippy_lints/src/methods/map_collect_result_unit.rs b/clippy_lints/src/methods/map_collect_result_unit.rs
index e4402b2da21..82063ad70b5 100644
--- a/clippy_lints/src/methods/map_collect_result_unit.rs
+++ b/clippy_lints/src/methods/map_collect_result_unit.rs
@@ -14,13 +14,13 @@ use super::MAP_COLLECT_RESULT_UNIT;
 pub(super) fn check(
     cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
-    map_args: &[hir::Expr<'_>],
-    collect_args: &[hir::Expr<'_>],
+    iter: &hir::Expr<'_>,
+    map_fn: &hir::Expr<'_>,
+    collect_recv: &hir::Expr<'_>,
 ) {
     if_chain! {
         // called on Iterator
-        if let [map_expr] = collect_args;
-        if is_trait_method(cx, map_expr, sym::Iterator);
+        if is_trait_method(cx, collect_recv, sym::Iterator);
         // return of collect `Result<(),_>`
         let collect_ret_ty = cx.typeck_results().expr_ty(expr);
         if is_type_diagnostic_item(cx, collect_ret_ty, sym::result_type);
@@ -28,7 +28,6 @@ pub(super) fn check(
         if let Some(result_t) = substs.types().next();
         if result_t.is_unit();
         // get parts for snippet
-        if let [iter, map_fn] = map_args;
         then {
             span_lint_and_sugg(
                 cx,
diff --git a/clippy_lints/src/methods/map_flatten.rs b/clippy_lints/src/methods/map_flatten.rs
index 4bc52b036a8..e8ad16bc0de 100644
--- a/clippy_lints/src/methods/map_flatten.rs
+++ b/clippy_lints/src/methods/map_flatten.rs
@@ -11,10 +11,15 @@ use rustc_span::symbol::sym;
 use super::MAP_FLATTEN;
 
 /// lint use of `map().flatten()` for `Iterators` and 'Options'
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) {
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'_>,
+    map_arg: &'tcx hir::Expr<'_>,
+) {
     // lint if caller of `.map().flatten()` is an Iterator
     if is_trait_method(cx, expr, sym::Iterator) {
-        let map_closure_ty = cx.typeck_results().expr_ty(&map_args[1]);
+        let map_closure_ty = cx.typeck_results().expr_ty(map_arg);
         let is_map_to_option = match map_closure_ty.kind() {
             ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) => {
                 let map_closure_sig = match map_closure_ty.kind() {
@@ -34,12 +39,12 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
             // `(...).map(...)` has type `impl Iterator<Item=impl Iterator<...>>
             "flat_map"
         };
-        let func_snippet = snippet(cx, map_args[1].span, "..");
+        let func_snippet = snippet(cx, map_arg.span, "..");
         let hint = format!(".{0}({1})", method_to_use, func_snippet);
         span_lint_and_sugg(
             cx,
             MAP_FLATTEN,
-            expr.span.with_lo(map_args[0].span.hi()),
+            expr.span.with_lo(recv.span.hi()),
             "called `map(..).flatten()` on an `Iterator`",
             &format!("try using `{}` instead", method_to_use),
             hint,
@@ -48,13 +53,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
     }
 
     // lint if caller of `.map().flatten()` is an Option
-    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type) {
-        let func_snippet = snippet(cx, map_args[1].span, "..");
+    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) {
+        let func_snippet = snippet(cx, map_arg.span, "..");
         let hint = format!(".and_then({})", func_snippet);
         span_lint_and_sugg(
             cx,
             MAP_FLATTEN,
-            expr.span.with_lo(map_args[0].span.hi()),
+            expr.span.with_lo(recv.span.hi()),
             "called `map(..).flatten()` on an `Option`",
             "try using `and_then` instead",
             hint,
diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs
index deb4b4492b5..4330fea727b 100644
--- a/clippy_lints/src/methods/map_unwrap_or.rs
+++ b/clippy_lints/src/methods/map_unwrap_or.rs
@@ -18,22 +18,23 @@ const MAP_UNWRAP_OR_MSRV: RustcVersion = RustcVersion::new(1, 41, 0);
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx hir::Expr<'_>,
-    map_args: &'tcx [hir::Expr<'_>],
-    unwrap_args: &'tcx [hir::Expr<'_>],
+    recv: &'tcx hir::Expr<'_>,
+    map_arg: &'tcx hir::Expr<'_>,
+    unwrap_arg: &'tcx hir::Expr<'_>,
     msrv: Option<&RustcVersion>,
 ) -> bool {
     if !meets_msrv(msrv, &MAP_UNWRAP_OR_MSRV) {
         return false;
     }
     // lint if the caller of `map()` is an `Option`
-    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type);
-    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::result_type);
+    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type);
+    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type);
 
     if is_option || is_result {
         // Don't make a suggestion that may fail to compile due to mutably borrowing
         // the same variable twice.
-        let map_mutated_vars = mutated_variables(&map_args[0], cx);
-        let unwrap_mutated_vars = mutated_variables(&unwrap_args[1], cx);
+        let map_mutated_vars = mutated_variables(recv, cx);
+        let unwrap_mutated_vars = mutated_variables(unwrap_arg, cx);
         if let (Some(map_mutated_vars), Some(unwrap_mutated_vars)) = (map_mutated_vars, unwrap_mutated_vars) {
             if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() {
                 return false;
@@ -51,14 +52,14 @@ pub(super) fn check<'tcx>(
             `.map_or_else(<g>, <f>)` instead"
         };
         // get snippets for args to map() and unwrap_or_else()
-        let map_snippet = snippet(cx, map_args[1].span, "..");
-        let unwrap_snippet = snippet(cx, unwrap_args[1].span, "..");
+        let map_snippet = snippet(cx, map_arg.span, "..");
+        let unwrap_snippet = snippet(cx, unwrap_arg.span, "..");
         // lint, with note if neither arg is > 1 line and both map() and
         // unwrap_or_else() have the same span
         let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
-        let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt();
+        let same_span = map_arg.span.ctxt() == unwrap_arg.span.ctxt();
         if same_span && !multiline {
-            let var_snippet = snippet(cx, map_args[0].span, "..");
+            let var_snippet = snippet(cx, recv.span, "..");
             span_lint_and_sugg(
                 cx,
                 MAP_UNWRAP_OR,
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index fccdee07877..b1ade5addd6 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -62,17 +62,18 @@ mod zst_offset;
 use bind_instead_of_map::BindInsteadOfMap;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
-use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, method_calls, paths, return_ty};
+use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, paths, return_ty};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_hir::{PrimTy, QPath, TraitItem, TraitItemKind};
+use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, TraitRef, Ty, TyS};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::symbol::{sym, SymbolStr};
+use rustc_span::symbol::SymbolStr;
+use rustc_span::{sym, Span};
 use rustc_typeck::hir_ty_to_ty;
 
 declare_clippy_lint! {
@@ -205,6 +206,13 @@ declare_clippy_lint! {
     /// |`to_`  | not `_mut` |`self`                 | `Copy`       |
     /// |`to_`  | not `_mut` |`&self`                | not `Copy`   |
     ///
+    /// Note: Clippy doesn't trigger methods with `to_` prefix in:
+    /// - Traits definition.
+    /// Clippy can not tell if a type that implements a trait is `Copy` or not.
+    /// - Traits implementation, when `&self` is taken.
+    /// The method signature is controlled by the trait and often `&self` is required for all types that implement the trait
+    /// (see e.g. the `std::string::ToString` trait).
+    ///
     /// Please find more info here:
     /// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
     ///
@@ -897,6 +905,28 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
+    /// **What it does:** Checks for indirect collection of populated `Option`
+    ///
+    /// **Why is this bad?** `Option` is like a collection of 0-1 things, so `flatten`
+    /// automatically does this without suspicious-looking `unwrap` calls.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// let _ = std::iter::empty::<Option<i32>>().filter(Option::is_some).map(Option::unwrap);
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let _ = std::iter::empty::<Option<i32>>().flatten();
+    /// ```
+    pub OPTION_FILTER_MAP,
+    complexity,
+    "filtering `Option` for `Some` then force-unwrapping, which can be one type-safe operation"
+}
+
+declare_clippy_lint! {
     /// **What it does:** Checks for the use of `iter.nth(0)`.
     ///
     /// **Why is this bad?** `iter.next()` is equivalent to
@@ -1651,6 +1681,7 @@ impl_lint_pass!(Methods => [
     FILTER_MAP_IDENTITY,
     MANUAL_FILTER_MAP,
     MANUAL_FIND_MAP,
+    OPTION_FILTER_MAP,
     FILTER_MAP_NEXT,
     FLAT_MAP_IDENTITY,
     MAP_FLATTEN,
@@ -1681,140 +1712,38 @@ impl_lint_pass!(Methods => [
     IMPLICIT_CLONE
 ]);
 
+/// Extracts a method call name, args, and `Span` of the method name.
+fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(SymbolStr, &'tcx [hir::Expr<'tcx>], Span)> {
+    if let ExprKind::MethodCall(path, span, args, _) = recv.kind {
+        if !args.iter().any(|e| e.span.from_expansion()) {
+            return Some((path.ident.name.as_str(), args, span));
+        }
+    }
+    None
+}
+
+/// Same as `method_call` but the `SymbolStr` is dereferenced into a temporary `&str`
+macro_rules! method_call {
+    ($expr:expr) => {
+        method_call($expr)
+            .as_ref()
+            .map(|&(ref name, args, span)| (&**name, args, span))
+    };
+}
+
 impl<'tcx> LateLintPass<'tcx> for Methods {
-    #[allow(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if in_macro(expr.span) {
             return;
         }
 
-        let (method_names, arg_lists, method_spans) = method_calls(expr, 2);
-        let method_names: Vec<SymbolStr> = method_names.iter().map(|s| s.as_str()).collect();
-        let method_names: Vec<&str> = method_names.iter().map(|s| &**s).collect();
-
-        match method_names.as_slice() {
-            ["unwrap", "get"] => get_unwrap::check(cx, expr, arg_lists[1], false),
-            ["unwrap", "get_mut"] => get_unwrap::check(cx, expr, arg_lists[1], true),
-            ["unwrap", ..] => unwrap_used::check(cx, expr, arg_lists[0]),
-            ["expect", "ok"] => ok_expect::check(cx, expr, arg_lists[1]),
-            ["expect", ..] => expect_used::check(cx, expr, arg_lists[0]),
-            ["unwrap_or", "map"] => option_map_unwrap_or::check(cx, expr, arg_lists[1], arg_lists[0], method_spans[1]),
-            ["unwrap_or_else", "map"] => {
-                if !map_unwrap_or::check(cx, expr, arg_lists[1], arg_lists[0], self.msrv.as_ref()) {
-                    unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "unwrap_or");
-                }
-            },
-            ["map_or", ..] => option_map_or_none::check(cx, expr, arg_lists[0]),
-            ["and_then", ..] => {
-                let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, arg_lists[0]);
-                let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, arg_lists[0]);
-                if !biom_option_linted && !biom_result_linted {
-                    unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "and");
-                }
-            },
-            ["or_else", ..] => {
-                if !bind_instead_of_map::ResultOrElseErrInfo::check(cx, expr, arg_lists[0]) {
-                    unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "or");
-                }
-            },
-            ["next", "filter"] => filter_next::check(cx, expr, arg_lists[1]),
-            ["next", "skip_while"] => skip_while_next::check(cx, expr, arg_lists[1]),
-            ["next", "iter"] => iter_next_slice::check(cx, expr, arg_lists[1]),
-            ["map", "filter"] => filter_map::check(cx, expr, false),
-            ["map", "filter_map"] => filter_map_map::check(cx, expr),
-            ["next", "filter_map"] => filter_map_next::check(cx, expr, arg_lists[1], self.msrv.as_ref()),
-            ["map", "find"] => filter_map::check(cx, expr, true),
-            ["flat_map", "filter"] => filter_flat_map::check(cx, expr),
-            ["flat_map", "filter_map"] => filter_map_flat_map::check(cx, expr),
-            ["flat_map", ..] => flat_map_identity::check(cx, expr, arg_lists[0], method_spans[0]),
-            ["flatten", "map"] => map_flatten::check(cx, expr, arg_lists[1]),
-            [option_check_method, "find"] if "is_some" == *option_check_method || "is_none" == *option_check_method => {
-                search_is_some::check(
-                    cx,
-                    expr,
-                    "find",
-                    option_check_method,
-                    arg_lists[1],
-                    arg_lists[0],
-                    method_spans[1],
-                )
-            },
-            [option_check_method, "position"]
-                if "is_some" == *option_check_method || "is_none" == *option_check_method =>
-            {
-                search_is_some::check(
-                    cx,
-                    expr,
-                    "position",
-                    option_check_method,
-                    arg_lists[1],
-                    arg_lists[0],
-                    method_spans[1],
-                )
-            },
-            [option_check_method, "rposition"]
-                if "is_some" == *option_check_method || "is_none" == *option_check_method =>
-            {
-                search_is_some::check(
-                    cx,
-                    expr,
-                    "rposition",
-                    option_check_method,
-                    arg_lists[1],
-                    arg_lists[0],
-                    method_spans[1],
-                )
-            },
-            ["extend", ..] => string_extend_chars::check(cx, expr, arg_lists[0]),
-            ["count", "into_iter"] => iter_count::check(cx, expr, &arg_lists[1], "into_iter"),
-            ["count", "iter"] => iter_count::check(cx, expr, &arg_lists[1], "iter"),
-            ["count", "iter_mut"] => iter_count::check(cx, expr, &arg_lists[1], "iter_mut"),
-            ["nth", "iter"] => iter_nth::check(cx, expr, &arg_lists, false),
-            ["nth", "iter_mut"] => iter_nth::check(cx, expr, &arg_lists, true),
-            ["nth", "bytes"] => bytes_nth::check(cx, expr, &arg_lists[1]),
-            ["nth", ..] => iter_nth_zero::check(cx, expr, arg_lists[0]),
-            ["step_by", ..] => iterator_step_by_zero::check(cx, expr, arg_lists[0]),
-            ["next", "skip"] => iter_skip_next::check(cx, expr, arg_lists[1]),
-            ["collect", "cloned"] => iter_cloned_collect::check(cx, expr, arg_lists[1]),
-            ["as_ref"] => useless_asref::check(cx, expr, "as_ref", arg_lists[0]),
-            ["as_mut"] => useless_asref::check(cx, expr, "as_mut", arg_lists[0]),
-            ["fold", ..] => unnecessary_fold::check(cx, expr, arg_lists[0], method_spans[0]),
-            ["filter_map", ..] => {
-                unnecessary_filter_map::check(cx, expr, arg_lists[0]);
-                filter_map_identity::check(cx, expr, arg_lists[0], method_spans[0]);
-            },
-            ["count", "map"] => suspicious_map::check(cx, expr, arg_lists[1], arg_lists[0]),
-            ["assume_init"] => uninit_assumed_init::check(cx, &arg_lists[0][0], expr),
-            ["unwrap_or", arith @ ("checked_add" | "checked_sub" | "checked_mul")] => {
-                manual_saturating_arithmetic::check(cx, expr, &arg_lists, &arith["checked_".len()..])
-            },
-            ["add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub"] => {
-                zst_offset::check(cx, expr, arg_lists[0])
-            },
-            ["is_file", ..] => filetype_is_file::check(cx, expr, arg_lists[0]),
-            ["map", "as_ref"] => {
-                option_as_ref_deref::check(cx, expr, arg_lists[1], arg_lists[0], false, self.msrv.as_ref())
-            },
-            ["map", "as_mut"] => {
-                option_as_ref_deref::check(cx, expr, arg_lists[1], arg_lists[0], true, self.msrv.as_ref())
-            },
-            ["unwrap_or_else", ..] => unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "unwrap_or"),
-            ["get_or_insert_with", ..] => unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "get_or_insert"),
-            ["ok_or_else", ..] => unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "ok_or"),
-            ["collect", "map"] => map_collect_result_unit::check(cx, expr, arg_lists[1], arg_lists[0]),
-            ["for_each", "inspect"] => inspect_for_each::check(cx, expr, method_spans[1]),
-            ["to_owned", ..] => implicit_clone::check(cx, expr, sym::ToOwned),
-            ["to_os_string", ..] => implicit_clone::check(cx, expr, sym::OsStr),
-            ["to_path_buf", ..] => implicit_clone::check(cx, expr, sym::Path),
-            ["to_vec", ..] => implicit_clone::check(cx, expr, sym::slice),
-            _ => {},
-        }
+        check_methods(cx, expr, self.msrv.as_ref());
 
         match expr.kind {
-            hir::ExprKind::Call(ref func, ref args) => {
+            hir::ExprKind::Call(func, args) => {
                 from_iter_instead_of_collect::check(cx, expr, args, &func.kind);
             },
-            hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => {
+            hir::ExprKind::MethodCall(method_call, ref method_span, args, _) => {
                 or_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args);
                 expect_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args);
                 clone_on_copy::check(cx, expr, method_call.ident.name, args);
@@ -1824,9 +1753,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 into_iter_on_ref::check(cx, expr, *method_span, method_call.ident.name, args);
                 single_char_pattern::check(cx, expr, method_call.ident.name, args);
             },
-            hir::ExprKind::Binary(op, ref lhs, ref rhs)
-                if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne =>
-            {
+            hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
                 let mut info = BinaryExprInfo {
                     expr,
                     chain: lhs,
@@ -1834,7 +1761,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                     eq: op.node == hir::BinOpKind::Eq,
                 };
                 lint_binary_expr_with_method_call(cx, &mut info);
-            }
+            },
             _ => (),
         }
     }
@@ -1850,10 +1777,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         let self_ty = cx.tcx.type_of(item.def_id);
 
         let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
-
         if_chain! {
             if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
-            if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next();
+            if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next();
 
             let method_sig = cx.tcx.fn_sig(impl_item.def_id);
             let method_sig = cx.tcx.erase_late_bound_regions(method_sig);
@@ -1873,7 +1799,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                             method_config.output_type.matches(&sig.decl.output) &&
                             method_config.self_kind.matches(cx, self_ty, first_arg_ty) &&
                             fn_header_equals(method_config.fn_header, sig.header) &&
-                            method_config.lifetime_param_cond(&impl_item)
+                            method_config.lifetime_param_cond(impl_item)
                         {
                             span_lint_and_help(
                                 cx,
@@ -1902,6 +1828,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                     self_ty,
                     first_arg_ty,
                     first_arg.pat.span,
+                    implements_trait,
                     false
                 );
             }
@@ -1960,11 +1887,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         if_chain! {
             if let TraitItemKind::Fn(ref sig, _) = item.kind;
             if let Some(first_arg_ty) = sig.decl.inputs.iter().next();
-            let first_arg_span = first_arg_ty.span;
-            let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
-            let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty();
-
             then {
+                let first_arg_span = first_arg_ty.span;
+                let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
+                let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty();
                 wrong_self_convention::check(
                     cx,
                     &item.ident.name.as_str(),
@@ -1972,6 +1898,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                     self_ty,
                     first_arg_ty,
                     first_arg_span,
+                    false,
                     true
                 );
             }
@@ -1997,6 +1924,140 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
 
     extract_msrv_attr!(LateContext);
 }
+
+#[allow(clippy::too_many_lines)]
+fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Option<&RustcVersion>) {
+    if let Some((name, [recv, args @ ..], span)) = method_call!(expr) {
+        match (name, args) {
+            ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [recv, _]) => {
+                zst_offset::check(cx, expr, recv)
+            },
+            ("and_then", [arg]) => {
+                let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
+                let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, recv, arg);
+                if !biom_option_linted && !biom_result_linted {
+                    unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
+                }
+            },
+            ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv),
+            ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv),
+            ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
+            ("collect", []) => match method_call!(recv) {
+                Some(("cloned", [recv2], _)) => iter_cloned_collect::check(cx, expr, recv2),
+                Some(("map", [m_recv, m_arg], _)) => {
+                    map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
+                },
+                _ => {},
+            },
+            ("count", []) => match method_call!(recv) {
+                Some((name @ ("into_iter" | "iter" | "iter_mut"), [recv2], _)) => {
+                    iter_count::check(cx, expr, recv2, name);
+                },
+                Some(("map", [_, arg], _)) => suspicious_map::check(cx, expr, recv, arg),
+                _ => {},
+            },
+            ("expect", [_]) => match method_call!(recv) {
+                Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
+                _ => expect_used::check(cx, expr, recv),
+            },
+            ("extend", [arg]) => string_extend_chars::check(cx, expr, recv, arg),
+            ("filter_map", [arg]) => {
+                unnecessary_filter_map::check(cx, expr, arg);
+                filter_map_identity::check(cx, expr, arg, span);
+            },
+            ("flat_map", [flm_arg]) => match method_call!(recv) {
+                Some(("filter", [_, _], _)) => filter_flat_map::check(cx, expr),
+                Some(("filter_map", [_, _], _)) => filter_map_flat_map::check(cx, expr),
+                _ => flat_map_identity::check(cx, expr, flm_arg, span),
+            },
+            ("flatten", []) => {
+                if let Some(("map", [recv, map_arg], _)) = method_call!(recv) {
+                    map_flatten::check(cx, expr, recv, map_arg);
+                }
+            },
+            ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span),
+            ("for_each", [_]) => {
+                if let Some(("inspect", [_, _], span2)) = method_call!(recv) {
+                    inspect_for_each::check(cx, expr, span2);
+                }
+            },
+            ("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"),
+            ("is_file", []) => filetype_is_file::check(cx, expr, recv),
+            ("is_none", []) => check_is_some_is_none(cx, expr, recv, false),
+            ("is_some", []) => check_is_some_is_none(cx, expr, recv, true),
+            ("map", [m_arg]) => {
+                if let Some((name, [recv2, args @ ..], span2)) = method_call!(recv) {
+                    match (name, args) {
+                        ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv),
+                        ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, msrv),
+                        ("filter", [f_arg]) => {
+                            filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false)
+                        },
+                        ("filter_map", [_]) => filter_map_map::check(cx, expr),
+                        ("find", [f_arg]) => filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, true),
+                        _ => {},
+                    }
+                }
+            },
+            ("map_or", [def, map]) => option_map_or_none::check(cx, expr, recv, def, map),
+            ("next", []) => {
+                if let Some((name, [recv, args @ ..], _)) = method_call!(recv) {
+                    match (name, args) {
+                        ("filter", [arg]) => filter_next::check(cx, expr, recv, arg),
+                        ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv, arg, msrv),
+                        ("iter", []) => iter_next_slice::check(cx, expr, recv),
+                        ("skip", [arg]) => iter_skip_next::check(cx, expr, recv, arg),
+                        ("skip_while", [_]) => skip_while_next::check(cx, expr),
+                        _ => {},
+                    }
+                }
+            },
+            ("nth", [n_arg]) => match method_call!(recv) {
+                Some(("bytes", [recv2], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
+                Some(("iter", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
+                Some(("iter_mut", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
+                _ => iter_nth_zero::check(cx, expr, recv, n_arg),
+            },
+            ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
+            ("or_else", [arg]) => {
+                if !bind_instead_of_map::ResultOrElseErrInfo::check(cx, expr, recv, arg) {
+                    unnecessary_lazy_eval::check(cx, expr, recv, arg, "or");
+                }
+            },
+            ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
+            ("to_os_string", []) => implicit_clone::check(cx, expr, sym::OsStr),
+            ("to_owned", []) => implicit_clone::check(cx, expr, sym::ToOwned),
+            ("to_path_buf", []) => implicit_clone::check(cx, expr, sym::Path),
+            ("to_vec", []) => implicit_clone::check(cx, expr, sym::slice),
+            ("unwrap", []) => match method_call!(recv) {
+                Some(("get", [recv, get_arg], _)) => get_unwrap::check(cx, expr, recv, get_arg, false),
+                Some(("get_mut", [recv, get_arg], _)) => get_unwrap::check(cx, expr, recv, get_arg, true),
+                _ => unwrap_used::check(cx, expr, recv),
+            },
+            ("unwrap_or", [u_arg]) => match method_call!(recv) {
+                Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => {
+                    manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
+                },
+                Some(("map", [m_recv, m_arg], span)) => {
+                    option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span)
+                },
+                _ => {},
+            },
+            ("unwrap_or_else", [u_arg]) => match method_call!(recv) {
+                Some(("map", [recv, map_arg], _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, msrv) => {},
+                _ => unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"),
+            },
+            _ => {},
+        }
+    }
+}
+
+fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
+    if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call!(recv) {
+        search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span)
+    }
+}
+
 /// Used for `lint_binary_expr_with_method_call`.
 #[derive(Copy, Clone)]
 struct BinaryExprInfo<'a> {
@@ -2209,10 +2270,10 @@ impl OutType {
         let is_unit = |ty: &hir::Ty<'_>| matches!(ty.kind, hir::TyKind::Tup(&[]));
         match (self, ty) {
             (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true,
-            (Self::Unit, &hir::FnRetTy::Return(ref ty)) if is_unit(ty) => true,
-            (Self::Bool, &hir::FnRetTy::Return(ref ty)) if is_bool(ty) => true,
-            (Self::Any, &hir::FnRetTy::Return(ref ty)) if !is_unit(ty) => true,
-            (Self::Ref, &hir::FnRetTy::Return(ref ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)),
+            (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true,
+            (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true,
+            (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true,
+            (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)),
             _ => false,
         }
     }
diff --git a/clippy_lints/src/methods/ok_expect.rs b/clippy_lints/src/methods/ok_expect.rs
index e6ce9cac397..d0b1b4b84be 100644
--- a/clippy_lints/src/methods/ok_expect.rs
+++ b/clippy_lints/src/methods/ok_expect.rs
@@ -9,11 +9,11 @@ use rustc_span::sym;
 use super::OK_EXPECT;
 
 /// lint use of `ok().expect()` for `Result`s
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
     if_chain! {
         // lint if the caller of `ok()` is a `Result`
-        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&ok_args[0]), sym::result_type);
-        let result_type = cx.typeck_results().expr_ty(&ok_args[0]);
+        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type);
+        let result_type = cx.typeck_results().expr_ty(recv);
         if let Some(error_type) = get_error_type(cx, result_type);
         if has_debug_impl(error_type, cx);
 
diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs
index d11ede080dc..7e9c8fa829d 100644
--- a/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -18,8 +18,8 @@ const OPTION_AS_REF_DEREF_MSRV: RustcVersion = RustcVersion::new(1, 40, 0);
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &hir::Expr<'_>,
-    as_ref_args: &[hir::Expr<'_>],
-    map_args: &[hir::Expr<'_>],
+    as_ref_recv: &hir::Expr<'_>,
+    map_arg: &hir::Expr<'_>,
     is_mut: bool,
     msrv: Option<&RustcVersion>,
 ) {
@@ -29,7 +29,7 @@ pub(super) fn check<'tcx>(
 
     let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not);
 
-    let option_ty = cx.typeck_results().expr_ty(&as_ref_args[0]);
+    let option_ty = cx.typeck_results().expr_ty(as_ref_recv);
     if !is_type_diagnostic_item(cx, option_ty, sym::option_type) {
         return;
     }
@@ -46,9 +46,9 @@ pub(super) fn check<'tcx>(
         &paths::VEC_AS_MUT_SLICE,
     ];
 
-    let is_deref = match map_args[1].kind {
+    let is_deref = match map_arg.kind {
         hir::ExprKind::Path(ref expr_qpath) => cx
-            .qpath_res(expr_qpath, map_args[1].hir_id)
+            .qpath_res(expr_qpath, map_arg.hir_id)
             .opt_def_id()
             .map_or(false, |fun_def_id| {
                 deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
@@ -77,10 +77,10 @@ pub(super) fn check<'tcx>(
                         }
                     }
                 },
-                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref inner) if same_mutability(m) => {
+                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, inner) if same_mutability(m) => {
                     if_chain! {
-                        if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner1) = inner.kind;
-                        if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner2) = inner1.kind;
+                        if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind;
+                        if let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind;
                         then {
                             path_to_local_id(inner2, closure_body.params[0].pat.hir_id)
                         } else {
@@ -96,12 +96,12 @@ pub(super) fn check<'tcx>(
 
     if is_deref {
         let current_method = if is_mut {
-            format!(".as_mut().map({})", snippet(cx, map_args[1].span, ".."))
+            format!(".as_mut().map({})", snippet(cx, map_arg.span, ".."))
         } else {
-            format!(".as_ref().map({})", snippet(cx, map_args[1].span, ".."))
+            format!(".as_ref().map({})", snippet(cx, map_arg.span, ".."))
         };
         let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" };
-        let hint = format!("{}.{}()", snippet(cx, as_ref_args[0].span, ".."), method_hint);
+        let hint = format!("{}.{}()", snippet(cx, as_ref_recv.span, ".."), method_hint);
         let suggestion = format!("try using {} instead", method_hint);
 
         let msg = format!(
diff --git a/clippy_lints/src/methods/option_map_or_none.rs b/clippy_lints/src/methods/option_map_or_none.rs
index d93db2c22e4..013a6f90ac9 100644
--- a/clippy_lints/src/methods/option_map_or_none.rs
+++ b/clippy_lints/src/methods/option_map_or_none.rs
@@ -11,9 +11,15 @@ use super::OPTION_MAP_OR_NONE;
 use super::RESULT_MAP_OR_INTO_OPTION;
 
 /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_or_args: &'tcx [hir::Expr<'_>]) {
-    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_or_args[0]), sym::option_type);
-    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_or_args[0]), sym::result_type);
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'_>,
+    def_arg: &'tcx hir::Expr<'_>,
+    map_arg: &'tcx hir::Expr<'_>,
+) {
+    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type);
+    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type);
 
     // There are two variants of this `map_or` lint:
     // (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>`
@@ -25,7 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
     }
 
     let (lint_name, msg, instead, hint) = {
-        let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].kind {
+        let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
             match_qpath(qpath, &paths::OPTION_NONE)
         } else {
             return;
@@ -36,15 +42,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
             return;
         }
 
-        let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_or_args[2].kind {
+        let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
             match_qpath(qpath, &paths::OPTION_SOME)
         } else {
             false
         };
 
         if is_option {
-            let self_snippet = snippet(cx, map_or_args[0].span, "..");
-            let func_snippet = snippet(cx, map_or_args[2].span, "..");
+            let self_snippet = snippet(cx, recv.span, "..");
+            let func_snippet = snippet(cx, map_arg.span, "..");
             let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
                        `and_then(..)` instead";
             (
@@ -56,7 +62,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
         } else if f_arg_is_some {
             let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \
                        `ok()` instead";
-            let self_snippet = snippet(cx, map_or_args[0].span, "..");
+            let self_snippet = snippet(cx, recv.span, "..");
             (
                 RESULT_MAP_OR_INTO_OPTION,
                 msg,
diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs
index e252abc177a..5bca49dec24 100644
--- a/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -18,13 +18,15 @@ use super::MAP_UNWRAP_OR;
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &rustc_hir::Expr<'_>,
-    map_args: &'tcx [rustc_hir::Expr<'_>],
-    unwrap_args: &'tcx [rustc_hir::Expr<'_>],
+    recv: &rustc_hir::Expr<'_>,
+    map_arg: &'tcx rustc_hir::Expr<'_>,
+    unwrap_recv: &rustc_hir::Expr<'_>,
+    unwrap_arg: &'tcx rustc_hir::Expr<'_>,
     map_span: Span,
 ) {
     // lint if the caller of `map()` is an `Option`
-    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type) {
-        if !is_copy(cx, cx.typeck_results().expr_ty(&unwrap_args[1])) {
+    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) {
+        if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) {
             // Do not lint if the `map` argument uses identifiers in the `map`
             // argument that are also used in the `unwrap_or` argument
 
@@ -32,27 +34,27 @@ pub(super) fn check<'tcx>(
                 cx,
                 identifiers: FxHashSet::default(),
             };
-            unwrap_visitor.visit_expr(&unwrap_args[1]);
+            unwrap_visitor.visit_expr(unwrap_arg);
 
             let mut map_expr_visitor = MapExprVisitor {
                 cx,
                 identifiers: unwrap_visitor.identifiers,
                 found_identifier: false,
             };
-            map_expr_visitor.visit_expr(&map_args[1]);
+            map_expr_visitor.visit_expr(map_arg);
 
             if map_expr_visitor.found_identifier {
                 return;
             }
         }
 
-        if differing_macro_contexts(unwrap_args[1].span, map_span) {
+        if differing_macro_contexts(unwrap_arg.span, map_span) {
             return;
         }
 
         let mut applicability = Applicability::MachineApplicable;
         // get snippet for unwrap_or()
-        let unwrap_snippet = snippet_with_applicability(cx, unwrap_args[1].span, "..", &mut applicability);
+        let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability);
         // lint message
         // comparing the snippet from source to raw text ("None") below is safe
         // because we already have checked the type.
@@ -70,14 +72,14 @@ pub(super) fn check<'tcx>(
         );
 
         span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| {
-            let map_arg_span = map_args[1].span;
+            let map_arg_span = map_arg.span;
 
             let mut suggestion = vec![
                 (
                     map_span,
                     String::from(if unwrap_snippet_none { "and_then" } else { "map_or" }),
                 ),
-                (expr.span.with_lo(unwrap_args[0].span.hi()), String::from("")),
+                (expr.span.with_lo(unwrap_recv.span.hi()), String::from("")),
             ];
 
             if !unwrap_snippet_none {
diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index 89dedc5f0d8..800172f4cf3 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/clippy_lints/src/methods/or_fun_call.rs
@@ -10,7 +10,7 @@ use rustc_hir::{BlockCheckMode, UnsafeSource};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::source_map::Span;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{kw, sym};
 use std::borrow::Cow;
 
 use super::OR_FUN_CALL;
@@ -38,8 +38,8 @@ pub(super) fn check<'tcx>(
             if !or_has_args;
             if name == "unwrap_or";
             if let hir::ExprKind::Path(ref qpath) = fun.kind;
-            let path = &*last_path_segment(qpath).ident.as_str();
-            if ["default", "new"].contains(&path);
+            let path = last_path_segment(qpath).ident.name;
+            if matches!(path, kw::Default | sym::new);
             let arg_ty = cx.typeck_results().expr_ty(arg);
             if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
             if implements_trait(cx, arg_ty, default_trait_id, &[]);
@@ -86,7 +86,7 @@ pub(super) fn check<'tcx>(
             (&paths::RESULT, true, &["or", "unwrap_or"], "else"),
         ];
 
-        if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = &arg.kind {
+        if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind {
             if path.ident.as_str() == "len" {
                 let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
 
@@ -105,7 +105,7 @@ pub(super) fn check<'tcx>(
             if KNOW_TYPES.iter().any(|k| k.2.contains(&name));
 
             if is_lazyness_candidate(cx, arg);
-            if !contains_return(&arg);
+            if !contains_return(arg);
 
             let self_ty = cx.typeck_results().expr_ty(self_expr);
 
@@ -158,7 +158,7 @@ pub(super) fn check<'tcx>(
 
     if args.len() == 2 {
         match args[1].kind {
-            hir::ExprKind::Call(ref fun, ref or_args) => {
+            hir::ExprKind::Call(fun, or_args) => {
                 let or_has_args = !or_args.is_empty();
                 if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) {
                     let fun_span = if or_has_args { None } else { Some(fun.span) };
diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index de7d168295f..ecec6fc3bb7 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -15,35 +15,37 @@ use super::SEARCH_IS_SOME;
 
 /// lint searching an Iterator followed by `is_some()`
 /// or calling `find()` on a string followed by `is_some()` or `is_none()`
-#[allow(clippy::too_many_lines)]
+#[allow(clippy::too_many_arguments, clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
+    cx: &LateContext<'_>,
     expr: &'tcx hir::Expr<'_>,
     search_method: &str,
-    option_check_method: &str,
-    search_args: &'tcx [hir::Expr<'_>],
-    is_some_args: &'tcx [hir::Expr<'_>],
+    is_some: bool,
+    search_recv: &hir::Expr<'_>,
+    search_arg: &'tcx hir::Expr<'_>,
+    is_some_recv: &hir::Expr<'_>,
     method_span: Span,
 ) {
+    let option_check_method = if is_some { "is_some" } else { "is_none" };
     // lint if caller of search is an Iterator
-    if is_trait_method(cx, &is_some_args[0], sym::Iterator) {
+    if is_trait_method(cx, is_some_recv, sym::Iterator) {
         let msg = format!(
             "called `{}()` after searching an `Iterator` with `{}`",
             option_check_method, search_method
         );
-        let search_snippet = snippet(cx, search_args[1].span, "..");
+        let search_snippet = snippet(cx, search_arg.span, "..");
         if search_snippet.lines().count() <= 1 {
             // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
             // suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
             let any_search_snippet = if_chain! {
                 if search_method == "find";
-                if let hir::ExprKind::Closure(_, _, body_id, ..) = search_args[1].kind;
+                if let hir::ExprKind::Closure(_, _, body_id, ..) = search_arg.kind;
                 let closure_body = cx.tcx.hir().body(body_id);
                 if let Some(closure_arg) = closure_body.params.get(0);
                 then {
                     if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
                         Some(search_snippet.replacen('&', "", 1))
-                    } else if let PatKind::Binding(_, _, ident, _) = strip_pat_refs(&closure_arg.pat).kind {
+                    } else if let PatKind::Binding(_, _, ident, _) = strip_pat_refs(closure_arg.pat).kind {
                         let name = &*ident.name.as_str();
                         Some(search_snippet.replace(&format!("*{}", name), name))
                     } else {
@@ -54,38 +56,34 @@ pub(super) fn check<'tcx>(
                 }
             };
             // add note if not multi-line
-            match option_check_method {
-                "is_some" => {
-                    span_lint_and_sugg(
-                        cx,
-                        SEARCH_IS_SOME,
-                        method_span.with_hi(expr.span.hi()),
-                        &msg,
-                        "use `any()` instead",
-                        format!(
-                            "any({})",
-                            any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
-                        ),
-                        Applicability::MachineApplicable,
-                    );
-                },
-                "is_none" => {
-                    let iter = snippet(cx, search_args[0].span, "..");
-                    span_lint_and_sugg(
-                        cx,
-                        SEARCH_IS_SOME,
-                        expr.span,
-                        &msg,
-                        "use `!_.any()` instead",
-                        format!(
-                            "!{}.any({})",
-                            iter,
-                            any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
-                        ),
-                        Applicability::MachineApplicable,
-                    );
-                },
-                _ => (),
+            if is_some {
+                span_lint_and_sugg(
+                    cx,
+                    SEARCH_IS_SOME,
+                    method_span.with_hi(expr.span.hi()),
+                    &msg,
+                    "use `any()` instead",
+                    format!(
+                        "any({})",
+                        any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
+                    ),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                let iter = snippet(cx, search_recv.span, "..");
+                span_lint_and_sugg(
+                    cx,
+                    SEARCH_IS_SOME,
+                    expr.span,
+                    &msg,
+                    "use `!_.any()` instead",
+                    format!(
+                        "!{}.any({})",
+                        iter,
+                        any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
+                    ),
+                    Applicability::MachineApplicable,
+                );
             }
         } else {
             let hint = format!(
@@ -110,14 +108,14 @@ pub(super) fn check<'tcx>(
             }
         };
         if_chain! {
-            if is_string_or_str_slice(&search_args[0]);
-            if is_string_or_str_slice(&search_args[1]);
+            if is_string_or_str_slice(search_recv);
+            if is_string_or_str_slice(search_arg);
             then {
                 let msg = format!("called `{}()` after calling `find()` on a string", option_check_method);
                 match option_check_method {
                     "is_some" => {
                         let mut applicability = Applicability::MachineApplicable;
-                        let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability);
+                        let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
                         span_lint_and_sugg(
                             cx,
                             SEARCH_IS_SOME,
@@ -129,9 +127,9 @@ pub(super) fn check<'tcx>(
                         );
                     },
                     "is_none" => {
-                        let string = snippet(cx, search_args[0].span, "..");
+                        let string = snippet(cx, search_recv.span, "..");
                         let mut applicability = Applicability::MachineApplicable;
-                        let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability);
+                        let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
                         span_lint_and_sugg(
                             cx,
                             SEARCH_IS_SOME,
diff --git a/clippy_lints/src/methods/skip_while_next.rs b/clippy_lints/src/methods/skip_while_next.rs
index 3db83785b59..9f0b6c34ea2 100644
--- a/clippy_lints/src/methods/skip_while_next.rs
+++ b/clippy_lints/src/methods/skip_while_next.rs
@@ -7,7 +7,7 @@ use rustc_span::sym;
 use super::SKIP_WHILE_NEXT;
 
 /// lint use of `skip_while().next()` for `Iterators`
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _skip_while_args: &'tcx [hir::Expr<'_>]) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
     // lint if caller of `.skip_while().next()` is an Iterator
     if is_trait_method(cx, expr, sym::Iterator) {
         span_lint_and_help(
diff --git a/clippy_lints/src/methods/string_extend_chars.rs b/clippy_lints/src/methods/string_extend_chars.rs
index 5c688ac5621..6e7890a3080 100644
--- a/clippy_lints/src/methods/string_extend_chars.rs
+++ b/clippy_lints/src/methods/string_extend_chars.rs
@@ -10,12 +10,11 @@ use rustc_span::symbol::sym;
 
 use super::STRING_EXTEND_CHARS;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
-    let obj_ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
+    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
     if !is_type_diagnostic_item(cx, obj_ty, sym::string_type) {
         return;
     }
-    let arg = &args[1];
     if let Some(arglists) = method_chain_args(arg, &["chars"]) {
         let target = &arglists[0][0];
         let self_ty = cx.typeck_results().expr_ty(target).peel_refs();
@@ -36,7 +35,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
             "try this",
             format!(
                 "{}.push_str({}{})",
-                snippet_with_applicability(cx, args[0].span, "..", &mut applicability),
+                snippet_with_applicability(cx, recv.span, "..", &mut applicability),
                 ref_str,
                 snippet_with_applicability(cx, target.span, "..", &mut applicability)
             ),
diff --git a/clippy_lints/src/methods/suspicious_map.rs b/clippy_lints/src/methods/suspicious_map.rs
index 7015bd54c35..0fd0668c734 100644
--- a/clippy_lints/src/methods/suspicious_map.rs
+++ b/clippy_lints/src/methods/suspicious_map.rs
@@ -8,15 +8,8 @@ use rustc_span::sym;
 
 use super::SUSPICIOUS_MAP;
 
-pub fn check<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &hir::Expr<'_>,
-    map_args: &[hir::Expr<'_>],
-    count_args: &[hir::Expr<'_>],
-) {
+pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
     if_chain! {
-        if let [count_recv] = count_args;
-        if let [_, map_arg] = map_args;
         if is_trait_method(cx, count_recv, sym::Iterator);
         let closure = expr_or_init(cx, map_arg);
         if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(closure.hir_id);
diff --git a/clippy_lints/src/methods/uninit_assumed_init.rs b/clippy_lints/src/methods/uninit_assumed_init.rs
index f2f6ef4be6c..0ae65c0c01d 100644
--- a/clippy_lints/src/methods/uninit_assumed_init.rs
+++ b/clippy_lints/src/methods/uninit_assumed_init.rs
@@ -8,18 +8,18 @@ use rustc_middle::ty::{self, Ty};
 use super::UNINIT_ASSUMED_INIT;
 
 /// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter)
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, outer: &hir::Expr<'_>) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
     if_chain! {
-        if let hir::ExprKind::Call(ref callee, ref args) = expr.kind;
+        if let hir::ExprKind::Call(callee, args) = recv.kind;
         if args.is_empty();
         if let hir::ExprKind::Path(ref path) = callee.kind;
         if match_qpath(path, &paths::MEM_MAYBEUNINIT_UNINIT);
-        if !is_maybe_uninit_ty_valid(cx, cx.typeck_results().expr_ty_adjusted(outer));
+        if !is_maybe_uninit_ty_valid(cx, cx.typeck_results().expr_ty_adjusted(expr));
         then {
             span_lint(
                 cx,
                 UNINIT_ASSUMED_INIT,
-                outer.span,
+                expr.span,
                 "this call for this type may be undefined behavior"
             );
         }
@@ -28,9 +28,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, outer: &hir::Exp
 
 fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
     match ty.kind() {
-        ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component),
-        ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)),
-        ty::Adt(ref adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT),
+        ty::Array(component, _) => is_maybe_uninit_ty_valid(cx, component),
+        ty::Tuple(types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)),
+        ty::Adt(adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT),
         _ => false,
     }
 }
diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs
index 48d905ab833..0f28bfdf09e 100644
--- a/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::{is_trait_method, match_qpath, path_to_local_id, paths};
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_lint::LateContext;
@@ -10,20 +9,20 @@ use rustc_span::sym;
 
 use super::UNNECESSARY_FILTER_MAP;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
     if !is_trait_method(cx, expr, sym::Iterator) {
         return;
     }
 
-    if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].kind {
+    if let hir::ExprKind::Closure(_, _, body_id, ..) = arg.kind {
         let body = cx.tcx.hir().body(body_id);
         let arg_id = body.params[0].pat.hir_id;
         let mutates_arg =
             mutated_variables(&body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id));
 
-        let (mut found_mapping, mut found_filtering) = check_expression(&cx, arg_id, &body.value);
+        let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, &body.value);
 
-        let mut return_visitor = ReturnVisitor::new(&cx, arg_id);
+        let mut return_visitor = ReturnVisitor::new(cx, arg_id);
         return_visitor.visit_expr(&body.value);
         found_mapping |= return_visitor.found_mapping;
         found_filtering |= return_visitor.found_filtering;
@@ -53,38 +52,35 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
 // returns (found_mapping, found_filtering)
 fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) {
     match &expr.kind {
-        hir::ExprKind::Call(ref func, ref args) => {
-            if_chain! {
-                if let hir::ExprKind::Path(ref path) = func.kind;
-                then {
-                    if match_qpath(path, &paths::OPTION_SOME) {
-                        if path_to_local_id(&args[0], arg_id) {
-                            return (false, false)
-                        }
-                        return (true, false);
+        hir::ExprKind::Call(func, args) => {
+            if let hir::ExprKind::Path(ref path) = func.kind {
+                if match_qpath(path, &paths::OPTION_SOME) {
+                    if path_to_local_id(&args[0], arg_id) {
+                        return (false, false);
                     }
-                    // We don't know. It might do anything.
-                    return (true, true);
+                    return (true, false);
                 }
+                // We don't know. It might do anything.
+                return (true, true);
             }
             (true, true)
         },
-        hir::ExprKind::Block(ref block, _) => block
+        hir::ExprKind::Block(block, _) => block
             .expr
             .as_ref()
-            .map_or((false, false), |expr| check_expression(cx, arg_id, &expr)),
+            .map_or((false, false), |expr| check_expression(cx, arg_id, expr)),
         hir::ExprKind::Match(_, arms, _) => {
             let mut found_mapping = false;
             let mut found_filtering = false;
             for arm in *arms {
-                let (m, f) = check_expression(cx, arg_id, &arm.body);
+                let (m, f) = check_expression(cx, arg_id, arm.body);
                 found_mapping |= m;
                 found_filtering |= f;
             }
             (found_mapping, found_filtering)
         },
         // There must be an else_arm or there will be a type error
-        hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => {
+        hir::ExprKind::If(_, if_arm, Some(else_arm)) => {
             let if_check = check_expression(cx, arg_id, if_arm);
             let else_check = check_expression(cx, arg_id, else_arm);
             (if_check.0 | else_check.0, if_check.1 | else_check.1)
diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs
index 1268fd4bda9..75517c48a21 100644
--- a/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/clippy_lints/src/methods/unnecessary_fold.rs
@@ -11,11 +11,17 @@ use rustc_span::{source_map::Span, sym};
 
 use super::UNNECESSARY_FOLD;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir::Expr<'_>], fold_span: Span) {
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    init: &hir::Expr<'_>,
+    acc: &hir::Expr<'_>,
+    fold_span: Span,
+) {
     fn check_fold_with_op(
         cx: &LateContext<'_>,
         expr: &hir::Expr<'_>,
-        fold_args: &[hir::Expr<'_>],
+        acc: &hir::Expr<'_>,
         fold_span: Span,
         op: hir::BinOpKind,
         replacement_method_name: &str,
@@ -23,18 +29,18 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir
     ) {
         if_chain! {
             // Extract the body of the closure passed to fold
-            if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].kind;
+            if let hir::ExprKind::Closure(_, _, body_id, _, _) = acc.kind;
             let closure_body = cx.tcx.hir().body(body_id);
             let closure_expr = remove_blocks(&closure_body.value);
 
             // Check if the closure body is of the form `acc <op> some_expr(x)`
-            if let hir::ExprKind::Binary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.kind;
+            if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind;
             if bin_op.node == op;
 
             // Extract the names of the two arguments to the closure
             if let [param_a, param_b] = closure_body.params;
-            if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(&param_a.pat).kind;
-            if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(&param_b.pat).kind;
+            if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind;
+            if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind;
 
             if path_to_local_id(left_expr, first_arg_id);
             if replacement_has_args || path_to_local_id(right_expr, second_arg_id);
@@ -74,25 +80,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir
         return;
     }
 
-    assert!(
-        fold_args.len() == 3,
-        "Expected fold_args to have three entries - the receiver, the initial value and the closure"
-    );
-
     // Check if the first argument to .fold is a suitable literal
-    if let hir::ExprKind::Lit(ref lit) = fold_args[1].kind {
+    if let hir::ExprKind::Lit(ref lit) = init.kind {
         match lit.node {
-            ast::LitKind::Bool(false) => {
-                check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::Or, "any", true)
-            },
-            ast::LitKind::Bool(true) => {
-                check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::And, "all", true)
-            },
-            ast::LitKind::Int(0, _) => {
-                check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::Add, "sum", false)
-            },
+            ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true),
+            ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true),
+            ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false),
             ast::LitKind::Int(1, _) => {
-                check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::Mul, "product", false)
+                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false)
             },
             _ => (),
         }
diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index a86185bf0a6..b7380883a5e 100644
--- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -14,14 +14,15 @@ use super::UNNECESSARY_LAZY_EVALUATIONS;
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx hir::Expr<'_>,
-    args: &'tcx [hir::Expr<'_>],
+    recv: &'tcx hir::Expr<'_>,
+    arg: &'tcx hir::Expr<'_>,
     simplify_using: &str,
 ) {
-    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym::option_type);
-    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym::result_type);
+    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type);
+    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type);
 
     if is_option || is_result {
-        if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind {
+        if let hir::ExprKind::Closure(_, _, eid, _, _) = arg.kind {
             let body = cx.tcx.hir().body(eid);
             let body_expr = &body.value;
 
@@ -55,7 +56,7 @@ pub(super) fn check<'tcx>(
                     &format!("use `{}` instead", simplify_using),
                     format!(
                         "{0}.{1}({2})",
-                        snippet(cx, args[0].span, ".."),
+                        snippet(cx, recv.span, ".."),
                         simplify_using,
                         snippet(cx, body_expr.span, ".."),
                     ),
diff --git a/clippy_lints/src/methods/unwrap_used.rs b/clippy_lints/src/methods/unwrap_used.rs
index 2f5806115bd..7fd1948594d 100644
--- a/clippy_lints/src/methods/unwrap_used.rs
+++ b/clippy_lints/src/methods/unwrap_used.rs
@@ -7,8 +7,8 @@ use rustc_span::sym;
 use super::UNWRAP_USED;
 
 /// lint use of `unwrap()` for `Option`s and `Result`s
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) {
-    let obj_ty = cx.typeck_results().expr_ty(&unwrap_args[0]).peel_refs();
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
+    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
 
     let mess = if is_type_diagnostic_item(cx, obj_ty, sym::option_type) {
         Some((UNWRAP_USED, "an Option", "None"))
diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs
index b5505af0f7e..e0b1de68b37 100644
--- a/clippy_lints/src/methods/useless_asref.rs
+++ b/clippy_lints/src/methods/useless_asref.rs
@@ -10,12 +10,11 @@ use rustc_lint::LateContext;
 use super::USELESS_ASREF;
 
 /// Checks for the `USELESS_ASREF` lint.
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, as_ref_args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, recvr: &hir::Expr<'_>) {
     // when we get here, we've already checked that the call name is "as_ref" or "as_mut"
     // check if the call is to the actual `AsRef` or `AsMut` trait
     if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) {
         // check if the type after `as_ref` or `as_mut` is the same as before
-        let recvr = &as_ref_args[0];
         let rcv_ty = cx.typeck_results().expr_ty(recvr);
         let res_ty = cx.typeck_results().expr_ty(expr);
         let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty);
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index ac6b55396da..f6bf37e08b9 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -26,7 +26,7 @@ pub(super) fn derefs_to_slice<'tcx>(
         }
     }
 
-    if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
+    if let hir::ExprKind::MethodCall(path, _, args, _) = expr.kind {
         if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) {
             Some(&args[0])
         } else {
diff --git a/clippy_lints/src/methods/wrong_self_convention.rs b/clippy_lints/src/methods/wrong_self_convention.rs
index 59e683aa9a7..1e0de249a91 100644
--- a/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/clippy_lints/src/methods/wrong_self_convention.rs
@@ -21,8 +21,10 @@ const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [
 
     // Conversion using `to_` can use borrowed (non-Copy types) or owned (Copy types).
     // Source: https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
-    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), Convention::ImplementsTrait(false)], &[SelfKind::Ref]),
-    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), Convention::ImplementsTrait(false)], &[SelfKind::Value]),
+    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), 
+    Convention::IsTraitItem(false)], &[SelfKind::Ref]),
+    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), 
+    Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Value]),
 ];
 
 enum Convention {
@@ -32,18 +34,27 @@ enum Convention {
     NotEndsWith(&'static str),
     IsSelfTypeCopy(bool),
     ImplementsTrait(bool),
+    IsTraitItem(bool),
 }
 
 impl Convention {
     #[must_use]
-    fn check<'tcx>(&self, cx: &LateContext<'tcx>, self_ty: &'tcx TyS<'tcx>, other: &str, is_trait_def: bool) -> bool {
+    fn check<'tcx>(
+        &self,
+        cx: &LateContext<'tcx>,
+        self_ty: &'tcx TyS<'tcx>,
+        other: &str,
+        implements_trait: bool,
+        is_trait_item: bool,
+    ) -> bool {
         match *self {
             Self::Eq(this) => this == other,
             Self::StartsWith(this) => other.starts_with(this) && this != other,
             Self::EndsWith(this) => other.ends_with(this) && this != other,
-            Self::NotEndsWith(this) => !Self::EndsWith(this).check(cx, self_ty, other, is_trait_def),
+            Self::NotEndsWith(this) => !Self::EndsWith(this).check(cx, self_ty, other, implements_trait, is_trait_item),
             Self::IsSelfTypeCopy(is_true) => is_true == is_copy(cx, self_ty),
-            Self::ImplementsTrait(is_true) => is_true == is_trait_def,
+            Self::ImplementsTrait(is_true) => is_true == implements_trait,
+            Self::IsTraitItem(is_true) => is_true == is_trait_item,
         }
     }
 }
@@ -60,12 +71,17 @@ impl fmt::Display for Convention {
             },
             Self::ImplementsTrait(is_true) => {
                 let (negation, s_suffix) = if is_true { ("", "s") } else { (" does not", "") };
-                format!("Method{} implement{} a trait", negation, s_suffix).fmt(f)
+                format!("method{} implement{} a trait", negation, s_suffix).fmt(f)
+            },
+            Self::IsTraitItem(is_true) => {
+                let suffix = if is_true { " is" } else { " is not" };
+                format!("method{} a trait item", suffix).fmt(f)
             },
         }
     }
 }
 
+#[allow(clippy::too_many_arguments)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     item_name: &str,
@@ -73,6 +89,7 @@ pub(super) fn check<'tcx>(
     self_ty: &'tcx TyS<'tcx>,
     first_arg_ty: &'tcx TyS<'tcx>,
     first_arg_span: Span,
+    implements_trait: bool,
     is_trait_item: bool,
 ) {
     let lint = if is_pub {
@@ -83,7 +100,7 @@ pub(super) fn check<'tcx>(
     if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| {
         convs
             .iter()
-            .all(|conv| conv.check(cx, self_ty, item_name, is_trait_item))
+            .all(|conv| conv.check(cx, self_ty, item_name, implements_trait, is_trait_item))
     }) {
         if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) {
             let suggestion = {
@@ -99,6 +116,7 @@ pub(super) fn check<'tcx>(
                         .filter_map(|conv| {
                             if (cut_ends_with_conv && matches!(conv, Convention::NotEndsWith(_)))
                                 || matches!(conv, Convention::ImplementsTrait(_))
+                                || matches!(conv, Convention::IsTraitItem(_))
                             {
                                 None
                             } else {
diff --git a/clippy_lints/src/methods/zst_offset.rs b/clippy_lints/src/methods/zst_offset.rs
index 9f6a7c4db17..866cf616679 100644
--- a/clippy_lints/src/methods/zst_offset.rs
+++ b/clippy_lints/src/methods/zst_offset.rs
@@ -6,10 +6,9 @@ use rustc_middle::ty;
 
 use super::ZST_OFFSET;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
     if_chain! {
-        if args.len() == 2;
-        if let ty::RawPtr(ty::TypeAndMut { ref ty, .. }) = cx.typeck_results().expr_ty(&args[0]).kind();
+        if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind();
         if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
         if layout.is_zst();
         then {
diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs
index 776f4c7b741..45948f4d926 100644
--- a/clippy_lints/src/minmax.rs
+++ b/clippy_lints/src/minmax.rs
@@ -67,7 +67,7 @@ enum MinMax {
 
 fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
     match expr.kind {
-        ExprKind::Call(ref path, ref args) => {
+        ExprKind::Call(path, args) => {
             if let ExprKind::Path(ref qpath) = path.kind {
                 cx.typeck_results()
                     .qpath_res(qpath, path.hir_id)
@@ -85,7 +85,7 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
                 None
             }
         },
-        ExprKind::MethodCall(ref path, _, ref args, _) => {
+        ExprKind::MethodCall(path, _, args, _) => {
             if_chain! {
                 if let [obj, _] = args;
                 if cx.typeck_results().expr_ty(obj).is_floating_point() || match_trait_method(cx, expr, &paths::ORD);
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 026ea50936a..afced5a5ce5 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -304,55 +304,54 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         if_chain! {
             if !in_external_macro(cx.tcx.sess, stmt.span);
-            if let StmtKind::Local(ref local) = stmt.kind;
+            if let StmtKind::Local(local) = stmt.kind;
             if let PatKind::Binding(an, .., name, None) = local.pat.kind;
-            if let Some(ref init) = local.init;
+            if let Some(init) = local.init;
             if !higher::is_from_for_desugar(local);
+            if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut;
             then {
-                if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut {
-                    // use the macro callsite when the init span (but not the whole local span)
-                    // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
-                    let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() {
-                        Sugg::hir_with_macro_callsite(cx, init, "..")
-                    } else {
-                        Sugg::hir(cx, init, "..")
-                    };
-                    let (mutopt, initref) = if an == BindingAnnotation::RefMut {
-                        ("mut ", sugg_init.mut_addr())
-                    } else {
-                        ("", sugg_init.addr())
-                    };
-                    let tyopt = if let Some(ref ty) = local.ty {
-                        format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, ".."))
-                    } else {
-                        String::new()
-                    };
-                    span_lint_hir_and_then(
-                        cx,
-                        TOPLEVEL_REF_ARG,
-                        init.hir_id,
-                        local.pat.span,
-                        "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
-                        |diag| {
-                            diag.span_suggestion(
-                                stmt.span,
-                                "try",
-                                format!(
-                                    "let {name}{tyopt} = {initref};",
-                                    name=snippet(cx, name.span, ".."),
-                                    tyopt=tyopt,
-                                    initref=initref,
-                                ),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    );
-                }
+                // use the macro callsite when the init span (but not the whole local span)
+                // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
+                let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() {
+                    Sugg::hir_with_macro_callsite(cx, init, "..")
+                } else {
+                    Sugg::hir(cx, init, "..")
+                };
+                let (mutopt, initref) = if an == BindingAnnotation::RefMut {
+                    ("mut ", sugg_init.mut_addr())
+                } else {
+                    ("", sugg_init.addr())
+                };
+                let tyopt = if let Some(ty) = local.ty {
+                    format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, ".."))
+                } else {
+                    String::new()
+                };
+                span_lint_hir_and_then(
+                    cx,
+                    TOPLEVEL_REF_ARG,
+                    init.hir_id,
+                    local.pat.span,
+                    "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
+                    |diag| {
+                        diag.span_suggestion(
+                            stmt.span,
+                            "try",
+                            format!(
+                                "let {name}{tyopt} = {initref};",
+                                name=snippet(cx, name.span, ".."),
+                                tyopt=tyopt,
+                                initref=initref,
+                            ),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                );
             }
         };
         if_chain! {
-            if let StmtKind::Semi(ref expr) = stmt.kind;
-            if let ExprKind::Binary(ref binop, ref a, ref b) = expr.kind;
+            if let StmtKind::Semi(expr) = stmt.kind;
+            if let ExprKind::Binary(ref binop, a, b) = expr.kind;
             if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
             if let Some(sugg) = Sugg::hir_opt(cx, a);
             then {
@@ -379,11 +378,11 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         match expr.kind {
-            ExprKind::Cast(ref e, ref ty) => {
+            ExprKind::Cast(e, ty) => {
                 check_cast(cx, expr.span, e, ty);
                 return;
             },
-            ExprKind::Binary(ref cmp, ref left, ref right) => {
+            ExprKind::Binary(ref cmp, left, right) => {
                 check_binary(cx, expr, cmp, left, right);
                 return;
             },
@@ -462,21 +461,18 @@ fn check_nan(cx: &LateContext<'_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) {
     if_chain! {
         if !in_constant(cx, cmp_expr.hir_id);
         if let Some((value, _)) = constant(cx, cx.typeck_results(), expr);
+        if match value {
+            Constant::F32(num) => num.is_nan(),
+            Constant::F64(num) => num.is_nan(),
+            _ => false,
+        };
         then {
-            let needs_lint = match value {
-                Constant::F32(num) => num.is_nan(),
-                Constant::F64(num) => num.is_nan(),
-                _ => false,
-            };
-
-            if needs_lint {
-                span_lint(
-                    cx,
-                    CMP_NAN,
-                    cmp_expr.span,
-                    "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead",
-                );
-            }
+            span_lint(
+                cx,
+                CMP_NAN,
+                cmp_expr.span,
+                "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead",
+            );
         }
     }
 }
@@ -505,12 +501,12 @@ fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
 // Return true if `expr` is the result of `signum()` invoked on a float value.
 fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     // The negation of a signum is still a signum
-    if let ExprKind::Unary(UnOp::Neg, ref child_expr) = expr.kind {
-        return is_signum(cx, &child_expr);
+    if let ExprKind::Unary(UnOp::Neg, child_expr) = expr.kind {
+        return is_signum(cx, child_expr);
     }
 
     if_chain! {
-        if let ExprKind::MethodCall(ref method_name, _, ref expressions, _) = expr.kind;
+        if let ExprKind::MethodCall(method_name, _, expressions, _) = expr.kind;
         if sym!(signum) == method_name.ident.name;
         // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
         // the method call)
@@ -556,7 +552,7 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left:
     }
 
     let (arg_ty, snip) = match expr.kind {
-        ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
+        ExprKind::MethodCall(.., args, _) if args.len() == 1 => {
             if_chain!(
                 if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
                 if is_diagnostic_assoc_item(cx, expr_def_id, sym::ToString)
@@ -568,7 +564,7 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left:
                 }
             )
         },
-        ExprKind::Call(ref path, ref v) if v.len() == 1 => {
+        ExprKind::Call(path, v) if v.len() == 1 => {
             if let ExprKind::Path(ref path) = path.kind {
                 if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
                     (cx.typeck_results().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
@@ -653,7 +649,7 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left:
 /// of what it means for an expression to be "used".
 fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind {
-        ExprKind::Assign(_, ref rhs, _) | ExprKind::AssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr),
+        ExprKind::Assign(_, rhs, _) | ExprKind::AssignOp(_, _, rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr),
         _ => is_used(cx, parent),
     })
 }
diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs
index 23554669d97..0dc02431ad5 100644
--- a/clippy_lints/src/missing_const_for_fn.rs
+++ b/clippy_lints/src/missing_const_for_fn.rs
@@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
 
         let mir = cx.tcx.optimized_mir(def_id);
 
-        if let Err((span, err)) = is_min_const_fn(cx.tcx, &mir) {
+        if let Err((span, err)) = is_min_const_fn(cx.tcx, mir) {
             if rustc_mir::const_eval::is_min_const_fn(cx.tcx, def_id.to_def_id()) {
                 cx.tcx.sess.span_err(span, &err);
             }
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index 21b4983a1af..dfab3e8a931 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -5,10 +5,10 @@
 // [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415
 //
 
+use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
-use rustc_ast::attr;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
@@ -93,9 +93,9 @@ impl MissingDoc {
             return;
         }
 
-        let has_doc = attrs
-            .iter()
-            .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta()));
+        let has_doc = attrs.iter().any(|a| {
+            a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta())
+        });
         if !has_doc {
             span_lint(
                 cx,
@@ -111,14 +111,7 @@ impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
 
 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
-        let doc_hidden = self.doc_hidden()
-            || attrs.iter().any(|attr| {
-                attr.has_name(sym::doc)
-                    && match attr.meta_item_list() {
-                        None => false,
-                        Some(l) => attr::list_contains_name(&l[..], sym::hidden),
-                    }
-            });
+        let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
         self.doc_hidden_stack.push(doc_hidden);
     }
 
diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs
index dd4488f3f02..041fe64a1a9 100644
--- a/clippy_lints/src/missing_inline.rs
+++ b/clippy_lints/src/missing_inline.rs
@@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
                 let attrs = cx.tcx.hir().attrs(it.hir_id());
                 check_missing_inline_attrs(cx, attrs, it.span, desc);
             },
-            hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, trait_items) => {
+            hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, _bounds, trait_items) => {
                 // note: we need to check if the trait is exported so we can't use
                 // `LateLintPass::check_trait_item` here.
                 for tit in trait_items {
diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index 4d3dff36a20..1786d5805d7 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/clippy_lints/src/mut_key.rs
@@ -59,21 +59,21 @@ declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]);
 impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
-            check_sig(cx, item.hir_id(), &sig.decl);
+            check_sig(cx, item.hir_id(), sig.decl);
         }
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
         if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
             if trait_ref_of_method(cx, item.hir_id()).is_none() {
-                check_sig(cx, item.hir_id(), &sig.decl);
+                check_sig(cx, item.hir_id(), sig.decl);
             }
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
         if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
-            check_sig(cx, item.hir_id(), &sig.decl);
+            check_sig(cx, item.hir_id(), sig.decl);
         }
     }
 
diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs
index ef33e41a5fa..4b9c51d0c16 100644
--- a/clippy_lints/src/mut_mut.rs
+++ b/clippy_lints/src/mut_mut.rs
@@ -62,7 +62,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
             // Let's ignore the generated code.
             intravisit::walk_expr(self, arg);
             intravisit::walk_expr(self, body);
-        } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, ref e) = expr.kind {
+        } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e) = expr.kind {
             if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) = e.kind {
                 span_lint(
                     self.cx,
@@ -85,7 +85,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
         if let hir::TyKind::Rptr(
             _,
             hir::MutTy {
-                ty: ref pty,
+                ty: pty,
                 mutbl: hir::Mutability::Mut,
             },
         ) = ty.kind
diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs
index 05457e80d52..cea6fce1195 100644
--- a/clippy_lints/src/mut_reference.rs
+++ b/clippy_lints/src/mut_reference.rs
@@ -33,7 +33,7 @@ declare_lint_pass!(UnnecessaryMutPassed => [UNNECESSARY_MUT_PASSED]);
 impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         match e.kind {
-            ExprKind::Call(ref fn_expr, ref arguments) => {
+            ExprKind::Call(fn_expr, arguments) => {
                 if let ExprKind::Path(ref path) = fn_expr.kind {
                     check_arguments(
                         cx,
@@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                     );
                 }
             },
-            ExprKind::MethodCall(ref path, _, ref arguments, _) => {
+            ExprKind::MethodCall(path, _, arguments, _) => {
                 let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
                 let substs = cx.typeck_results().node_substs(e.hir_id);
                 let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs
index 7dfe12cd4eb..533c5a22db0 100644
--- a/clippy_lints/src/mutable_debug_assertion.rs
+++ b/clippy_lints/src/mutable_debug_assertion.rs
@@ -87,10 +87,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
                 self.found = true;
                 return;
             },
-            ExprKind::If(..) => {
-                self.found = true;
-                return;
-            },
             ExprKind::Path(_) => {
                 if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
                     if adj
diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs
index db7b3423ad9..96a58d1410f 100644
--- a/clippy_lints/src/needless_bool.rs
+++ b/clippy_lints/src/needless_bool.rs
@@ -71,7 +71,7 @@ declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]);
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
-        if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.kind {
+        if let ExprKind::If(pred, then_block, Some(else_expr)) = e.kind {
             let reduce = |ret, not| {
                 let mut applicability = Applicability::MachineApplicable;
                 let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                     snip = snip.make_return();
                 }
 
-                if parent_node_is_if_expr(&e, &cx) {
+                if parent_node_is_if_expr(e, cx) {
                     snip = snip.blockify()
                 }
 
@@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                     applicability,
                 );
             };
-            if let ExprKind::Block(ref then_block, _) = then_block.kind {
+            if let ExprKind::Block(then_block, _) = then_block.kind {
                 match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
                     (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => {
                         span_lint(
@@ -225,7 +225,7 @@ fn check_comparison<'a, 'tcx>(
 ) {
     use self::Expression::{Bool, Other};
 
-    if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind {
+    if let ExprKind::Binary(op, left_side, right_side) = e.kind {
         let (l_ty, r_ty) = (
             cx.typeck_results().expr_ty(left_side),
             cx.typeck_results().expr_ty(right_side),
@@ -237,7 +237,7 @@ fn check_comparison<'a, 'tcx>(
             let mut applicability = Applicability::MachineApplicable;
 
             if let BinOpKind::Eq = op.node {
-                let expression_info = one_side_is_unary_not(&left_side, &right_side);
+                let expression_info = one_side_is_unary_not(left_side, right_side);
                 if expression_info.one_side_is_unary_not {
                     span_lint_and_sugg(
                         cx,
@@ -324,9 +324,9 @@ fn fetch_bool_block(block: &Block<'_>) -> Expression {
     match (&*block.stmts, block.expr.as_ref()) {
         (&[], Some(e)) => fetch_bool_expr(&**e),
         (&[ref e], None) => {
-            if let StmtKind::Semi(ref e) = e.kind {
+            if let StmtKind::Semi(e) = e.kind {
                 if let ExprKind::Ret(_) = e.kind {
-                    fetch_bool_expr(&**e)
+                    fetch_bool_expr(e)
                 } else {
                     Expression::Other
                 }
@@ -340,7 +340,7 @@ fn fetch_bool_block(block: &Block<'_>) -> Expression {
 
 fn fetch_bool_expr(expr: &Expr<'_>) -> Expression {
     match expr.kind {
-        ExprKind::Block(ref block, _) => fetch_bool_block(block),
+        ExprKind::Block(block, _) => fetch_bool_block(block),
         ExprKind::Lit(ref lit_ptr) => {
             if let LitKind::Bool(value) = lit_ptr.node {
                 Expression::Bool(value)
@@ -348,7 +348,7 @@ fn fetch_bool_expr(expr: &Expr<'_>) -> Expression {
                 Expression::Other
             }
         },
-        ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) {
+        ExprKind::Ret(Some(expr)) => match fetch_bool_expr(expr) {
             Expression::Bool(value) => Expression::RetBool(value),
             _ => Expression::Other,
         },
diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs
index 79d84da2dfc..eef3c16730b 100644
--- a/clippy_lints/src/needless_borrow.rs
+++ b/clippy_lints/src/needless_borrow.rs
@@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
         if e.span.from_expansion() || self.derived_item.is_some() {
             return;
         }
-        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = e.kind {
+        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind {
             if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() {
                 for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) {
                     if let [Adjustment {
diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs
index 7fbffe04a3f..0e976b130eb 100644
--- a/clippy_lints/src/needless_borrowed_ref.rs
+++ b/clippy_lints/src/needless_borrowed_ref.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
 
         if_chain! {
             // Only lint immutable refs, because `&mut ref T` may be useful.
-            if let PatKind::Ref(ref sub_pat, Mutability::Not) = pat.kind;
+            if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
 
             // Check sub_pat got a `ref` keyword (excluding `ref mut`).
             if let PatKind::Binding(BindingAnnotation::Ref, .., spanned_name, _) = sub_pat.kind;
diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs
new file mode 100644
index 00000000000..079b6642d58
--- /dev/null
+++ b/clippy_lints/src/needless_for_each.rs
@@ -0,0 +1,167 @@
+use rustc_errors::Applicability;
+use rustc_hir::{
+    intravisit::{walk_expr, NestedVisitorMap, Visitor},
+    Expr, ExprKind, Stmt, StmtKind,
+};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::map::Map;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{source_map::Span, sym, Symbol};
+
+use if_chain::if_chain;
+
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_trait_method;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::has_iter_method;
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for usage of `for_each` that would be more simply written as a
+    /// `for` loop.
+    ///
+    /// **Why is this bad?** `for_each` may be used after applying iterator transformers like
+    /// `filter` for better readability and performance. It may also be used to fit a simple
+    /// operation on one line.
+    /// But when none of these apply, a simple `for` loop is more idiomatic.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// let v = vec![0, 1, 2];
+    /// v.iter().for_each(|elem| {
+    ///     println!("{}", elem);
+    /// })
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let v = vec![0, 1, 2];
+    /// for elem in v.iter() {
+    ///     println!("{}", elem);
+    /// }
+    /// ```
+    pub NEEDLESS_FOR_EACH,
+    pedantic,
+    "using `for_each` where a `for` loop would be simpler"
+}
+
+declare_lint_pass!(NeedlessForEach => [NEEDLESS_FOR_EACH]);
+
+impl LateLintPass<'_> for NeedlessForEach {
+    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
+        let expr = match stmt.kind {
+            StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr,
+            _ => return,
+        };
+
+        if_chain! {
+            // Check the method name is `for_each`.
+            if let ExprKind::MethodCall(method_name, _, [for_each_recv, for_each_arg], _) = expr.kind;
+            if method_name.ident.name == Symbol::intern("for_each");
+            // Check `for_each` is an associated function of `Iterator`.
+            if is_trait_method(cx, expr, sym::Iterator);
+            // Checks the receiver of `for_each` is also a method call.
+            if let ExprKind::MethodCall(_, _, [iter_recv], _) = for_each_recv.kind;
+            // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or
+            // `v.foo().iter().for_each()` must be skipped.
+            if matches!(
+                iter_recv.kind,
+                ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..)
+            );
+            // Checks the type of the `iter` method receiver is NOT a user defined type.
+            if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some();
+            // Skip the lint if the body is not block because this is simpler than `for` loop.
+            // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop.
+            if let ExprKind::Closure(_, _, body_id, ..) = for_each_arg.kind;
+            let body = cx.tcx.hir().body(body_id);
+            if let ExprKind::Block(..) = body.value.kind;
+            then {
+                let mut ret_collector = RetCollector::default();
+                ret_collector.visit_expr(&body.value);
+
+                // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`.
+                if ret_collector.ret_in_loop {
+                    return;
+                }
+
+                let (mut applicability, ret_suggs) = if ret_collector.spans.is_empty() {
+                    (Applicability::MachineApplicable, None)
+                } else {
+                    (
+                        Applicability::MaybeIncorrect,
+                        Some(
+                            ret_collector
+                                .spans
+                                .into_iter()
+                                .map(|span| (span, "continue".to_string()))
+                                .collect(),
+                        ),
+                    )
+                };
+
+                let sugg = format!(
+                    "for {} in {} {}",
+                    snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, body.value.span, "..", &mut applicability),
+                );
+
+                span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| {
+                    diag.span_suggestion(stmt.span, "try", sugg, applicability);
+                    if let Some(ret_suggs) = ret_suggs {
+                        diag.multipart_suggestion("...and replace `return` with `continue`", ret_suggs, applicability);
+                    }
+                })
+            }
+        }
+    }
+}
+
+/// This type plays two roles.
+/// 1. Collect spans of `return` in the closure body.
+/// 2. Detect use of `return` in `Loop` in the closure body.
+///
+/// NOTE: The functionality of this type is similar to
+/// [`crate::utilts::visitors::find_all_ret_expressions`], but we can't use
+/// `find_all_ret_expressions` instead of this type. The reasons are:
+/// 1. `find_all_ret_expressions` passes the argument of `ExprKind::Ret` to a callback, but what we
+///    need here is `ExprKind::Ret` itself.
+/// 2. We can't trace current loop depth with `find_all_ret_expressions`.
+#[derive(Default)]
+struct RetCollector {
+    spans: Vec<Span>,
+    ret_in_loop: bool,
+    loop_depth: u16,
+}
+
+impl<'tcx> Visitor<'tcx> for RetCollector {
+    type Map = Map<'tcx>;
+
+    fn visit_expr(&mut self, expr: &Expr<'_>) {
+        match expr.kind {
+            ExprKind::Ret(..) => {
+                if self.loop_depth > 0 && !self.ret_in_loop {
+                    self.ret_in_loop = true
+                }
+
+                self.spans.push(expr.span)
+            },
+
+            ExprKind::Loop(..) => {
+                self.loop_depth += 1;
+                walk_expr(self, expr);
+                self.loop_depth -= 1;
+                return;
+            },
+
+            _ => {},
+        }
+
+        walk_expr(self, expr);
+    }
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+}
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index e70c248e87b..780e2241293 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -5,10 +5,11 @@ use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
 use clippy_utils::{get_trait_def_id, is_self, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind};
+use rustc_hir::{HirIdMap, HirIdSet};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
@@ -207,7 +208,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                             if is_type_diagnostic_item(cx, ty, sym::vec_type);
                             if let Some(clone_spans) =
                                 get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]);
-                            if let TyKind::Path(QPath::Resolved(_, ref path)) = input.kind;
+                            if let TyKind::Path(QPath::Resolved(_, path)) = input.kind;
                             if let Some(elem_ty) = path.segments.iter()
                                 .find(|seg| seg.ident.name == sym::Vec)
                                 .and_then(|ps| ps.args.as_ref())
@@ -310,10 +311,10 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool {
 
 #[derive(Default)]
 struct MovedVariablesCtxt {
-    moved_vars: FxHashSet<HirId>,
+    moved_vars: HirIdSet,
     /// Spans which need to be prefixed with `*` for dereferencing the
     /// suggested additional reference.
-    spans_need_deref: FxHashMap<HirId, FxHashSet<Span>>,
+    spans_need_deref: HirIdMap<FxHashSet<Span>>,
 }
 
 impl MovedVariablesCtxt {
diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs
index e93de8a252a..8f325404deb 100644
--- a/clippy_lints/src/needless_update.rs
+++ b/clippy_lints/src/needless_update.rs
@@ -49,7 +49,7 @@ declare_lint_pass!(NeedlessUpdate => [NEEDLESS_UPDATE]);
 
 impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.kind {
+        if let ExprKind::Struct(_, fields, Some(base)) = expr.kind {
             let ty = cx.typeck_results().expr_ty(expr);
             if let ty::Adt(def, _) = ty.kind() {
                 if fields.len() == def.non_enum_variant().fields.len()
diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
index 4b935c7b906..0704173a011 100644
--- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
+++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
@@ -51,8 +51,8 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
         if_chain! {
 
             if !in_external_macro(cx.sess(), expr.span);
-            if let ExprKind::Unary(UnOp::Not, ref inner) = expr.kind;
-            if let ExprKind::Binary(ref op, ref left, _) = inner.kind;
+            if let ExprKind::Unary(UnOp::Not, inner) = expr.kind;
+            if let ExprKind::Binary(ref op, left, _) = inner.kind;
             if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node;
 
             then {
diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs
index 7b00879251f..34fd012572f 100644
--- a/clippy_lints/src/neg_multiply.rs
+++ b/clippy_lints/src/neg_multiply.rs
@@ -28,12 +28,12 @@ declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]);
 #[allow(clippy::match_same_arms)]
 impl<'tcx> LateLintPass<'tcx> for NegMultiply {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref op, ref left, ref right) = e.kind {
+        if let ExprKind::Binary(ref op, left, right) = e.kind {
             if BinOpKind::Mul == op.node {
                 match (&left.kind, &right.kind) {
                     (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {},
-                    (&ExprKind::Unary(UnOp::Neg, ref lit), _) => check_mul(cx, e.span, lit, right),
-                    (_, &ExprKind::Unary(UnOp::Neg, ref lit)) => check_mul(cx, e.span, lit, left),
+                    (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right),
+                    (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left),
                     _ => {},
                 }
             }
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index 3789572ad43..a5f91eb035f 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -97,60 +97,60 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                             // impl of `Default`
                             return;
                         }
-                        if sig.decl.inputs.is_empty() && name == sym::new && cx.access_levels.is_reachable(id) {
+                        if_chain! {
+                            if sig.decl.inputs.is_empty();
+                            if name == sym::new;
+                            if cx.access_levels.is_reachable(id);
                             let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id));
                             let self_ty = cx.tcx.type_of(self_def_id);
-                            if_chain! {
-                                if TyS::same_type(self_ty, return_ty(cx, id));
-                                if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
-                                then {
-                                    if self.impling_types.is_none() {
-                                        let mut impls = HirIdSet::default();
-                                        cx.tcx.for_each_impl(default_trait_id, |d| {
-                                            if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
-                                                if let Some(local_def_id) = ty_def.did.as_local() {
-                                                    impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
-                                                }
-                                            }
-                                        });
-                                        self.impling_types = Some(impls);
-                                    }
-
-                                    // Check if a Default implementation exists for the Self type, regardless of
-                                    // generics
-                                    if_chain! {
-                                        if let Some(ref impling_types) = self.impling_types;
-                                        if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def();
-                                        if let Some(self_local_did) = self_def.did.as_local();
-                                        then {
-                                            let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
-                                            if impling_types.contains(&self_id) {
-                                                return;
+                            if TyS::same_type(self_ty, return_ty(cx, id));
+                            if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
+                            then {
+                                if self.impling_types.is_none() {
+                                    let mut impls = HirIdSet::default();
+                                    cx.tcx.for_each_impl(default_trait_id, |d| {
+                                        if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
+                                            if let Some(local_def_id) = ty_def.did.as_local() {
+                                                impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
                                             }
                                         }
-                                    }
+                                    });
+                                    self.impling_types = Some(impls);
+                                }
 
-                                    let generics_sugg = snippet(cx, generics.span, "");
-                                    span_lint_hir_and_then(
-                                        cx,
-                                        NEW_WITHOUT_DEFAULT,
-                                        id,
-                                        impl_item.span,
-                                        &format!(
-                                            "you should consider adding a `Default` implementation for `{}`",
-                                            self_ty
-                                        ),
-                                        |diag| {
-                                            diag.suggest_prepend_item(
-                                                cx,
-                                                item.span,
-                                                "try this",
-                                                &create_new_without_default_suggest_msg(self_ty, &generics_sugg),
-                                                Applicability::MaybeIncorrect,
-                                            );
-                                        },
-                                    );
+                                // Check if a Default implementation exists for the Self type, regardless of
+                                // generics
+                                if_chain! {
+                                    if let Some(ref impling_types) = self.impling_types;
+                                    if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def();
+                                    if let Some(self_local_did) = self_def.did.as_local();
+                                    let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
+                                    if impling_types.contains(&self_id);
+                                    then {
+                                        return;
+                                    }
                                 }
+
+                                let generics_sugg = snippet(cx, generics.span, "");
+                                span_lint_hir_and_then(
+                                    cx,
+                                    NEW_WITHOUT_DEFAULT,
+                                    id,
+                                    impl_item.span,
+                                    &format!(
+                                        "you should consider adding a `Default` implementation for `{}`",
+                                        self_ty
+                                    ),
+                                    |diag| {
+                                        diag.suggest_prepend_item(
+                                            cx,
+                                            item.span,
+                                            "try this",
+                                            &create_new_without_default_suggest_msg(self_ty, &generics_sugg),
+                                            Applicability::MaybeIncorrect,
+                                        );
+                                    },
+                                );
                             }
                         }
                     }
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 83953a16bc8..cfcaf509471 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -51,23 +51,21 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match expr.kind {
         ExprKind::Lit(..) | ExprKind::Closure(..) => true,
         ExprKind::Path(..) => !has_drop(cx, cx.typeck_results().expr_ty(expr)),
-        ExprKind::Index(ref a, ref b) | ExprKind::Binary(_, ref a, ref b) => {
-            has_no_effect(cx, a) && has_no_effect(cx, b)
-        },
-        ExprKind::Array(ref v) | ExprKind::Tup(ref v) => v.iter().all(|val| has_no_effect(cx, val)),
-        ExprKind::Repeat(ref inner, _)
-        | ExprKind::Cast(ref inner, _)
-        | ExprKind::Type(ref inner, _)
-        | ExprKind::Unary(_, ref inner)
-        | ExprKind::Field(ref inner, _)
-        | ExprKind::AddrOf(_, _, ref inner)
-        | ExprKind::Box(ref inner) => has_no_effect(cx, inner),
-        ExprKind::Struct(_, ref fields, ref base) => {
+        ExprKind::Index(a, b) | ExprKind::Binary(_, a, b) => has_no_effect(cx, a) && has_no_effect(cx, b),
+        ExprKind::Array(v) | ExprKind::Tup(v) => v.iter().all(|val| has_no_effect(cx, val)),
+        ExprKind::Repeat(inner, _)
+        | ExprKind::Cast(inner, _)
+        | ExprKind::Type(inner, _)
+        | ExprKind::Unary(_, inner)
+        | ExprKind::Field(inner, _)
+        | ExprKind::AddrOf(_, _, inner)
+        | ExprKind::Box(inner) => has_no_effect(cx, inner),
+        ExprKind::Struct(_, fields, ref base) => {
             !has_drop(cx, cx.typeck_results().expr_ty(expr))
-                && fields.iter().all(|field| has_no_effect(cx, &field.expr))
+                && fields.iter().all(|field| has_no_effect(cx, field.expr))
                 && base.as_ref().map_or(true, |base| has_no_effect(cx, base))
         },
-        ExprKind::Call(ref callee, ref args) => {
+        ExprKind::Call(callee, args) => {
             if let ExprKind::Path(ref qpath) = callee.kind {
                 let res = cx.qpath_res(qpath, callee.hir_id);
                 match res {
@@ -81,7 +79,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
                 false
             }
         },
-        ExprKind::Block(ref block, _) => {
+        ExprKind::Block(block, _) => {
             block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| has_no_effect(cx, expr))
         },
         _ => false,
@@ -92,7 +90,7 @@ declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION]);
 
 impl<'tcx> LateLintPass<'tcx> for NoEffect {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if let StmtKind::Semi(ref expr) = stmt.kind {
+        if let StmtKind::Semi(expr) = stmt.kind {
             if has_no_effect(cx, expr) {
                 span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
             } else if let Some(reduced) = reduce_expression(cx, expr) {
@@ -127,26 +125,26 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
         return None;
     }
     match expr.kind {
-        ExprKind::Index(ref a, ref b) => Some(vec![&**a, &**b]),
-        ExprKind::Binary(ref binop, ref a, ref b) if binop.node != BinOpKind::And && binop.node != BinOpKind::Or => {
-            Some(vec![&**a, &**b])
+        ExprKind::Index(a, b) => Some(vec![a, b]),
+        ExprKind::Binary(ref binop, a, b) if binop.node != BinOpKind::And && binop.node != BinOpKind::Or => {
+            Some(vec![a, b])
         },
-        ExprKind::Array(ref v) | ExprKind::Tup(ref v) => Some(v.iter().collect()),
-        ExprKind::Repeat(ref inner, _)
-        | ExprKind::Cast(ref inner, _)
-        | ExprKind::Type(ref inner, _)
-        | ExprKind::Unary(_, ref inner)
-        | ExprKind::Field(ref inner, _)
-        | ExprKind::AddrOf(_, _, ref inner)
-        | ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
-        ExprKind::Struct(_, ref fields, ref base) => {
+        ExprKind::Array(v) | ExprKind::Tup(v) => Some(v.iter().collect()),
+        ExprKind::Repeat(inner, _)
+        | ExprKind::Cast(inner, _)
+        | ExprKind::Type(inner, _)
+        | ExprKind::Unary(_, inner)
+        | ExprKind::Field(inner, _)
+        | ExprKind::AddrOf(_, _, inner)
+        | ExprKind::Box(inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
+        ExprKind::Struct(_, fields, ref base) => {
             if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
                 None
             } else {
                 Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
             }
         },
-        ExprKind::Call(ref callee, ref args) => {
+        ExprKind::Call(callee, args) => {
             if let ExprKind::Path(ref qpath) = callee.kind {
                 let res = cx.qpath_res(qpath, callee.hir_id);
                 match res {
@@ -161,7 +159,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
                 None
             }
         },
-        ExprKind::Block(ref block, _) => {
+        ExprKind::Block(block, _) => {
             if block.stmts.is_empty() {
                 block.expr.as_ref().and_then(|e| {
                     match block.rules {
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index aa1d8fbe300..d775cd7c7f7 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -307,19 +307,17 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                             // we should use here as a frozen variant is a potential to be frozen
                             // similar to unknown layouts.
                             // e.g. `layout_of(...).is_err() || has_frozen_variant(...);`
+                        let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+                        let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
+                        if is_unfrozen(cx, normalized);
+                        if is_value_unfrozen_poly(cx, *body_id, normalized);
                         then {
-                            let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-                            let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-                            if is_unfrozen(cx, normalized)
-                                && is_value_unfrozen_poly(cx, *body_id, normalized)
-                            {
-                                lint(
-                                   cx,
-                                   Source::Assoc {
-                                       item: impl_item.span,
-                                    },
-                                );
-                            }
+                            lint(
+                               cx,
+                               Source::Assoc {
+                                   item: impl_item.span,
+                                },
+                            );
                         }
                     }
                 },
diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs
index 4c8bceaf2cb..52661416de6 100644
--- a/clippy_lints/src/non_expressive_names.rs
+++ b/clippy_lints/src/non_expressive_names.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use rustc_ast::ast::{
-    Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat,
-    PatKind,
+    Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind,
 };
 use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs
new file mode 100644
index 00000000000..a83daea97bf
--- /dev/null
+++ b/clippy_lints/src/non_octal_unix_permissions.rs
@@ -0,0 +1,106 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{snippet_opt, snippet_with_applicability};
+use clippy_utils::ty::match_type;
+use clippy_utils::{match_def_path, paths};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for non-octal values used to set Unix file permissions.
+    ///
+    /// **Why is this bad?** They will be converted into octal, creating potentially
+    /// unintended file permissions.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust,ignore
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.mode(644);
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.mode(0o644);
+    /// ```
+    pub NON_OCTAL_UNIX_PERMISSIONS,
+    correctness,
+    "use of non-octal value to set unix file permissions, which will be translated into octal"
+}
+
+declare_lint_pass!(NonOctalUnixPermissions => [NON_OCTAL_UNIX_PERMISSIONS]);
+
+impl LateLintPass<'_> for NonOctalUnixPermissions {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        match &expr.kind {
+            ExprKind::MethodCall(path, _, [func, param], _) => {
+                let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
+
+                if_chain! {
+                    if (path.ident.name == sym!(mode)
+                        && (match_type(cx, obj_ty, &paths::OPEN_OPTIONS)
+                            || match_type(cx, obj_ty, &paths::DIR_BUILDER)))
+                        || (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS));
+                    if let ExprKind::Lit(_) = param.kind;
+
+                    then {
+                        let snip = match snippet_opt(cx, param.span) {
+                            Some(s) => s,
+                            _ => return,
+                        };
+
+                        if !snip.starts_with("0o") {
+                            show_error(cx, param);
+                        }
+                    }
+                }
+            },
+            ExprKind::Call(func, [param]) => {
+                if_chain! {
+                    if let ExprKind::Path(ref path) = func.kind;
+                    if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
+                    if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
+                    if let ExprKind::Lit(_) = param.kind;
+
+                    then {
+                        let snip = match snippet_opt(cx, param.span) {
+                            Some(s) => s,
+                            _ => return,
+                        };
+
+                        if !snip.starts_with("0o") {
+                            show_error(cx, param);
+                        }
+                    }
+                }
+            },
+            _ => {},
+        };
+    }
+}
+
+fn show_error(cx: &LateContext<'_>, param: &Expr<'_>) {
+    let mut applicability = Applicability::MachineApplicable;
+    span_lint_and_sugg(
+        cx,
+        NON_OCTAL_UNIX_PERMISSIONS,
+        param.span,
+        "using a non-octal value to set unix file permissions",
+        "consider using an octal literal instead",
+        format!(
+            "0o{}",
+            snippet_with_applicability(cx, param.span, "0o..", &mut applicability,),
+        ),
+        applicability,
+    );
+}
diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs
index c61dff4b8e0..9efe45336bf 100644
--- a/clippy_lints/src/open_options.rs
+++ b/clippy_lints/src/open_options.rs
@@ -31,7 +31,7 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for OpenOptions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::MethodCall(ref path, _, ref arguments, _) = e.kind {
+        if let ExprKind::MethodCall(path, _, arguments, _) = e.kind {
             let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs();
             if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
                 let mut options = Vec::new();
@@ -59,7 +59,7 @@ enum OpenOption {
 }
 
 fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
-    if let ExprKind::MethodCall(ref path, _, ref arguments, _) = argument.kind {
+    if let ExprKind::MethodCall(path, _, arguments, _) = argument.kind {
         let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs();
 
         // Only proceed if this is a call on some object of type std::fs::OpenOptions
diff --git a/clippy_lints/src/option_env_unwrap.rs b/clippy_lints/src/option_env_unwrap.rs
index a0bc324e026..b6f518661bd 100644
--- a/clippy_lints/src/option_env_unwrap.rs
+++ b/clippy_lints/src/option_env_unwrap.rs
@@ -4,6 +4,7 @@ use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for usage of `option_env!(...).unwrap()` and
@@ -37,8 +38,7 @@ impl EarlyLintPass for OptionEnvUnwrap {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
         if_chain! {
             if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind;
-            let method_name = path_segment.ident.as_str();
-            if method_name == "expect" || method_name == "unwrap";
+            if matches!(path_segment.ident.name, sym::expect | sym::unwrap);
             if let ExprKind::Call(caller, _) = &args[0].kind;
             if is_direct_expn_of(caller.span, "option_env").is_some();
             then {
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index a76a4a33f1f..1b9120ae45f 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -66,9 +66,9 @@ declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);
 
 /// Returns true iff the given expression is the result of calling `Result::ok`
 fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
-    if let ExprKind::MethodCall(ref path, _, &[ref receiver], _) = &expr.kind {
+    if let ExprKind::MethodCall(path, _, &[ref receiver], _) = &expr.kind {
         path.ident.name.as_str() == "ok"
-            && is_type_diagnostic_item(cx, &cx.typeck_results().expr_ty(&receiver), sym::result_type)
+            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::result_type)
     } else {
         false
     }
@@ -97,9 +97,9 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
     ) = &arm.body.kind
     {
         if let [] = statements {
-            Some(&expr)
+            Some(expr)
         } else {
-            Some(&arm.body)
+            Some(arm.body)
         }
     } else {
         None
diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs
index cf667c6e805..e222782c2cc 100644
--- a/clippy_lints/src/overflow_check_conditional.rs
+++ b/clippy_lints/src/overflow_check_conditional.rs
@@ -31,11 +31,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r);
         if_chain! {
-            if let ExprKind::Binary(ref op, ref first, ref second) = expr.kind;
-            if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = first.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path3)) = second.kind;
+            if let ExprKind::Binary(ref op, first, second) = expr.kind;
+            if let ExprKind::Binary(ref op2, ident1, ident2) = first.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path3)) = second.kind;
             if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
             if cx.typeck_results().expr_ty(ident1).is_integral();
             if cx.typeck_results().expr_ty(ident2).is_integral();
@@ -56,11 +56,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
         }
 
         if_chain! {
-            if let ExprKind::Binary(ref op, ref first, ref second) = expr.kind;
-            if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = second.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref path3)) = first.kind;
+            if let ExprKind::Binary(ref op, first, second) = expr.kind;
+            if let ExprKind::Binary(ref op2, ident1, ident2) = second.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path3)) = first.kind;
             if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
             if cx.typeck_results().expr_ty(ident1).is_integral();
             if cx.typeck_results().expr_ty(ident2).is_integral();
diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs
index d06e7f8fe1e..1e946858947 100644
--- a/clippy_lints/src/panic_unimplemented.rs
+++ b/clippy_lints/src/panic_unimplemented.rs
@@ -97,11 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
 fn get_outer_span(expr: &Expr<'_>) -> Span {
     if_chain! {
         if expr.span.from_expansion();
-        let first = expr.span.ctxt().outer_expn_data();
-        if first.call_site.from_expansion();
-        let second = first.call_site.ctxt().outer_expn_data();
+        let first = expr.span.ctxt().outer_expn_data().call_site;
+        if first.from_expansion();
         then {
-            second.call_site
+            first.ctxt().outer_expn_data().call_site
         } else {
             expr.span
         }
diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index e151f85a391..6f80e447c7d 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/clippy_lints/src/pass_by_ref_or_value.rs
@@ -142,11 +142,11 @@ impl<'tcx> PassByRefOrValue {
                     };
 
                     if_chain! {
-                        if !output_lts.contains(&input_lt);
+                        if !output_lts.contains(input_lt);
                         if is_copy(cx, ty);
                         if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
                         if size <= self.ref_min_size;
-                        if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.kind;
+                        if let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind;
                         then {
                             let value_type = if is_self_ty(decl_ty) {
                                 "self".into()
diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs
index 95ffae28d8c..00245926381 100644
--- a/clippy_lints/src/path_buf_push_overwrite.rs
+++ b/clippy_lints/src/path_buf_push_overwrite.rs
@@ -45,7 +45,7 @@ declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]);
 impl<'tcx> LateLintPass<'tcx> for PathBufPushOverwrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
             if path.ident.name == sym!(push);
             if args.len() == 2;
             if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::PathBuf);
diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs
index c0c2ab67e38..9bab783998a 100644
--- a/clippy_lints/src/pattern_type_mismatch.rs
+++ b/clippy_lints/src/pattern_type_mismatch.rs
@@ -87,7 +87,7 @@ declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]);
 
 impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if let StmtKind::Local(ref local) = stmt.kind {
+        if let StmtKind::Local(local) = stmt.kind {
             if let Some(init) = &local.init {
                 if let Some(init_ty) = cx.typeck_results().node_type_opt(init.hir_id) {
                     let pat = &local.pat;
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Match(ref expr, arms, source) = expr.kind {
+        if let ExprKind::Match(expr, arms, source) = expr.kind {
             match source {
                 MatchSource::Normal | MatchSource::IfLetDesugar { .. } | MatchSource::WhileLetDesugar => {
                     if let Some(expr_ty) = cx.typeck_results().node_type_opt(expr.hir_id) {
@@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
     ) {
         if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) {
             for (param, ty) in iter::zip(body.params, fn_sig.inputs()) {
-                apply_lint(cx, &param.pat, ty, DerefPossible::Impossible);
+                apply_lint(cx, param.pat, ty, DerefPossible::Impossible);
             }
         }
     }
@@ -188,7 +188,7 @@ fn find_first_mismatch<'tcx>(
     ty: Ty<'tcx>,
     level: Level,
 ) -> Option<(Span, Mutability, Level)> {
-    if let PatKind::Ref(ref sub_pat, _) = pat.kind {
+    if let PatKind::Ref(sub_pat, _) = pat.kind {
         if let TyKind::Ref(_, sub_ty, _) = ty.kind() {
             return find_first_mismatch(cx, sub_pat, sub_ty, Level::Lower);
         }
@@ -200,8 +200,8 @@ fn find_first_mismatch<'tcx>(
         }
     }
 
-    if let PatKind::Struct(ref qpath, ref field_pats, _) = pat.kind {
-        if let TyKind::Adt(ref adt_def, ref substs_ref) = ty.kind() {
+    if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind {
+        if let TyKind::Adt(adt_def, substs_ref) = ty.kind() {
             if let Some(variant) = get_variant(adt_def, qpath) {
                 let field_defs = &variant.fields;
                 return find_first_mismatch_in_struct(cx, field_pats, field_defs, substs_ref);
@@ -209,8 +209,8 @@ fn find_first_mismatch<'tcx>(
         }
     }
 
-    if let PatKind::TupleStruct(ref qpath, ref pats, _) = pat.kind {
-        if let TyKind::Adt(ref adt_def, ref substs_ref) = ty.kind() {
+    if let PatKind::TupleStruct(ref qpath, pats, _) = pat.kind {
+        if let TyKind::Adt(adt_def, substs_ref) = ty.kind() {
             if let Some(variant) = get_variant(adt_def, qpath) {
                 let field_defs = &variant.fields;
                 let ty_iter = field_defs.iter().map(|field_def| field_def.ty(cx.tcx, substs_ref));
@@ -219,7 +219,7 @@ fn find_first_mismatch<'tcx>(
         }
     }
 
-    if let PatKind::Tuple(ref pats, _) = pat.kind {
+    if let PatKind::Tuple(pats, _) = pat.kind {
         if let TyKind::Tuple(..) = ty.kind() {
             return find_first_mismatch_in_tuple(cx, pats, ty.tuple_fields());
         }
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index be686b1b0cd..09fcdb5faf8 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -124,7 +124,7 @@ declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]);
 impl<'tcx> LateLintPass<'tcx> for Ptr {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if let ItemKind::Fn(ref sig, _, body_id) = item.kind {
-            check_fn(cx, &sig.decl, item.hir_id(), Some(body_id));
+            check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
         }
     }
 
@@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
                     return; // ignore trait impls
                 }
             }
-            check_fn(cx, &sig.decl, item.hir_id(), Some(body_id));
+            check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
         }
     }
 
@@ -147,12 +147,12 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
             } else {
                 None
             };
-            check_fn(cx, &sig.decl, item.hir_id(), body_id);
+            check_fn(cx, sig.decl, item.hir_id(), body_id);
         }
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind {
+        if let ExprKind::Binary(ref op, l, r) = expr.kind {
             if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) {
                 span_lint(
                     cx,
@@ -262,35 +262,34 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                 }
             } else if match_type(cx, ty, &paths::COW) {
                 if_chain! {
-                    if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind;
-                    if let TyKind::Path(QPath::Resolved(None, ref pp)) = ty.kind;
+                    if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind;
+                    if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind;
                     if let [ref bx] = *pp.segments;
-                    if let Some(ref params) = bx.args;
+                    if let Some(params) = bx.args;
                     if !params.parenthesized;
                     if let Some(inner) = params.args.iter().find_map(|arg| match arg {
                         GenericArg::Type(ty) => Some(ty),
                         _ => None,
                     });
+                    let replacement = snippet_opt(cx, inner.span);
+                    if let Some(r) = replacement;
                     then {
-                        let replacement = snippet_opt(cx, inner.span);
-                        if let Some(r) = replacement {
-                            span_lint_and_sugg(
-                                cx,
-                                PTR_ARG,
-                                arg.span,
-                                "using a reference to `Cow` is not recommended",
-                                "change this to",
-                                "&".to_owned() + &r,
-                                Applicability::Unspecified,
-                            );
-                        }
+                        span_lint_and_sugg(
+                            cx,
+                            PTR_ARG,
+                            arg.span,
+                            "using a reference to `Cow` is not recommended",
+                            "change this to",
+                            "&".to_owned() + &r,
+                            Applicability::Unspecified,
+                        );
                     }
                 }
             }
         }
     }
 
-    if let FnRetTy::Return(ref ty) = decl.output {
+    if let FnRetTy::Return(ty) = decl.output {
         if let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) {
             let mut immutables = vec![];
             for (_, ref mutbl, ref argspan) in decl
@@ -323,8 +322,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
 
 fn get_only_generic_arg_snippet(cx: &LateContext<'_>, arg: &Ty<'_>) -> Option<String> {
     if_chain! {
-        if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
-        if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
+        if let TyKind::Path(QPath::Resolved(_, path)) = walk_ptrs_hir_ty(arg).kind;
+        if let Some(&PathSegment{args: Some(parameters), ..}) = path.segments.last();
         let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
             GenericArg::Type(ty) => Some(ty),
             _ => None,
@@ -347,7 +346,7 @@ fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability,
 }
 
 fn is_null_path(expr: &Expr<'_>) -> bool {
-    if let ExprKind::Call(ref pathexp, ref args) = expr.kind {
+    if let ExprKind::Call(pathexp, args) = expr.kind {
         if args.is_empty() {
             if let ExprKind::Path(ref path) = pathexp.kind {
                 return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT);
diff --git a/clippy_lints/src/ptr_eq.rs b/clippy_lints/src/ptr_eq.rs
index 5796c59c8b3..77cfa3f6b17 100644
--- a/clippy_lints/src/ptr_eq.rs
+++ b/clippy_lints/src/ptr_eq.rs
@@ -46,11 +46,11 @@ impl LateLintPass<'_> for PtrEq {
             return;
         }
 
-        if let ExprKind::Binary(ref op, ref left, ref right) = expr.kind {
+        if let ExprKind::Binary(ref op, left, right) = expr.kind {
             if BinOpKind::Eq == op.node {
                 let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
                     (Some(lhs), Some(rhs)) => (lhs, rhs),
-                    _ => (&**left, &**right),
+                    _ => (left, right),
                 };
 
                 if_chain! {
@@ -79,7 +79,7 @@ impl LateLintPass<'_> for PtrEq {
 // E.g., `foo as *const _ as usize` returns `foo as *const _`.
 fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize {
-        if let ExprKind::Cast(ref expr, _) = cast_expr.kind {
+        if let ExprKind::Cast(expr, _) = cast_expr.kind {
             return Some(expr);
         }
     }
@@ -90,7 +90,7 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
 // E.g., `foo as *const _` returns `foo`.
 fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() {
-        if let ExprKind::Cast(ref expr, _) = cast_expr.kind {
+        if let ExprKind::Cast(expr, _) = cast_expr.kind {
             return Some(expr);
         }
     }
diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs
index c04b4255256..afb198f4955 100644
--- a/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/clippy_lints/src/ptr_offset_with_cast.rs
@@ -78,8 +78,8 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast {
 
 // If the given expression is a cast from a usize, return the lhs of the cast
 fn expr_as_cast_from_usize<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    if let ExprKind::Cast(ref cast_lhs_expr, _) = expr.kind {
-        if is_expr_ty_usize(cx, &cast_lhs_expr) {
+    if let ExprKind::Cast(cast_lhs_expr, _) = expr.kind {
+        if is_expr_ty_usize(cx, cast_lhs_expr) {
             return Some(cast_lhs_expr);
         }
     }
@@ -92,7 +92,7 @@ fn expr_as_ptr_offset_call<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
-    if let ExprKind::MethodCall(ref path_segment, _, ref args, _) = expr.kind {
+    if let ExprKind::MethodCall(path_segment, _, args, _) = expr.kind {
         if is_expr_ty_raw_ptr(cx, &args[0]) {
             if path_segment.ident.name == sym::offset {
                 return Some((&args[0], &args[1], Method::Offset));
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index 2054255a7c9..6d720f43851 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -148,14 +148,14 @@ impl QuestionMark {
 
     fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
         match expression.kind {
-            ExprKind::Block(ref block, _) => {
+            ExprKind::Block(block, _) => {
                 if let Some(return_expression) = Self::return_expression(block) {
-                    return Self::expression_returns_none(cx, &return_expression);
+                    return Self::expression_returns_none(cx, return_expression);
                 }
 
                 false
             },
-            ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
+            ExprKind::Ret(Some(expr)) => Self::expression_returns_none(cx, expr),
             ExprKind::Path(ref qp) => {
                 if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
                     cx.qpath_res(qp, expression.hir_id)
@@ -174,7 +174,7 @@ impl QuestionMark {
         if_chain! {
             if block.stmts.len() == 1;
             if let Some(expr) = block.stmts.iter().last();
-            if let StmtKind::Semi(ref expr) = expr.kind;
+            if let StmtKind::Semi(expr) = expr.kind;
             if let ExprKind::Ret(Some(ret_expr)) = expr.kind;
 
             then {
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 95b21489eb5..1c3c125e579 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -183,10 +183,10 @@ impl_lint_pass!(Ranges => [
 impl<'tcx> LateLintPass<'tcx> for Ranges {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         match expr.kind {
-            ExprKind::MethodCall(ref path, _, ref args, _) => {
+            ExprKind::MethodCall(path, _, args, _) => {
                 check_range_zip_with_len(cx, path, args, expr.span);
             },
-            ExprKind::Binary(ref op, ref l, ref r) => {
+            ExprKind::Binary(ref op, l, r) => {
                 if meets_msrv(self.msrv.as_ref(), &MANUAL_RANGE_CONTAINS_MSRV) {
                     check_possible_range_contains(cx, op.node, l, r, expr);
                 }
@@ -287,7 +287,7 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
 }
 
 fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant, Ident, Span, Span, Ordering, bool)> {
-    if let ExprKind::Binary(ref op, ref l, ref r) = ex.kind {
+    if let ExprKind::Binary(ref op, l, r) = ex.kind {
         let (inclusive, ordering) = match op.node {
             BinOpKind::Gt => (false, Ordering::Greater),
             BinOpKind::Ge => (true, Ordering::Greater),
@@ -320,32 +320,29 @@ fn match_ident(e: &Expr<'_>) -> Option<Ident> {
 }
 
 fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args: &[Expr<'_>], span: Span) {
-    let name = path.ident.as_str();
-    if name == "zip" && args.len() == 2 {
-        let iter = &args[0].kind;
-        let zip_arg = &args[1];
-        if_chain! {
-            // `.iter()` call
-            if let ExprKind::MethodCall(ref iter_path, _, ref iter_args, _) = *iter;
-            if iter_path.ident.name == sym::iter;
-            // range expression in `.zip()` call: `0..x.len()`
-            if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg);
-            if is_integer_const(cx, start, 0);
-            // `.len()` call
-            if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind;
-            if len_path.ident.name == sym!(len) && len_args.len() == 1;
-            // `.iter()` and `.len()` called on same `Path`
-            if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;
-            if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].kind;
-            if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
-            then {
-                span_lint(cx,
-                    RANGE_ZIP_WITH_LEN,
-                    span,
-                    &format!("it is more idiomatic to use `{}.iter().enumerate()`",
-                        snippet(cx, iter_args[0].span, "_"))
-                );
-            }
+    if_chain! {
+        if path.ident.as_str() == "zip";
+        if let [iter, zip_arg] = args;
+        // `.iter()` call
+        if let ExprKind::MethodCall(iter_path, _, iter_args, _) = iter.kind;
+        if iter_path.ident.name == sym::iter;
+        // range expression in `.zip()` call: `0..x.len()`
+        if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg);
+        if is_integer_const(cx, start, 0);
+        // `.len()` call
+        if let ExprKind::MethodCall(len_path, _, len_args, _) = end.kind;
+        if len_path.ident.name == sym!(len) && len_args.len() == 1;
+        // `.iter()` and `.len()` called on same `Path`
+        if let ExprKind::Path(QPath::Resolved(_, iter_path)) = iter_args[0].kind;
+        if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_args[0].kind;
+        if SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments);
+        then {
+            span_lint(cx,
+                RANGE_ZIP_WITH_LEN,
+                span,
+                &format!("it is more idiomatic to use `{}.iter().enumerate()`",
+                    snippet(cx, iter_args[0].span, "_"))
+            );
         }
     }
 }
@@ -511,8 +508,8 @@ fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'
             Spanned {
                 node: BinOpKind::Add, ..
             },
-            ref lhs,
-            ref rhs,
+            lhs,
+            rhs,
         ) => {
             if is_integer_const(cx, lhs, 1) {
                 Some(rhs)
@@ -532,8 +529,8 @@ fn y_minus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<
             Spanned {
                 node: BinOpKind::Sub, ..
             },
-            ref lhs,
-            ref rhs,
+            lhs,
+            rhs,
         ) if is_integer_const(cx, rhs, 1) => Some(lhs),
         _ => None,
     }
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index 3abe619207e..19650c41b84 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
             .into_results_cursor(mir);
         let mut possible_borrower = {
             let mut vis = PossibleBorrowerVisitor::new(cx, mir);
-            vis.visit_body(&mir);
+            vis.visit_body(mir);
             vis.into_map(cx, maybe_storage_live_result)
         };
 
@@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 continue;
             }
 
-            if let ty::Adt(ref def, _) = arg_ty.kind() {
+            if let ty::Adt(def, _) = arg_ty.kind() {
                 if match_def_path(cx, def.did, &paths::MEM_MANUALLY_DROP) {
                     continue;
                 }
@@ -199,79 +199,72 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 (local, deref_clone_ret)
             };
 
-            let is_temp = mir.local_kind(ret_local) == mir::LocalKind::Temp;
-
-            // 1. `local` can be moved out if it is not used later.
-            // 2. If `ret_local` is a temporary and is neither consumed nor mutated, we can remove this `clone`
-            // call anyway.
-            let (used, consumed_or_mutated) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold(
-                (false, !is_temp),
-                |(used, consumed), (tbb, tdata)| {
-                    // Short-circuit
-                    if (used && consumed) ||
-                        // Give up on loops
-                        tdata.terminator().successors().any(|s| *s == bb)
-                    {
-                        return (true, true);
+            let clone_usage = if local == ret_local {
+                CloneUsage {
+                    cloned_used: false,
+                    cloned_consume_or_mutate_loc: None,
+                    clone_consumed_or_mutated: true,
+                }
+            } else {
+                let clone_usage = visit_clone_usage(local, ret_local, mir, bb);
+                if clone_usage.cloned_used && clone_usage.clone_consumed_or_mutated {
+                    // cloned value is used, and the clone is modified or moved
+                    continue;
+                } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc {
+                    // cloned value is mutated, and the clone is alive.
+                    if possible_borrower.is_alive_at(ret_local, loc) {
+                        continue;
                     }
+                }
+                clone_usage
+            };
 
-                    let mut vis = LocalUseVisitor {
-                        used: (local, false),
-                        consumed_or_mutated: (ret_local, false),
-                    };
-                    vis.visit_basic_block_data(tbb, tdata);
-                    (used || vis.used.1, consumed || vis.consumed_or_mutated.1)
-                },
-            );
-
-            if !used || !consumed_or_mutated {
-                let span = terminator.source_info.span;
-                let scope = terminator.source_info.scope;
-                let node = mir.source_scopes[scope]
-                    .local_data
-                    .as_ref()
-                    .assert_crate_local()
-                    .lint_root;
-
-                if_chain! {
-                    if let Some(snip) = snippet_opt(cx, span);
-                    if let Some(dot) = snip.rfind('.');
-                    then {
-                        let sugg_span = span.with_lo(
-                            span.lo() + BytePos(u32::try_from(dot).unwrap())
-                        );
-                        let mut app = Applicability::MaybeIncorrect;
-
-                        let call_snip = &snip[dot + 1..];
-                        // Machine applicable when `call_snip` looks like `foobar()`
-                        if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) {
-                            if call_snip.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') {
-                                app = Applicability::MachineApplicable;
-                            }
+            let span = terminator.source_info.span;
+            let scope = terminator.source_info.scope;
+            let node = mir.source_scopes[scope]
+                .local_data
+                .as_ref()
+                .assert_crate_local()
+                .lint_root;
+
+            if_chain! {
+                if let Some(snip) = snippet_opt(cx, span);
+                if let Some(dot) = snip.rfind('.');
+                then {
+                    let sugg_span = span.with_lo(
+                        span.lo() + BytePos(u32::try_from(dot).unwrap())
+                    );
+                    let mut app = Applicability::MaybeIncorrect;
+
+                    let call_snip = &snip[dot + 1..];
+                    // Machine applicable when `call_snip` looks like `foobar()`
+                    if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) {
+                        if call_snip.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') {
+                            app = Applicability::MachineApplicable;
                         }
+                    }
 
-                        span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| {
-                            diag.span_suggestion(
-                                sugg_span,
-                                "remove this",
-                                String::new(),
-                                app,
+                    span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| {
+                        diag.span_suggestion(
+                            sugg_span,
+                            "remove this",
+                            String::new(),
+                            app,
+                        );
+                        if clone_usage.cloned_used {
+                            diag.span_note(
+                                span,
+                                "cloned value is neither consumed nor mutated",
                             );
-                            if used {
-                                diag.span_note(
-                                    span,
-                                    "cloned value is neither consumed nor mutated",
-                                );
-                            } else {
-                                diag.span_note(
-                                    span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
-                                    "this value is dropped without further use",
-                                );
-                            }
-                        });
-                    } else {
-                        span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
-                    }
+                        } else {
+                            diag.span_note(
+                                span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
+                                "this value is dropped without further use",
+                            );
+                        }
+                    });
+                } else {
+                    span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
                 }
             }
         }
@@ -365,49 +358,97 @@ fn base_local_and_movability<'tcx>(
     (local, deref || field || slice)
 }
 
-struct LocalUseVisitor {
-    used: (mir::Local, bool),
-    consumed_or_mutated: (mir::Local, bool),
+#[derive(Default)]
+struct CloneUsage {
+    /// Whether the cloned value is used after the clone.
+    cloned_used: bool,
+    /// The first location where the cloned value is consumed or mutated, if any.
+    cloned_consume_or_mutate_loc: Option<mir::Location>,
+    /// Whether the clone value is mutated.
+    clone_consumed_or_mutated: bool,
 }
-
-impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
-    fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) {
-        let statements = &data.statements;
-        for (statement_index, statement) in statements.iter().enumerate() {
-            self.visit_statement(statement, mir::Location { block, statement_index });
-        }
-
-        self.visit_terminator(
-            data.terminator(),
-            mir::Location {
-                block,
-                statement_index: statements.len(),
-            },
-        );
+fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage {
+    struct V {
+        cloned: mir::Local,
+        clone: mir::Local,
+        result: CloneUsage,
     }
+    impl<'tcx> mir::visit::Visitor<'tcx> for V {
+        fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) {
+            let statements = &data.statements;
+            for (statement_index, statement) in statements.iter().enumerate() {
+                self.visit_statement(statement, mir::Location { block, statement_index });
+            }
 
-    fn visit_place(&mut self, place: &mir::Place<'tcx>, ctx: PlaceContext, _: mir::Location) {
-        let local = place.local;
-
-        if local == self.used.0
-            && !matches!(
-                ctx,
-                PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)
-            )
-        {
-            self.used.1 = true;
+            self.visit_terminator(
+                data.terminator(),
+                mir::Location {
+                    block,
+                    statement_index: statements.len(),
+                },
+            );
         }
 
-        if local == self.consumed_or_mutated.0 {
-            match ctx {
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
-                | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
-                    self.consumed_or_mutated.1 = true;
-                },
-                _ => {},
+        fn visit_place(&mut self, place: &mir::Place<'tcx>, ctx: PlaceContext, loc: mir::Location) {
+            let local = place.local;
+
+            if local == self.cloned
+                && !matches!(
+                    ctx,
+                    PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)
+                )
+            {
+                self.result.cloned_used = true;
+                self.result.cloned_consume_or_mutate_loc = self.result.cloned_consume_or_mutate_loc.or_else(|| {
+                    matches!(
+                        ctx,
+                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
+                            | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
+                    )
+                    .then(|| loc)
+                });
+            } else if local == self.clone {
+                match ctx {
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
+                    | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
+                        self.result.clone_consumed_or_mutated = true;
+                    },
+                    _ => {},
+                }
             }
         }
     }
+
+    let init = CloneUsage {
+        cloned_used: false,
+        cloned_consume_or_mutate_loc: None,
+        // Consider non-temporary clones consumed.
+        // TODO: Actually check for mutation of non-temporaries.
+        clone_consumed_or_mutated: mir.local_kind(clone) != mir::LocalKind::Temp,
+    };
+    traversal::ReversePostorder::new(mir, bb)
+        .skip(1)
+        .fold(init, |usage, (tbb, tdata)| {
+            // Short-circuit
+            if (usage.cloned_used && usage.clone_consumed_or_mutated) ||
+                // Give up on loops
+                tdata.terminator().successors().any(|s| *s == bb)
+            {
+                return CloneUsage {
+                    cloned_used: true,
+                    clone_consumed_or_mutated: true,
+                    ..usage
+                };
+            }
+
+            let mut v = V {
+                cloned,
+                clone,
+                result: usage,
+            };
+            v.visit_basic_block_data(tbb, tdata);
+            v.result
+        })
 }
 
 /// Determines liveness of each local purely based on `StorageLive`/`Dead`.
@@ -547,7 +588,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
             // If the call returns something with lifetimes,
             // let's conservatively assume the returned value contains lifetime of all the arguments.
             // For example, given `let y: Foo<'a> = foo(x)`, `y` is considered to be a possible borrower of `x`.
-            if ContainsRegion.visit_ty(&self.body.local_decls[*dest].ty).is_continue() {
+            if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_continue() {
                 return;
             }
 
@@ -587,7 +628,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
         BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
             visit_op(lhs);
             visit_op(rhs);
-        }
+        },
         _ => (),
     }
 }
@@ -623,4 +664,9 @@ impl PossibleBorrowerMap<'_, '_> {
 
         self.bitset.0 == self.bitset.1
     }
+
+    fn is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool {
+        self.maybe_live.seek_after_primary_effect(at);
+        self.maybe_live.contains(local)
+    }
 }
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index 2977a108d14..92921bedf4d 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/clippy_lints/src/redundant_closure_call.rs
@@ -111,10 +111,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
 
                 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                     if_chain! {
-                        if let hir::ExprKind::Call(ref closure, _) = expr.kind;
-                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
-                        if self.path.segments[0].ident == path.segments[0].ident
-                            && self.path.res == path.res;
+                        if let hir::ExprKind::Call(closure, _) = expr.kind;
+                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind;
+                        if self.path.segments[0].ident == path.segments[0].ident;
+                        if self.path.res == path.res;
                         then {
                             self.count += 1;
                         }
@@ -133,14 +133,14 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
 
         for w in block.stmts.windows(2) {
             if_chain! {
-                if let hir::StmtKind::Local(ref local) = w[0].kind;
-                if let Option::Some(ref t) = local.init;
+                if let hir::StmtKind::Local(local) = w[0].kind;
+                if let Option::Some(t) = local.init;
                 if let hir::ExprKind::Closure(..) = t.kind;
                 if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
-                if let hir::StmtKind::Semi(ref second) = w[1].kind;
-                if let hir::ExprKind::Assign(_, ref call, _) = second.kind;
-                if let hir::ExprKind::Call(ref closure, _) = call.kind;
-                if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
+                if let hir::StmtKind::Semi(second) = w[1].kind;
+                if let hir::ExprKind::Assign(_, call, _) = second.kind;
+                if let hir::ExprKind::Call(closure, _) = call.kind;
+                if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind;
                 if ident == path.segments[0].ident;
                 if count_closure_usage(cx, block, path) == 1;
                 then {
diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs
index 6da7b5fbcc8..9c6cd7b4fa6 100644
--- a/clippy_lints/src/redundant_slicing.rs
+++ b/clippy_lints/src/redundant_slicing.rs
@@ -1,11 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{get_parent_expr, in_macro};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, LangItem};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::{lint::in_external_macro, ty::TyS};
+use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyS;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -40,26 +41,44 @@ declare_lint_pass!(RedundantSlicing => [REDUNDANT_SLICING]);
 
 impl LateLintPass<'_> for RedundantSlicing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_macro(expr.span) {
             return;
         }
 
+        let ctxt = expr.span.ctxt();
         if_chain! {
-            if let ExprKind::AddrOf(_, _, addressee) = expr.kind;
+            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
+            if addressee.span.ctxt() == ctxt;
             if let ExprKind::Index(indexed, range) = addressee.kind;
             if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull);
             if TyS::same_type(cx.typeck_results().expr_ty(expr), cx.typeck_results().expr_ty(indexed));
             then {
                 let mut app = Applicability::MachineApplicable;
-                let hint = snippet_with_applicability(cx, indexed.span, "..", &mut app).into_owned();
+                let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
+
+                let (reborrow_str, help_str) = if mutability == Mutability::Mut {
+                    // The slice was used to reborrow the mutable reference.
+                    ("&mut *", "reborrow the original value instead")
+                } else if matches!(
+                    get_parent_expr(cx, expr),
+                    Some(Expr {
+                        kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _),
+                        ..
+                    })
+                ) {
+                    // The slice was used to make a temporary reference.
+                    ("&*", "reborrow the original value instead")
+                } else {
+                    ("", "use the original value instead")
+                };
 
                 span_lint_and_sugg(
                     cx,
                     REDUNDANT_SLICING,
                     expr.span,
                     "redundant slicing of the whole range",
-                    "use the original slice instead",
-                    hint,
+                    help_str,
+                    format!("{}{}", reborrow_str, snip),
                     app,
                 );
             }
diff --git a/clippy_lints/src/ref_option_ref.rs b/clippy_lints/src/ref_option_ref.rs
index 0922cfa494e..0cf4e0ce7fe 100644
--- a/clippy_lints/src/ref_option_ref.rs
+++ b/clippy_lints/src/ref_option_ref.rs
@@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
             if let Some(def_id) = res.opt_def_id();
 
             if cx.tcx.is_diagnostic_item(sym::option_type, def_id);
-            if let Some(ref params) = last_path_segment(qpath).args ;
+            if let Some(params) = last_path_segment(qpath).args ;
             if !params.parenthesized;
             if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg {
                 GenericArg::Type(inner_ty) => Some(inner_ty),
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index 1cc332de894..4b5306de58e 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -60,7 +60,7 @@ impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
 impl<'tcx> LateLintPass<'tcx> for Regex {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::Call(ref fun, ref args) = expr.kind;
+            if let ExprKind::Call(fun, args) = expr.kind;
             if let ExprKind::Path(ref qpath) = fun.kind;
             if args.len() == 1;
             if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
@@ -134,7 +134,7 @@ fn is_trivial_regex(s: &regex_syntax::hir::Hir) -> Option<&'static str> {
 
 fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
     if_chain! {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind;
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind;
         if let ExprKind::Array(exprs) = expr.kind;
         then {
             for expr in exprs {
diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs
index 63e5ec69e66..560a5e7c920 100644
--- a/clippy_lints/src/repeat_once.rs
+++ b/clippy_lints/src/repeat_once.rs
@@ -45,10 +45,10 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
         if_chain! {
             if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
             if path.ident.name == sym!(repeat);
-            if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(&count);
+            if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(count);
             if !in_macro(receiver.span);
             then {
-                let ty = cx.typeck_results().expr_ty(&receiver).peel_refs();
+                let ty = cx.typeck_results().expr_ty(receiver).peel_refs();
                 if ty.is_str() {
                     span_lint_and_sugg(
                         cx,
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 8995ae431ad..af772cf4a14 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
                         err.span_label(local.span, "unnecessary `let` binding");
 
                         if let Some(mut snippet) = snippet_opt(cx, initexpr.span) {
-                            if !cx.typeck_results().expr_adjustments(&retexpr).is_empty() {
+                            if !cx.typeck_results().expr_adjustments(retexpr).is_empty() {
                                 snippet.push_str(" as _");
                             }
                             err.multipart_suggestion(
@@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
                 check_final_expr(cx, &body.value, Some(body.value.span), replacement)
             },
             FnKind::ItemFn(..) | FnKind::Method(..) => {
-                if let ExprKind::Block(ref block, _) = body.value.kind {
+                if let ExprKind::Block(block, _) = body.value.kind {
                     check_block_return(cx, block);
                 }
             },
@@ -160,7 +160,7 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) {
         check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty);
     } else if let Some(stmt) = block.stmts.iter().last() {
         match stmt.kind {
-            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
+            StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
                 check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty);
             },
             _ => (),
@@ -192,11 +192,11 @@ fn check_final_expr<'tcx>(
             }
         },
         // a whole block? check it!
-        ExprKind::Block(ref block, _) => {
+        ExprKind::Block(block, _) => {
             check_block_return(cx, block);
         },
         ExprKind::If(_, then, else_clause_opt) => {
-            if let ExprKind::Block(ref ifblock, _) = then.kind {
+            if let ExprKind::Block(ifblock, _) = then.kind {
                 check_block_return(cx, ifblock);
             }
             if let Some(else_clause) = else_clause_opt {
@@ -207,16 +207,16 @@ fn check_final_expr<'tcx>(
         // an if/if let expr, check both exprs
         // note, if without else is going to be a type checking error anyways
         // (except for unit type functions) so we don't match it
-        ExprKind::Match(_, ref arms, source) => match source {
+        ExprKind::Match(_, arms, source) => match source {
             MatchSource::Normal => {
                 for arm in arms.iter() {
-                    check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block);
+                    check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Block);
                 }
             },
             MatchSource::IfLetDesugar {
                 contains_else_clause: true,
             } => {
-                if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind {
+                if let ExprKind::Block(ifblock, _) = arms[0].body.kind {
                     check_block_return(cx, ifblock);
                 }
                 check_final_expr(cx, arms[1].body, None, RetReplacement::Empty);
diff --git a/clippy_lints/src/semicolon_if_nothing_returned.rs b/clippy_lints/src/semicolon_if_nothing_returned.rs
index f61af15fbed..553987a426b 100644
--- a/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -51,7 +51,7 @@ impl LateLintPass<'_> for SemicolonIfNothingReturned {
                     return;
                 }
 
-                let sugg = sugg::Sugg::hir_with_macro_callsite(cx, &expr, "..");
+                let sugg = sugg::Sugg::hir_with_macro_callsite(cx, expr, "..");
                 let suggestion = format!("{0};", sugg);
                 span_lint_and_sugg(
                     cx,
diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index 612d2fd84cb..d6101bd5e36 100644
--- a/clippy_lints/src/shadow.rs
+++ b/clippy_lints/src/shadow.rs
@@ -130,12 +130,12 @@ fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &
     let len = bindings.len();
     for stmt in block.stmts {
         match stmt.kind {
-            StmtKind::Local(ref local) => check_local(cx, local, bindings),
-            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
+            StmtKind::Local(local) => check_local(cx, local, bindings),
+            StmtKind::Expr(e) | StmtKind::Semi(e) => check_expr(cx, e, bindings),
             StmtKind::Item(..) => {},
         }
     }
-    if let Some(ref o) = block.expr {
+    if let Some(o) = block.expr {
         check_expr(cx, o, bindings);
     }
     bindings.truncate(len);
@@ -149,16 +149,16 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &
         return;
     }
     let Local {
-        ref pat,
+        pat,
         ref ty,
         ref init,
         span,
         ..
     } = *local;
-    if let Some(ref t) = *ty {
+    if let Some(t) = *ty {
         check_ty(cx, t, bindings)
     }
-    if let Some(ref o) = *init {
+    if let Some(o) = *init {
         check_expr(cx, o, bindings);
         check_pat(cx, pat, Some(o), span, bindings);
     } else {
@@ -196,34 +196,34 @@ fn check_pat<'tcx>(
                     bindings.push((name, ident.span));
                 }
             }
-            if let Some(ref p) = *inner {
+            if let Some(p) = *inner {
                 check_pat(cx, p, init, span, bindings);
             }
         },
         PatKind::Struct(_, pfields, _) => {
             if let Some(init_struct) = init {
-                if let ExprKind::Struct(_, ref efields, _) = init_struct.kind {
+                if let ExprKind::Struct(_, efields, _) = init_struct.kind {
                     for field in pfields {
                         let name = field.ident.name;
                         let efield = efields
                             .iter()
                             .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
-                        check_pat(cx, &field.pat, efield, span, bindings);
+                        check_pat(cx, field.pat, efield, span, bindings);
                     }
                 } else {
                     for field in pfields {
-                        check_pat(cx, &field.pat, init, span, bindings);
+                        check_pat(cx, field.pat, init, span, bindings);
                     }
                 }
             } else {
                 for field in pfields {
-                    check_pat(cx, &field.pat, None, span, bindings);
+                    check_pat(cx, field.pat, None, span, bindings);
                 }
             }
         },
         PatKind::Tuple(inner, _) => {
             if let Some(init_tup) = init {
-                if let ExprKind::Tup(ref tup) = init_tup.kind {
+                if let ExprKind::Tup(tup) = init_tup.kind {
                     for (i, p) in inner.iter().enumerate() {
                         check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                     }
@@ -238,10 +238,10 @@ fn check_pat<'tcx>(
                 }
             }
         },
-        PatKind::Box(ref inner) => {
+        PatKind::Box(inner) => {
             if let Some(initp) = init {
-                if let ExprKind::Box(ref inner_init) = initp.kind {
-                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
+                if let ExprKind::Box(inner_init) = initp.kind {
+                    check_pat(cx, inner, Some(inner_init), span, bindings);
                 } else {
                     check_pat(cx, inner, init, span, bindings);
                 }
@@ -249,7 +249,7 @@ fn check_pat<'tcx>(
                 check_pat(cx, inner, init, span, bindings);
             }
         },
-        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
+        PatKind::Ref(inner, _) => check_pat(cx, inner, init, span, bindings),
         // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
         _ => (),
     }
@@ -323,11 +323,10 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
         return;
     }
     match expr.kind {
-        ExprKind::Unary(_, ref e)
-        | ExprKind::Field(ref e, _)
-        | ExprKind::AddrOf(_, _, ref e)
-        | ExprKind::Box(ref e) => check_expr(cx, e, bindings),
-        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, ..) => check_block(cx, block, bindings),
+        ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => {
+            check_expr(cx, e, bindings)
+        },
+        ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings),
         // ExprKind::Call
         // ExprKind::MethodCall
         ExprKind::Array(v) | ExprKind::Tup(v) => {
@@ -335,18 +334,18 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
                 check_expr(cx, e, bindings)
             }
         },
-        ExprKind::If(ref cond, ref then, ref otherwise) => {
+        ExprKind::If(cond, then, ref otherwise) => {
             check_expr(cx, cond, bindings);
-            check_expr(cx, &**then, bindings);
-            if let Some(ref o) = *otherwise {
+            check_expr(cx, then, bindings);
+            if let Some(o) = *otherwise {
                 check_expr(cx, o, bindings);
             }
         },
-        ExprKind::Match(ref init, arms, _) => {
+        ExprKind::Match(init, arms, _) => {
             check_expr(cx, init, bindings);
             let len = bindings.len();
             for arm in arms {
-                check_pat(cx, &arm.pat, Some(&**init), arm.pat.span, bindings);
+                check_pat(cx, arm.pat, Some(init), arm.pat.span, bindings);
                 // This is ugly, but needed to get the right type
                 if let Some(ref guard) = arm.guard {
                     match guard {
@@ -357,7 +356,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
                         },
                     }
                 }
-                check_expr(cx, &arm.body, bindings);
+                check_expr(cx, arm.body, bindings);
                 bindings.truncate(len);
             }
         },
@@ -367,14 +366,12 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
 
 fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
     match ty.kind {
-        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
-        TyKind::Array(ref fty, ref anon_const) => {
+        TyKind::Slice(sty) => check_ty(cx, sty, bindings),
+        TyKind::Array(fty, ref anon_const) => {
             check_ty(cx, fty, bindings);
             check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
         },
-        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
-            check_ty(cx, mty, bindings)
-        },
+        TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings),
         TyKind::Tup(tup) => {
             for t in tup {
                 check_ty(cx, t, bindings)
@@ -387,12 +384,12 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(
 
 fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
     match expr.kind {
-        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner),
-        ExprKind::Block(ref block, _) => {
+        ExprKind::Box(inner) | ExprKind::AddrOf(_, _, inner) => is_self_shadow(name, inner),
+        ExprKind::Block(block, _) => {
             block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
         },
-        ExprKind::Unary(op, ref inner) => (UnOp::Deref == op) && is_self_shadow(name, inner),
-        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
+        ExprKind::Unary(op, inner) => (UnOp::Deref == op) && is_self_shadow(name, inner),
+        ExprKind::Path(QPath::Resolved(_, path)) => path_eq_name(name, path),
         _ => false,
     }
 }
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index d55a83f1613..8cf89ae456e 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -70,14 +70,14 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)`
         if_chain! {
-            if let ExprKind::Assign(ref left, ref right, _) = expr.kind;
+            if let ExprKind::Assign(left, right, _) = expr.kind;
 
             // Extract variable name
-            if let ExprKind::Path(QPath::Resolved(_, ref path)) = left.kind;
+            if let ExprKind::Path(QPath::Resolved(_, path)) = left.kind;
             if let Some(variable_name) = path.segments.get(0);
 
             // Extract len argument
-            if let Some(ref len_arg) = Self::is_vec_with_capacity(right);
+            if let Some(len_arg) = Self::is_vec_with_capacity(right);
 
             then {
                 let vi = VecAllocation {
@@ -94,10 +94,10 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
         if_chain! {
-            if let StmtKind::Local(ref local) = stmt.kind;
+            if let StmtKind::Local(local) = stmt.kind;
             if let PatKind::Binding(BindingAnnotation::Mutable, .., variable_name, None) = local.pat.kind;
-            if let Some(ref init) = local.init;
-            if let Some(ref len_arg) = Self::is_vec_with_capacity(init);
+            if let Some(init) = local.init;
+            if let Some(len_arg) = Self::is_vec_with_capacity(init);
 
             then {
                 let vi = VecAllocation {
@@ -117,7 +117,7 @@ impl SlowVectorInit {
     /// of the first argument of `with_capacity` call if it matches or `None` if it does not.
     fn is_vec_with_capacity<'tcx>(expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
         if_chain! {
-            if let ExprKind::Call(ref func, ref args) = expr.kind;
+            if let ExprKind::Call(func, args) = expr.kind;
             if let ExprKind::Path(ref path) = func.kind;
             if match_qpath(path, &["Vec", "with_capacity"]);
             if args.len() == 1;
@@ -208,11 +208,11 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             if self.initialization_found;
-            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
             if let ExprKind::Path(ref qpath_subj) = args[0].kind;
-            if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
+            if match_qpath(qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
             if path.ident.name == sym!(extend);
-            if let Some(ref extend_arg) = args.get(1);
+            if let Some(extend_arg) = args.get(1);
             if self.is_repeat_take(extend_arg);
 
             then {
@@ -225,11 +225,11 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             if self.initialization_found;
-            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
             if let ExprKind::Path(ref qpath_subj) = args[0].kind;
-            if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
+            if match_qpath(qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
             if path.ident.name == sym!(resize);
-            if let (Some(ref len_arg), Some(fill_arg)) = (args.get(1), args.get(2));
+            if let (Some(len_arg), Some(fill_arg)) = (args.get(1), args.get(2));
 
             // Check that is filled with 0
             if let ExprKind::Lit(ref lit) = fill_arg.kind;
@@ -247,15 +247,15 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     /// Returns `true` if give expression is `repeat(0).take(...)`
     fn is_repeat_take(&self, expr: &Expr<'_>) -> bool {
         if_chain! {
-            if let ExprKind::MethodCall(ref take_path, _, ref take_args, _) = expr.kind;
+            if let ExprKind::MethodCall(take_path, _, take_args, _) = expr.kind;
             if take_path.ident.name == sym!(take);
 
             // Check that take is applied to `repeat(0)`
-            if let Some(ref repeat_expr) = take_args.get(0);
+            if let Some(repeat_expr) = take_args.get(0);
             if Self::is_repeat_zero(repeat_expr);
 
             // Check that len expression is equals to `with_capacity` expression
-            if let Some(ref len_arg) = take_args.get(1);
+            if let Some(len_arg) = take_args.get(1);
             if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr);
 
             then {
@@ -269,10 +269,10 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     /// Returns `true` if given expression is `repeat(0)`
     fn is_repeat_zero(expr: &Expr<'_>) -> bool {
         if_chain! {
-            if let ExprKind::Call(ref fn_expr, ref repeat_args) = expr.kind;
+            if let ExprKind::Call(fn_expr, repeat_args) = expr.kind;
             if let ExprKind::Path(ref qpath_repeat) = fn_expr.kind;
-            if match_qpath(&qpath_repeat, &["repeat"]);
-            if let Some(ref repeat_arg) = repeat_args.get(0);
+            if match_qpath(qpath_repeat, &["repeat"]);
+            if let Some(repeat_arg) = repeat_args.get(0);
             if let ExprKind::Lit(ref lit) = repeat_arg.kind;
             if let LitKind::Int(0, _) = lit.node;
 
@@ -291,7 +291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         if self.initialization_found {
             match stmt.kind {
-                StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
+                StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
                     self.search_slow_extend_filling(expr);
                     self.search_slow_resize_filling(expr);
                 },
@@ -306,7 +306,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
 
     fn visit_block(&mut self, block: &'tcx Block<'_>) {
         if self.initialization_found {
-            if let Some(ref s) = block.stmts.get(0) {
+            if let Some(s) = block.stmts.get(0) {
                 self.visit_stmt(s)
             }
 
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 99ca7ef77a5..9d91b53e1bb 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
             Spanned {
                 node: BinOpKind::Add, ..
             },
-            ref left,
+            left,
             _,
         ) = e.kind
         {
@@ -127,7 +127,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
                 if !is_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
                     let parent = get_parent_expr(cx, e);
                     if let Some(p) = parent {
-                        if let ExprKind::Assign(ref target, _, _) = p.kind {
+                        if let ExprKind::Assign(target, _, _) = p.kind {
                             // avoid duplicate matches
                             if SpanlessEq::new(cx).eq_expr(target, left) {
                                 return;
@@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
                     "you added something to a string. Consider using `String::push_str()` instead",
                 );
             }
-        } else if let ExprKind::Assign(ref target, ref src, _) = e.kind {
+        } else if let ExprKind::Assign(target, src, _) = e.kind {
             if is_string(cx, target) && is_add(cx, src, target) {
                 span_lint(
                     cx,
@@ -166,10 +166,10 @@ fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool {
             Spanned {
                 node: BinOpKind::Add, ..
             },
-            ref left,
+            left,
             _,
         ) => SpanlessEq::new(cx).eq_expr(target, left),
-        ExprKind::Block(ref block, _) => {
+        ExprKind::Block(block, _) => {
             block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target))
         },
         _ => false,
@@ -210,8 +210,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
             if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8);
 
             // Find string::as_bytes
-            if let ExprKind::AddrOf(BorrowKind::Ref, _, ref args) = args[0].kind;
-            if let ExprKind::Index(ref left, ref right) = args.kind;
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind;
+            if let ExprKind::Index(left, right) = args.kind;
             let (method_names, expressions, _) = method_calls(left, 1);
             if method_names.len() == 1;
             if expressions.len() == 1;
diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs
index 46f423204a2..cb2237e5312 100644
--- a/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/clippy_lints/src/suspicious_operation_groupings.rs
@@ -225,7 +225,7 @@ fn attempt_to_emit_no_difference_lint(
                     emit_suggestion(
                         cx,
                         binop.span,
-                        replace_left_sugg(cx, &binop, &sugg, &mut applicability),
+                        replace_left_sugg(cx, binop, &sugg, &mut applicability),
                         applicability,
                     );
                     return;
@@ -247,7 +247,7 @@ fn attempt_to_emit_no_difference_lint(
                     emit_suggestion(
                         cx,
                         binop.span,
-                        replace_right_sugg(cx, &binop, &sugg, &mut applicability),
+                        replace_right_sugg(cx, binop, &sugg, &mut applicability),
                         applicability,
                     );
                     return;
@@ -276,8 +276,8 @@ fn ident_swap_sugg(
     location: IdentLocation,
     applicability: &mut Applicability,
 ) -> Option<String> {
-    let left_ident = get_ident(&binop.left, location)?;
-    let right_ident = get_ident(&binop.right, location)?;
+    let left_ident = get_ident(binop.left, location)?;
+    let right_ident = get_ident(binop.right, location)?;
 
     let sugg = match (
         paired_identifiers.contains(&left_ident),
@@ -293,8 +293,7 @@ fn ident_swap_sugg(
             // ends up duplicating a clause, the `logic_bug` lint
             // should catch it.
 
-            let right_suggestion =
-                suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?;
+            let right_suggestion = suggestion_with_swapped_ident(cx, binop.right, location, left_ident, applicability)?;
 
             replace_right_sugg(cx, binop, &right_suggestion, applicability)
         },
@@ -302,15 +301,14 @@ fn ident_swap_sugg(
             // We haven't seen a pair involving the left one, so
             // it's probably what is wanted.
 
-            let right_suggestion =
-                suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?;
+            let right_suggestion = suggestion_with_swapped_ident(cx, binop.right, location, left_ident, applicability)?;
 
             replace_right_sugg(cx, binop, &right_suggestion, applicability)
         },
         (true, false) => {
             // We haven't seen a pair involving the right one, so
             // it's probably what is wanted.
-            let left_suggestion = suggestion_with_swapped_ident(cx, &binop.left, location, right_ident, applicability)?;
+            let left_suggestion = suggestion_with_swapped_ident(cx, binop.left, location, right_ident, applicability)?;
 
             replace_left_sugg(cx, binop, &left_suggestion, applicability)
         },
diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs
index 99e3d818b79..512abde11a6 100644
--- a/clippy_lints/src/suspicious_trait_impl.rs
+++ b/clippy_lints/src/suspicious_trait_impl.rs
@@ -68,14 +68,13 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
 
             // Check for more than one binary operation in the implemented function
             // Linting when multiple operations are involved can result in false positives
+            let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
             if_chain! {
-                let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
                 if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
                 if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
-                let body = cx.tcx.hir().body(body_id);
-                let mut visitor = BinaryExprVisitor { nb_binops: 0 };
-
                 then {
+                    let body = cx.tcx.hir().body(body_id);
+                    let mut visitor = BinaryExprVisitor { nb_binops: 0 };
                     walk_expr(&mut visitor, &body.value);
                     if visitor.nb_binops > 1 {
                         return;
diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs
index 14519eaa962..19967e2c970 100644
--- a/clippy_lints/src/swap.rs
+++ b/clippy_lints/src/swap.rs
@@ -78,26 +78,26 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
     for w in block.stmts.windows(3) {
         if_chain! {
             // let t = foo();
-            if let StmtKind::Local(ref tmp) = w[0].kind;
-            if let Some(ref tmp_init) = tmp.init;
+            if let StmtKind::Local(tmp) = w[0].kind;
+            if let Some(tmp_init) = tmp.init;
             if let PatKind::Binding(.., ident, None) = tmp.pat.kind;
 
             // foo() = bar();
-            if let StmtKind::Semi(ref first) = w[1].kind;
-            if let ExprKind::Assign(ref lhs1, ref rhs1, _) = first.kind;
+            if let StmtKind::Semi(first) = w[1].kind;
+            if let ExprKind::Assign(lhs1, rhs1, _) = first.kind;
 
             // bar() = t;
-            if let StmtKind::Semi(ref second) = w[2].kind;
-            if let ExprKind::Assign(ref lhs2, ref rhs2, _) = second.kind;
-            if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.kind;
+            if let StmtKind::Semi(second) = w[2].kind;
+            if let ExprKind::Assign(lhs2, rhs2, _) = second.kind;
+            if let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind;
             if rhs2.segments.len() == 1;
 
             if ident.name == rhs2.segments[0].ident.name;
             if eq_expr_value(cx, tmp_init, lhs1);
             if eq_expr_value(cx, rhs1, lhs2);
             then {
-                if let ExprKind::Field(ref lhs1, _) = lhs1.kind {
-                    if let ExprKind::Field(ref lhs2, _) = lhs2.kind {
+                if let ExprKind::Field(lhs1, _) = lhs1.kind {
+                    if let ExprKind::Field(lhs2, _) = lhs2.kind {
                         if lhs1.hir_id.owner == lhs2.hir_id.owner {
                             return;
                         }
@@ -192,8 +192,8 @@ enum Slice<'a> {
 
 /// Checks if both expressions are index operations into "slice-like" types.
 fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> {
-    if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind {
-        if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind {
+    if let ExprKind::Index(lhs1, idx1) = lhs1.kind {
+        if let ExprKind::Index(lhs2, idx2) = lhs2.kind {
             if eq_expr_value(cx, lhs1, lhs2) {
                 let ty = cx.typeck_results().expr_ty(lhs1).peel_refs();
 
@@ -217,11 +217,11 @@ fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<
 fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
     for w in block.stmts.windows(2) {
         if_chain! {
-            if let StmtKind::Semi(ref first) = w[0].kind;
-            if let StmtKind::Semi(ref second) = w[1].kind;
+            if let StmtKind::Semi(first) = w[0].kind;
+            if let StmtKind::Semi(second) = w[1].kind;
             if !differing_macro_contexts(first.span, second.span);
-            if let ExprKind::Assign(ref lhs0, ref rhs0, _) = first.kind;
-            if let ExprKind::Assign(ref lhs1, ref rhs1, _) = second.kind;
+            if let ExprKind::Assign(lhs0, rhs0, _) = first.kind;
+            if let ExprKind::Assign(lhs1, rhs1, _) = second.kind;
             if eq_expr_value(cx, lhs0, rhs1);
             if eq_expr_value(cx, lhs1, rhs0);
             then {
diff --git a/clippy_lints/src/tabs_in_doc_comments.rs b/clippy_lints/src/tabs_in_doc_comments.rs
index 88bd2feaadd..a0492a88f91 100644
--- a/clippy_lints/src/tabs_in_doc_comments.rs
+++ b/clippy_lints/src/tabs_in_doc_comments.rs
@@ -86,7 +86,7 @@ impl TabsInDocComments {
 
 impl EarlyLintPass for TabsInDocComments {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attribute: &ast::Attribute) {
-        Self::warn_if_tabs_in_doc(cx, &attribute);
+        Self::warn_if_tabs_in_doc(cx, attribute);
     }
 }
 
diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs
index 42ec14c31b5..ae05a8da37b 100644
--- a/clippy_lints/src/to_string_in_display.rs
+++ b/clippy_lints/src/to_string_in_display.rs
@@ -92,7 +92,7 @@ impl LateLintPass<'_> for ToStringInDisplay {
         if_chain! {
             if self.in_display_impl;
             if let Some(self_hir_id) = self.self_hir_id;
-            if let ExprKind::MethodCall(ref path, _, args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
             if path.ident.name == sym!(to_string);
             if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
             if is_diagnostic_assoc_item(cx, expr_def_id, sym::ToString);
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 3ff27c3bcf4..b0589b0512e 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -107,7 +107,7 @@ impl TraitBounds {
                 if let WherePredicate::BoundPredicate(ref p) = bound;
                 if p.bounds.len() as u64 <= self.max_trait_bounds;
                 if !in_macro(p.span);
-                let h = hash(&p.bounded_ty);
+                let h = hash(p.bounded_ty);
                 if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>());
 
                 then {
@@ -170,7 +170,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
         if_chain! {
             if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
             if !in_macro(bound_predicate.span);
-            if let TyKind::Path(QPath::Resolved(_, Path { ref segments, .. })) = bound_predicate.bounded_ty.kind;
+            if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
             if let Some(segment) = segments.first();
             if let Some(trait_resolutions_direct) = map.get(&segment.ident);
             then {
diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index 47d58bd30db..86ac916df6c 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -325,7 +325,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
     #[allow(clippy::similar_names, clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::Call(ref path_expr, ref args) = e.kind;
+            if let ExprKind::Call(path_expr, args) = e.kind;
             if let ExprKind::Path(ref qpath) = path_expr.kind;
             if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id();
             if match_def_path(cx, def_id, &paths::TRANSMUTE);
diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index 72489f27cd3..3aa3c393ba5 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -30,16 +30,16 @@ pub(super) fn check<'tcx>(
                     let mut arg = sugg::Sugg::hir(cx, expr, "..");
 
                     if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind {
-                        expr = &inner_expr;
+                        expr = inner_expr;
                     }
 
                     if_chain! {
                         // if the expression is a float literal and it is unsuffixed then
                         // add a suffix so the suggestion is valid and unambiguous
-                        let op = format!("{}{}", arg, float_ty.name_str()).into();
                         if let ExprKind::Lit(lit) = &expr.kind;
                         if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node;
                         then {
+                            let op = format!("{}{}", arg, float_ty.name_str()).into();
                             match arg {
                                 sugg::Sugg::MaybeParen(_) => arg = sugg::Sugg::MaybeParen(op),
                                 _ => arg = sugg::Sugg::NonParen(op)
diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs
index c6d0d63b0b5..f359b606e45 100644
--- a/clippy_lints/src/transmute/utils.rs
+++ b/clippy_lints/src/transmute/utils.rs
@@ -16,7 +16,7 @@ use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited};
 pub(super) fn get_type_snippet(cx: &LateContext<'_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String {
     let seg = last_path_segment(path);
     if_chain! {
-        if let Some(ref params) = seg.args;
+        if let Some(params) = seg.args;
         if !params.parenthesized;
         if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg {
             GenericArg::Type(ty) => Some(ty),
diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs
index d42cdde110e..0be05d3e0cf 100644
--- a/clippy_lints/src/transmuting_null.rs
+++ b/clippy_lints/src/transmuting_null.rs
@@ -37,7 +37,7 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull {
         }
 
         if_chain! {
-            if let ExprKind::Call(ref func, ref args) = expr.kind;
+            if let ExprKind::Call(func, args) = expr.kind;
             if let ExprKind::Path(ref path) = func.kind;
             if match_qpath(path, &paths::STD_MEM_TRANSMUTE);
             if args.len() == 1;
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull {
                 // Catching:
                 // `std::mem::transmute(0 as *const i32)`
                 if_chain! {
-                    if let ExprKind::Cast(ref inner_expr, ref _cast_ty) = args[0].kind;
+                    if let ExprKind::Cast(inner_expr, _cast_ty) = args[0].kind;
                     if let ExprKind::Lit(ref lit) = inner_expr.kind;
                     if let LitKind::Int(0, _) = lit.node;
                     then {
@@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull {
                 // Catching:
                 // `std::mem::transmute(std::ptr::null::<i32>())`
                 if_chain! {
-                    if let ExprKind::Call(ref func1, ref args1) = args[0].kind;
+                    if let ExprKind::Call(func1, args1) = args[0].kind;
                     if let ExprKind::Path(ref path1) = func1.kind;
                     if match_qpath(path1, &paths::STD_PTR_NULL);
                     if args1.is_empty();
diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs
index e61058c2749..23a1953ffac 100644
--- a/clippy_lints/src/try_err.rs
+++ b/clippy_lints/src/try_err.rs
@@ -60,13 +60,13 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
         // };
         if_chain! {
             if !in_external_macro(cx.tcx.sess, expr.span);
-            if let ExprKind::Match(ref match_arg, _, MatchSource::TryDesugar) = expr.kind;
-            if let ExprKind::Call(ref match_fun, ref try_args) = match_arg.kind;
+            if let ExprKind::Match(match_arg, _, MatchSource::TryDesugar) = expr.kind;
+            if let ExprKind::Call(match_fun, try_args) = match_arg.kind;
             if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
             if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _));
-            if let Some(ref try_arg) = try_args.get(0);
-            if let ExprKind::Call(ref err_fun, ref err_args) = try_arg.kind;
-            if let Some(ref err_arg) = err_args.get(0);
+            if let Some(try_arg) = try_args.get(0);
+            if let ExprKind::Call(err_fun, err_args) = try_arg.kind;
+            if let Some(err_arg) = err_args.get(0);
             if let ExprKind::Path(ref err_fun_path) = err_fun.kind;
             if match_qpath(err_fun_path, &paths::RESULT_ERR);
             if let Some(return_ty) = find_return_type(cx, &expr.kind);
@@ -123,9 +123,9 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
 
 /// Finds function return type by examining return expressions in match arms.
 fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> {
-    if let ExprKind::Match(_, ref arms, MatchSource::TryDesugar) = expr {
+    if let ExprKind::Match(_, arms, MatchSource::TryDesugar) = expr {
         for arm in arms.iter() {
-            if let ExprKind::Ret(Some(ref ret)) = arm.body.kind {
+            if let ExprKind::Ret(Some(ret)) = arm.body.kind {
                 return Some(cx.typeck_results().expr_ty(ret));
             }
         }
@@ -138,9 +138,8 @@ fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
     if_chain! {
         if let ty::Adt(_, subst) = ty.kind();
         if is_type_diagnostic_item(cx, ty, sym::result_type);
-        let err_ty = subst.type_at(1);
         then {
-            Some(err_ty)
+            Some(subst.type_at(1))
         } else {
             None
         }
@@ -156,10 +155,8 @@ fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<
 
         if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
         if cx.tcx.is_diagnostic_item(sym::result_type, ready_def.did);
-        let err_ty = ready_subst.type_at(1);
-
         then {
-            Some(err_ty)
+            Some(ready_subst.type_at(1))
         } else {
             None
         }
@@ -179,10 +176,8 @@ fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) ->
 
         if let ty::Adt(some_def, some_subst) = some_ty.kind();
         if cx.tcx.is_diagnostic_item(sym::result_type, some_def.did);
-        let err_ty = some_subst.type_at(1);
-
         then {
-            Some(err_ty)
+            Some(some_subst.type_at(1))
         } else {
             None
         }
diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs
index d68c6db4e23..1425d8f3f37 100644
--- a/clippy_lints/src/types/borrowed_box.rs
+++ b/clippy_lints/src/types/borrowed_box.rs
@@ -19,9 +19,9 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
             if_chain! {
                 if let Some(def_id) = def.opt_def_id();
                 if Some(def_id) == cx.tcx.lang_items().owned_box();
-                if let QPath::Resolved(None, ref path) = *qpath;
+                if let QPath::Resolved(None, path) = *qpath;
                 if let [ref bx] = *path.segments;
-                if let Some(ref params) = bx.args;
+                if let Some(params) = bx.args;
                 if !params.parenthesized;
                 if let Some(inner) = params.args.iter().find_map(|arg| match arg {
                     GenericArg::Type(ty) => Some(ty),
@@ -86,11 +86,11 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
 // Returns true if given type is `Any` trait.
 fn is_any_trait(t: &hir::Ty<'_>) -> bool {
     if_chain! {
-        if let TyKind::TraitObject(ref traits, ..) = t.kind;
+        if let TyKind::TraitObject(traits, ..) = t.kind;
         if !traits.is_empty();
         // Only Send/Sync can be used as additional traits, so it is enough to
         // check only the first trait.
-        if match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT);
+        if match_path(traits[0].trait_ref.path, &paths::ANY_TRAIT);
         then {
             return true;
         }
diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs
index c73c1c9d92d..d9b47a699dc 100644
--- a/clippy_lints/src/types/mod.rs
+++ b/clippy_lints/src/types/mod.rs
@@ -1,43 +1,22 @@
-#![allow(rustc::default_hash_types)]
-
 mod borrowed_box;
 mod box_vec;
 mod linked_list;
 mod option_option;
 mod rc_buffer;
 mod redundant_allocation;
+mod type_complexity;
 mod utils;
 mod vec_box;
 
-use std::borrow::Cow;
-use std::cmp::Ordering;
-use std::collections::BTreeMap;
-
-use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_help, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_opt};
-use clippy_utils::ty::{is_isize_or_usize, is_type_diagnostic_item};
-use if_chain::if_chain;
-use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
-    BinOpKind, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem,
-    ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitFn, TraitItem, TraitItemKind, TyKind,
+    Body, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem,
+    TraitItemKind, TyKind,
 };
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
-use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, IntTy, Ty, TyS, TypeckResults, UintTy};
-use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
-use rustc_span::symbol::sym;
-use rustc_target::abi::LayoutOf;
-use rustc_target::spec::abi::Abi;
-use rustc_typeck::hir_ty_to_ty;
-
-use crate::consts::{constant, Constant};
-use clippy_utils::paths;
-use clippy_utils::{clip, comparisons, differing_macro_contexts, int_bits, match_path, sext, unsext};
 
 declare_clippy_lint! {
     /// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
@@ -250,55 +229,119 @@ declare_clippy_lint! {
     "shared ownership of a buffer type"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for types used in structs, parameters and `let`
+    /// declarations above a certain complexity threshold.
+    ///
+    /// **Why is this bad?** Too complex types make the code less readable. Consider
+    /// using a `type` definition to simplify them.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// # use std::rc::Rc;
+    /// struct Foo {
+    ///     inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
+    /// }
+    /// ```
+    pub TYPE_COMPLEXITY,
+    complexity,
+    "usage of very complex types that might be better factored into `type` definitions"
+}
+
 pub struct Types {
     vec_box_size_threshold: u64,
+    type_complexity_threshold: u64,
 }
 
-impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER]);
+impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, TYPE_COMPLEXITY]);
 
 impl<'tcx> LateLintPass<'tcx> for Types {
     fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
-        // Skip trait implementations; see issue #605.
-        if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) {
-            if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
-                return;
-            }
+        let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id))
+        {
+            matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
+        } else {
+            false
+        };
+
+        self.check_fn_decl(
+            cx,
+            decl,
+            CheckTyContext {
+                is_in_trait_impl,
+                ..CheckTyContext::default()
+            },
+        );
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        match item.kind {
+            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(cx, ty, CheckTyContext::default()),
+            // functions, enums, structs, impls and traits are covered
+            _ => (),
         }
+    }
 
-        self.check_fn_decl(cx, decl);
+    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
+        match item.kind {
+            ImplItemKind::Const(ty, _) | ImplItemKind::TyAlias(ty) => self.check_ty(
+                cx,
+                ty,
+                CheckTyContext {
+                    is_in_trait_impl: true,
+                    ..CheckTyContext::default()
+                },
+            ),
+            // methods are covered by check_fn
+            ImplItemKind::Fn(..) => (),
+        }
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
-        self.check_ty(cx, &field.ty, false);
+        self.check_ty(cx, field.ty, CheckTyContext::default());
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
         match item.kind {
-            TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_ty(cx, ty, false),
-            TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, &sig.decl),
+            TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => {
+                self.check_ty(cx, ty, CheckTyContext::default())
+            },
+            TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, CheckTyContext::default()),
             TraitItemKind::Type(..) => (),
         }
     }
 
     fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
-        if let Some(ref ty) = local.ty {
-            self.check_ty(cx, ty, true);
+        if let Some(ty) = local.ty {
+            self.check_ty(
+                cx,
+                ty,
+                CheckTyContext {
+                    is_local: true,
+                    ..CheckTyContext::default()
+                },
+            );
         }
     }
 }
 
 impl Types {
-    pub fn new(vec_box_size_threshold: u64) -> Self {
-        Self { vec_box_size_threshold }
+    pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64) -> Self {
+        Self {
+            vec_box_size_threshold,
+            type_complexity_threshold,
+        }
     }
 
-    fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>) {
+    fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) {
         for input in decl.inputs {
-            self.check_ty(cx, input, false);
+            self.check_ty(cx, input, context);
         }
 
-        if let FnRetTy::Return(ref ty) = decl.output {
-            self.check_ty(cx, ty, false);
+        if let FnRetTy::Return(ty) = decl.output {
+            self.check_ty(cx, ty, context);
         }
     }
 
@@ -306,12 +349,22 @@ impl Types {
     /// lint found.
     ///
     /// The parameter `is_local` distinguishes the context of the type.
-    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, is_local: bool) {
+    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) {
         if hir_ty.span.from_expansion() {
             return;
         }
+
+        if !context.is_nested_call && type_complexity::check(cx, hir_ty, self.type_complexity_threshold) {
+            return;
+        }
+
+        // Skip trait implementations; see issue #605.
+        if context.is_in_trait_impl {
+            return;
+        }
+
         match hir_ty.kind {
-            TyKind::Path(ref qpath) if !is_local => {
+            TyKind::Path(ref qpath) if !context.is_local => {
                 let hir_id = hir_ty.hir_id;
                 let res = cx.qpath_res(qpath, hir_id);
                 if let Some(def_id) = res.opt_def_id() {
@@ -328,8 +381,9 @@ impl Types {
                     }
                 }
                 match *qpath {
-                    QPath::Resolved(Some(ref ty), ref p) => {
-                        self.check_ty(cx, ty, is_local);
+                    QPath::Resolved(Some(ty), p) => {
+                        context.is_nested_call = true;
+                        self.check_ty(cx, ty, context);
                         for ty in p.segments.iter().flat_map(|seg| {
                             seg.args
                                 .as_ref()
@@ -339,10 +393,11 @@ impl Types {
                                     _ => None,
                                 })
                         }) {
-                            self.check_ty(cx, ty, is_local);
+                            self.check_ty(cx, ty, context);
                         }
                     },
-                    QPath::Resolved(None, ref p) => {
+                    QPath::Resolved(None, p) => {
+                        context.is_nested_call = true;
                         for ty in p.segments.iter().flat_map(|seg| {
                             seg.args
                                 .as_ref()
@@ -352,17 +407,18 @@ impl Types {
                                     _ => None,
                                 })
                         }) {
-                            self.check_ty(cx, ty, is_local);
+                            self.check_ty(cx, ty, context);
                         }
                     },
-                    QPath::TypeRelative(ref ty, ref seg) => {
-                        self.check_ty(cx, ty, is_local);
-                        if let Some(ref params) = seg.args {
+                    QPath::TypeRelative(ty, seg) => {
+                        context.is_nested_call = true;
+                        self.check_ty(cx, ty, context);
+                        if let Some(params) = seg.args {
                             for ty in params.args.iter().filter_map(|arg| match arg {
                                 GenericArg::Type(ty) => Some(ty),
                                 _ => None,
                             }) {
-                                self.check_ty(cx, ty, is_local);
+                                self.check_ty(cx, ty, context);
                             }
                         }
                     },
@@ -370,16 +426,19 @@ impl Types {
                 }
             },
             TyKind::Rptr(ref lt, ref mut_ty) => {
+                context.is_nested_call = true;
                 if !borrowed_box::check(cx, hir_ty, lt, mut_ty) {
-                    self.check_ty(cx, &mut_ty.ty, is_local);
+                    self.check_ty(cx, mut_ty.ty, context);
                 }
             },
-            TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => {
-                self.check_ty(cx, ty, is_local)
+            TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => {
+                context.is_nested_call = true;
+                self.check_ty(cx, ty, context)
             },
             TyKind::Tup(tys) => {
+                context.is_nested_call = true;
                 for ty in tys {
-                    self.check_ty(cx, ty, is_local);
+                    self.check_ty(cx, ty, context);
                 }
             },
             _ => {},
@@ -387,895 +446,9 @@ impl Types {
     }
 }
 
-declare_clippy_lint! {
-    /// **What it does:** Checks for types used in structs, parameters and `let`
-    /// declarations above a certain complexity threshold.
-    ///
-    /// **Why is this bad?** Too complex types make the code less readable. Consider
-    /// using a `type` definition to simplify them.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// # use std::rc::Rc;
-    /// struct Foo {
-    ///     inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
-    /// }
-    /// ```
-    pub TYPE_COMPLEXITY,
-    complexity,
-    "usage of very complex types that might be better factored into `type` definitions"
-}
-
-pub struct TypeComplexity {
-    threshold: u64,
-}
-
-impl TypeComplexity {
-    #[must_use]
-    pub fn new(threshold: u64) -> Self {
-        Self { threshold }
-    }
-}
-
-impl_lint_pass!(TypeComplexity => [TYPE_COMPLEXITY]);
-
-impl<'tcx> LateLintPass<'tcx> for TypeComplexity {
-    fn check_fn(
-        &mut self,
-        cx: &LateContext<'tcx>,
-        _: FnKind<'tcx>,
-        decl: &'tcx FnDecl<'_>,
-        _: &'tcx Body<'_>,
-        _: Span,
-        _: HirId,
-    ) {
-        self.check_fndecl(cx, decl);
-    }
-
-    fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::FieldDef<'_>) {
-        // enum variants are also struct fields now
-        self.check_type(cx, &field.ty);
-    }
-
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        match item.kind {
-            ItemKind::Static(ref ty, _, _) | ItemKind::Const(ref ty, _) => self.check_type(cx, ty),
-            // functions, enums, structs, impls and traits are covered
-            _ => (),
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
-        match item.kind {
-            TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty),
-            TraitItemKind::Fn(FnSig { ref decl, .. }, TraitFn::Required(_)) => self.check_fndecl(cx, decl),
-            // methods with default impl are covered by check_fn
-            TraitItemKind::Type(..) | TraitItemKind::Fn(_, TraitFn::Provided(_)) => (),
-        }
-    }
-
-    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
-        match item.kind {
-            ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty),
-            // methods are covered by check_fn
-            ImplItemKind::Fn(..) => (),
-        }
-    }
-
-    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
-        if let Some(ref ty) = local.ty {
-            self.check_type(cx, ty);
-        }
-    }
-}
-
-impl<'tcx> TypeComplexity {
-    fn check_fndecl(&self, cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>) {
-        for arg in decl.inputs {
-            self.check_type(cx, arg);
-        }
-        if let FnRetTy::Return(ref ty) = decl.output {
-            self.check_type(cx, ty);
-        }
-    }
-
-    fn check_type(&self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) {
-        if ty.span.from_expansion() {
-            return;
-        }
-        let score = {
-            let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
-            visitor.visit_ty(ty);
-            visitor.score
-        };
-
-        if score > self.threshold {
-            span_lint(
-                cx,
-                TYPE_COMPLEXITY,
-                ty.span,
-                "very complex type used. Consider factoring parts into `type` definitions",
-            );
-        }
-    }
-}
-
-/// Walks a type and assigns a complexity score to it.
-struct TypeComplexityVisitor {
-    /// total complexity score of the type
-    score: u64,
-    /// current nesting level
-    nest: u64,
-}
-
-impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
-    type Map = Map<'tcx>;
-
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
-        let (add_score, sub_nest) = match ty.kind {
-            // _, &x and *x have only small overhead; don't mess with nesting level
-            TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0),
-
-            // the "normal" components of a type: named types, arrays/tuples
-            TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1),
-
-            // function types bring a lot of overhead
-            TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
-
-            TyKind::TraitObject(ref param_bounds, _, _) => {
-                let has_lifetime_parameters = param_bounds.iter().any(|bound| {
-                    bound
-                        .bound_generic_params
-                        .iter()
-                        .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. }))
-                });
-                if has_lifetime_parameters {
-                    // complex trait bounds like A<'a, 'b>
-                    (50 * self.nest, 1)
-                } else {
-                    // simple trait bounds like A + B
-                    (20 * self.nest, 0)
-                }
-            },
-
-            _ => (0, 0),
-        };
-        self.score += add_score;
-        self.nest += sub_nest;
-        walk_ty(self, ty);
-        self.nest -= sub_nest;
-    }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for comparisons where one side of the relation is
-    /// either the minimum or maximum value for its type and warns if it involves a
-    /// case that is always true or always false. Only integer and boolean types are
-    /// checked.
-    ///
-    /// **Why is this bad?** An expression like `min <= x` may misleadingly imply
-    /// that it is possible for `x` to be less than the minimum. Expressions like
-    /// `max < x` are probably mistakes.
-    ///
-    /// **Known problems:** For `usize` the size of the current compile target will
-    /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
-    /// a comparison to detect target pointer width will trigger this lint. One can
-    /// use `mem::sizeof` and compare its value or conditional compilation
-    /// attributes
-    /// like `#[cfg(target_pointer_width = "64")] ..` instead.
-    ///
-    /// **Example:**
-    ///
-    /// ```rust
-    /// let vec: Vec<isize> = Vec::new();
-    /// if vec.len() <= 0 {}
-    /// if 100 > i32::MAX {}
-    /// ```
-    pub ABSURD_EXTREME_COMPARISONS,
-    correctness,
-    "a comparison with a maximum or minimum value that is always true or false"
-}
-
-declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]);
-
-enum ExtremeType {
-    Minimum,
-    Maximum,
-}
-
-struct ExtremeExpr<'a> {
-    which: ExtremeType,
-    expr: &'a Expr<'a>,
-}
-
-enum AbsurdComparisonResult {
-    AlwaysFalse,
-    AlwaysTrue,
-    InequalityImpossible,
-}
-
-fn is_cast_between_fixed_and_target<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
-    if let ExprKind::Cast(ref cast_exp, _) = expr.kind {
-        let precast_ty = cx.typeck_results().expr_ty(cast_exp);
-        let cast_ty = cx.typeck_results().expr_ty(expr);
-
-        return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty);
-    }
-
-    false
-}
-
-fn detect_absurd_comparison<'tcx>(
-    cx: &LateContext<'tcx>,
-    op: BinOpKind,
-    lhs: &'tcx Expr<'_>,
-    rhs: &'tcx Expr<'_>,
-) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> {
-    use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible};
-    use crate::types::ExtremeType::{Maximum, Minimum};
-    use clippy_utils::comparisons::{normalize_comparison, Rel};
-
-    // absurd comparison only makes sense on primitive types
-    // primitive types don't implement comparison operators with each other
-    if cx.typeck_results().expr_ty(lhs) != cx.typeck_results().expr_ty(rhs) {
-        return None;
-    }
-
-    // comparisons between fix sized types and target sized types are considered unanalyzable
-    if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) {
-        return None;
-    }
-
-    let (rel, normalized_lhs, normalized_rhs) = normalize_comparison(op, lhs, rhs)?;
-
-    let lx = detect_extreme_expr(cx, normalized_lhs);
-    let rx = detect_extreme_expr(cx, normalized_rhs);
-
-    Some(match rel {
-        Rel::Lt => {
-            match (lx, rx) {
-                (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x
-                (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min
-                _ => return None,
-            }
-        },
-        Rel::Le => {
-            match (lx, rx) {
-                (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x
-                (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x
-                (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min
-                (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max
-                _ => return None,
-            }
-        },
-        Rel::Ne | Rel::Eq => return None,
-    })
-}
-
-fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
-    use crate::types::ExtremeType::{Maximum, Minimum};
-
-    let ty = cx.typeck_results().expr_ty(expr);
-
-    let cv = constant(cx, cx.typeck_results(), expr)?.0;
-
-    let which = match (ty.kind(), cv) {
-        (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum,
-        (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => {
-            Minimum
-        },
-
-        (&ty::Bool, Constant::Bool(true)) => Maximum,
-        (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => {
-            Maximum
-        },
-        (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => Maximum,
-
-        _ => return None,
-    };
-    Some(ExtremeExpr { which, expr })
-}
-
-impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible};
-        use crate::types::ExtremeType::{Maximum, Minimum};
-
-        if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind {
-            if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) {
-                if !expr.span.from_expansion() {
-                    let msg = "this comparison involving the minimum or maximum element for this \
-                               type contains a case that is always true or always false";
-
-                    let conclusion = match result {
-                        AlwaysFalse => "this comparison is always false".to_owned(),
-                        AlwaysTrue => "this comparison is always true".to_owned(),
-                        InequalityImpossible => format!(
-                            "the case where the two sides are not equal never occurs, consider using `{} == {}` \
-                             instead",
-                            snippet(cx, lhs.span, "lhs"),
-                            snippet(cx, rhs.span, "rhs")
-                        ),
-                    };
-
-                    let help = format!(
-                        "because `{}` is the {} value for this type, {}",
-                        snippet(cx, culprit.expr.span, "x"),
-                        match culprit.which {
-                            Minimum => "minimum",
-                            Maximum => "maximum",
-                        },
-                        conclusion
-                    );
-
-                    span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help);
-                }
-            }
-        }
-    }
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for comparisons where the relation is always either
-    /// true or false, but where one side has been upcast so that the comparison is
-    /// necessary. Only integer types are checked.
-    ///
-    /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300`
-    /// will mistakenly imply that it is possible for `x` to be outside the range of
-    /// `u8`.
-    ///
-    /// **Known problems:**
-    /// https://github.com/rust-lang/rust-clippy/issues/886
-    ///
-    /// **Example:**
-    /// ```rust
-    /// let x: u8 = 1;
-    /// (x as u32) > 300;
-    /// ```
-    pub INVALID_UPCAST_COMPARISONS,
-    pedantic,
-    "a comparison involving an upcast which is always true or false"
-}
-
-declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
-
-#[derive(Copy, Clone, Debug, Eq)]
-enum FullInt {
-    S(i128),
-    U(u128),
-}
-
-impl FullInt {
-    #[allow(clippy::cast_sign_loss)]
-    #[must_use]
-    fn cmp_s_u(s: i128, u: u128) -> Ordering {
-        if s < 0 {
-            Ordering::Less
-        } else if u > (i128::MAX as u128) {
-            Ordering::Greater
-        } else {
-            (s as u128).cmp(&u)
-        }
-    }
-}
-
-impl PartialEq for FullInt {
-    #[must_use]
-    fn eq(&self, other: &Self) -> bool {
-        self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
-    }
-}
-
-impl PartialOrd for FullInt {
-    #[must_use]
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(match (self, other) {
-            (&Self::S(s), &Self::S(o)) => s.cmp(&o),
-            (&Self::U(s), &Self::U(o)) => s.cmp(&o),
-            (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
-            (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
-        })
-    }
-}
-
-impl Ord for FullInt {
-    #[must_use]
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.partial_cmp(other)
-            .expect("`partial_cmp` for FullInt can never return `None`")
-    }
-}
-
-fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
-    if let ExprKind::Cast(ref cast_exp, _) = expr.kind {
-        let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
-        let cast_ty = cx.typeck_results().expr_ty(expr);
-        // if it's a cast from i32 to u32 wrapping will invalidate all these checks
-        if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) {
-            return None;
-        }
-        match pre_cast_ty.kind() {
-            ty::Int(int_ty) => Some(match int_ty {
-                IntTy::I8 => (FullInt::S(i128::from(i8::MIN)), FullInt::S(i128::from(i8::MAX))),
-                IntTy::I16 => (FullInt::S(i128::from(i16::MIN)), FullInt::S(i128::from(i16::MAX))),
-                IntTy::I32 => (FullInt::S(i128::from(i32::MIN)), FullInt::S(i128::from(i32::MAX))),
-                IntTy::I64 => (FullInt::S(i128::from(i64::MIN)), FullInt::S(i128::from(i64::MAX))),
-                IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)),
-                IntTy::Isize => (FullInt::S(isize::MIN as i128), FullInt::S(isize::MAX as i128)),
-            }),
-            ty::Uint(uint_ty) => Some(match uint_ty {
-                UintTy::U8 => (FullInt::U(u128::from(u8::MIN)), FullInt::U(u128::from(u8::MAX))),
-                UintTy::U16 => (FullInt::U(u128::from(u16::MIN)), FullInt::U(u128::from(u16::MAX))),
-                UintTy::U32 => (FullInt::U(u128::from(u32::MIN)), FullInt::U(u128::from(u32::MAX))),
-                UintTy::U64 => (FullInt::U(u128::from(u64::MIN)), FullInt::U(u128::from(u64::MAX))),
-                UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)),
-                UintTy::Usize => (FullInt::U(usize::MIN as u128), FullInt::U(usize::MAX as u128)),
-            }),
-            _ => None,
-        }
-    } else {
-        None
-    }
-}
-
-fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
-    let val = constant(cx, cx.typeck_results(), expr)?.0;
-    if let Constant::Int(const_int) = val {
-        match *cx.typeck_results().expr_ty(expr).kind() {
-            ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
-            ty::Uint(_) => Some(FullInt::U(const_int)),
-            _ => None,
-        }
-    } else {
-        None
-    }
-}
-
-fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
-    if let ExprKind::Cast(ref cast_val, _) = expr.kind {
-        span_lint(
-            cx,
-            INVALID_UPCAST_COMPARISONS,
-            span,
-            &format!(
-                "because of the numeric bounds on `{}` prior to casting, this expression is always {}",
-                snippet(cx, cast_val.span, "the expression"),
-                if always { "true" } else { "false" },
-            ),
-        );
-    }
-}
-
-fn upcast_comparison_bounds_err<'tcx>(
-    cx: &LateContext<'tcx>,
-    span: Span,
-    rel: comparisons::Rel,
-    lhs_bounds: Option<(FullInt, FullInt)>,
-    lhs: &'tcx Expr<'_>,
-    rhs: &'tcx Expr<'_>,
-    invert: bool,
-) {
-    use clippy_utils::comparisons::Rel;
-
-    if let Some((lb, ub)) = lhs_bounds {
-        if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
-            if rel == Rel::Eq || rel == Rel::Ne {
-                if norm_rhs_val < lb || norm_rhs_val > ub {
-                    err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
-                }
-            } else if match rel {
-                Rel::Lt => {
-                    if invert {
-                        norm_rhs_val < lb
-                    } else {
-                        ub < norm_rhs_val
-                    }
-                },
-                Rel::Le => {
-                    if invert {
-                        norm_rhs_val <= lb
-                    } else {
-                        ub <= norm_rhs_val
-                    }
-                },
-                Rel::Eq | Rel::Ne => unreachable!(),
-            } {
-                err_upcast_comparison(cx, span, lhs, true)
-            } else if match rel {
-                Rel::Lt => {
-                    if invert {
-                        norm_rhs_val >= ub
-                    } else {
-                        lb >= norm_rhs_val
-                    }
-                },
-                Rel::Le => {
-                    if invert {
-                        norm_rhs_val > ub
-                    } else {
-                        lb > norm_rhs_val
-                    }
-                },
-                Rel::Eq | Rel::Ne => unreachable!(),
-            } {
-                err_upcast_comparison(cx, span, lhs, false)
-            }
-        }
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind {
-            let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
-            let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
-                val
-            } else {
-                return;
-            };
-
-            let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs);
-            let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs);
-
-            upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false);
-            upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true);
-        }
-    }
-}
-
-declare_clippy_lint! {
-    /// **What it does:** Checks for public `impl` or `fn` missing generalization
-    /// over different hashers and implicitly defaulting to the default hashing
-    /// algorithm (`SipHash`).
-    ///
-    /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be
-    /// used with them.
-    ///
-    /// **Known problems:** Suggestions for replacing constructors can contain
-    /// false-positives. Also applying suggestions can require modification of other
-    /// pieces of code, possibly including external crates.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// # use std::collections::HashMap;
-    /// # use std::hash::{Hash, BuildHasher};
-    /// # trait Serialize {};
-    /// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { }
-    ///
-    /// pub fn foo(map: &mut HashMap<i32, i32>) { }
-    /// ```
-    /// could be rewritten as
-    /// ```rust
-    /// # use std::collections::HashMap;
-    /// # use std::hash::{Hash, BuildHasher};
-    /// # trait Serialize {};
-    /// impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { }
-    ///
-    /// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { }
-    /// ```
-    pub IMPLICIT_HASHER,
-    pedantic,
-    "missing generalization over different hashers"
-}
-
-declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]);
-
-impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
-    #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)]
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        use rustc_span::BytePos;
-
-        fn suggestion<'tcx>(
-            cx: &LateContext<'tcx>,
-            diag: &mut DiagnosticBuilder<'_>,
-            generics_span: Span,
-            generics_suggestion_span: Span,
-            target: &ImplicitHasherType<'_>,
-            vis: ImplicitHasherConstructorVisitor<'_, '_, '_>,
-        ) {
-            let generics_snip = snippet(cx, generics_span, "");
-            // trim `<` `>`
-            let generics_snip = if generics_snip.is_empty() {
-                ""
-            } else {
-                &generics_snip[1..generics_snip.len() - 1]
-            };
-
-            multispan_sugg(
-                diag,
-                "consider adding a type parameter",
-                vec![
-                    (
-                        generics_suggestion_span,
-                        format!(
-                            "<{}{}S: ::std::hash::BuildHasher{}>",
-                            generics_snip,
-                            if generics_snip.is_empty() { "" } else { ", " },
-                            if vis.suggestions.is_empty() {
-                                ""
-                            } else {
-                                // request users to add `Default` bound so that generic constructors can be used
-                                " + Default"
-                            },
-                        ),
-                    ),
-                    (
-                        target.span(),
-                        format!("{}<{}, S>", target.type_name(), target.type_arguments(),),
-                    ),
-                ],
-            );
-
-            if !vis.suggestions.is_empty() {
-                multispan_sugg(diag, "...and use generic constructor", vis.suggestions);
-            }
-        }
-
-        if !cx.access_levels.is_exported(item.hir_id()) {
-            return;
-        }
-
-        match item.kind {
-            ItemKind::Impl(ref impl_) => {
-                let mut vis = ImplicitHasherTypeVisitor::new(cx);
-                vis.visit_ty(impl_.self_ty);
-
-                for target in &vis.found {
-                    if differing_macro_contexts(item.span, target.span()) {
-                        return;
-                    }
-
-                    let generics_suggestion_span = impl_.generics.span.substitute_dummy({
-                        let pos = snippet_opt(cx, item.span.until(target.span()))
-                            .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
-                        if let Some(pos) = pos {
-                            Span::new(pos, pos, item.span.data().ctxt)
-                        } else {
-                            return;
-                        }
-                    });
-
-                    let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
-                    for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
-                        ctr_vis.visit_impl_item(item);
-                    }
-
-                    span_lint_and_then(
-                        cx,
-                        IMPLICIT_HASHER,
-                        target.span(),
-                        &format!(
-                            "impl for `{}` should be generalized over different hashers",
-                            target.type_name()
-                        ),
-                        move |diag| {
-                            suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis);
-                        },
-                    );
-                }
-            },
-            ItemKind::Fn(ref sig, ref generics, body_id) => {
-                let body = cx.tcx.hir().body(body_id);
-
-                for ty in sig.decl.inputs {
-                    let mut vis = ImplicitHasherTypeVisitor::new(cx);
-                    vis.visit_ty(ty);
-
-                    for target in &vis.found {
-                        if in_external_macro(cx.sess(), generics.span) {
-                            continue;
-                        }
-                        let generics_suggestion_span = generics.span.substitute_dummy({
-                            let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span))
-                                .and_then(|snip| {
-                                    let i = snip.find("fn")?;
-                                    Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
-                                })
-                                .expect("failed to create span for type parameters");
-                            Span::new(pos, pos, item.span.data().ctxt)
-                        });
-
-                        let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
-                        ctr_vis.visit_body(body);
-
-                        span_lint_and_then(
-                            cx,
-                            IMPLICIT_HASHER,
-                            target.span(),
-                            &format!(
-                                "parameter of type `{}` should be generalized over different hashers",
-                                target.type_name()
-                            ),
-                            move |diag| {
-                                suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis);
-                            },
-                        );
-                    }
-                }
-            },
-            _ => {},
-        }
-    }
-}
-
-enum ImplicitHasherType<'tcx> {
-    HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>),
-    HashSet(Span, Ty<'tcx>, Cow<'static, str>),
-}
-
-impl<'tcx> ImplicitHasherType<'tcx> {
-    /// Checks that `ty` is a target type without a `BuildHasher`.
-    fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> {
-        if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.kind {
-            let params: Vec<_> = path
-                .segments
-                .last()
-                .as_ref()?
-                .args
-                .as_ref()?
-                .args
-                .iter()
-                .filter_map(|arg| match arg {
-                    GenericArg::Type(ty) => Some(ty),
-                    _ => None,
-                })
-                .collect();
-            let params_len = params.len();
-
-            let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-
-            if is_type_diagnostic_item(cx, ty, sym::hashmap_type) && params_len == 2 {
-                Some(ImplicitHasherType::HashMap(
-                    hir_ty.span,
-                    ty,
-                    snippet(cx, params[0].span, "K"),
-                    snippet(cx, params[1].span, "V"),
-                ))
-            } else if is_type_diagnostic_item(cx, ty, sym::hashset_type) && params_len == 1 {
-                Some(ImplicitHasherType::HashSet(
-                    hir_ty.span,
-                    ty,
-                    snippet(cx, params[0].span, "T"),
-                ))
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }
-
-    fn type_name(&self) -> &'static str {
-        match *self {
-            ImplicitHasherType::HashMap(..) => "HashMap",
-            ImplicitHasherType::HashSet(..) => "HashSet",
-        }
-    }
-
-    fn type_arguments(&self) -> String {
-        match *self {
-            ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v),
-            ImplicitHasherType::HashSet(.., ref t) => format!("{}", t),
-        }
-    }
-
-    fn ty(&self) -> Ty<'tcx> {
-        match *self {
-            ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty,
-        }
-    }
-
-    fn span(&self) -> Span {
-        match *self {
-            ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span,
-        }
-    }
-}
-
-struct ImplicitHasherTypeVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    found: Vec<ImplicitHasherType<'tcx>>,
-}
-
-impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
-    fn new(cx: &'a LateContext<'tcx>) -> Self {
-        Self { cx, found: vec![] }
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) {
-        if let Some(target) = ImplicitHasherType::new(self.cx, t) {
-            self.found.push(target);
-        }
-
-        walk_ty(self, t);
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-}
-
-/// Looks for default-hasher-dependent constructors like `HashMap::new`.
-struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>,
-    target: &'b ImplicitHasherType<'tcx>,
-    suggestions: BTreeMap<Span, String>,
-}
-
-impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
-    fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self {
-        Self {
-            cx,
-            maybe_typeck_results: cx.maybe_typeck_results(),
-            target,
-            suggestions: BTreeMap::new(),
-        }
-    }
-}
-
-impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_body(&mut self, body: &'tcx Body<'_>) {
-        let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id()));
-        walk_body(self, body);
-        self.maybe_typeck_results = old_maybe_typeck_results;
-    }
-
-    fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Call(ref fun, ref args) = e.kind;
-            if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind;
-            if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind;
-            then {
-                if !TyS::same_type(self.target.ty(), self.maybe_typeck_results.unwrap().expr_ty(e)) {
-                    return;
-                }
-
-                if match_path(ty_path, &paths::HASHMAP) {
-                    if method.ident.name == sym::new {
-                        self.suggestions
-                            .insert(e.span, "HashMap::default()".to_string());
-                    } else if method.ident.name == sym!(with_capacity) {
-                        self.suggestions.insert(
-                            e.span,
-                            format!(
-                                "HashMap::with_capacity_and_hasher({}, Default::default())",
-                                snippet(self.cx, args[0].span, "capacity"),
-                            ),
-                        );
-                    }
-                } else if match_path(ty_path, &paths::HASHSET) {
-                    if method.ident.name == sym::new {
-                        self.suggestions
-                            .insert(e.span, "HashSet::default()".to_string());
-                    } else if method.ident.name == sym!(with_capacity) {
-                        self.suggestions.insert(
-                            e.span,
-                            format!(
-                                "HashSet::with_capacity_and_hasher({}, Default::default())",
-                                snippet(self.cx, args[0].span, "capacity"),
-                            ),
-                        );
-                    }
-                }
-            }
-        }
-
-        walk_expr(self, e);
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
-    }
+#[derive(Clone, Copy, Default)]
+struct CheckTyContext {
+    is_in_trait_impl: bool,
+    is_local: bool,
+    is_nested_call: bool,
 }
diff --git a/clippy_lints/src/types/type_complexity.rs b/clippy_lints/src/types/type_complexity.rs
new file mode 100644
index 00000000000..d8c4b67520d
--- /dev/null
+++ b/clippy_lints/src/types/type_complexity.rs
@@ -0,0 +1,79 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_hir as hir;
+use rustc_hir::intravisit::{walk_ty, NestedVisitorMap, Visitor};
+use rustc_hir::{GenericParamKind, TyKind};
+use rustc_lint::LateContext;
+use rustc_middle::hir::map::Map;
+use rustc_target::spec::abi::Abi;
+
+use super::TYPE_COMPLEXITY;
+
+pub(super) fn check(cx: &LateContext<'_>, ty: &hir::Ty<'_>, type_complexity_threshold: u64) -> bool {
+    let score = {
+        let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
+        visitor.visit_ty(ty);
+        visitor.score
+    };
+
+    if score > type_complexity_threshold {
+        span_lint(
+            cx,
+            TYPE_COMPLEXITY,
+            ty.span,
+            "very complex type used. Consider factoring parts into `type` definitions",
+        );
+        true
+    } else {
+        false
+    }
+}
+
+/// Walks a type and assigns a complexity score to it.
+struct TypeComplexityVisitor {
+    /// total complexity score of the type
+    score: u64,
+    /// current nesting level
+    nest: u64,
+}
+
+impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
+    type Map = Map<'tcx>;
+
+    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
+        let (add_score, sub_nest) = match ty.kind {
+            // _, &x and *x have only small overhead; don't mess with nesting level
+            TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0),
+
+            // the "normal" components of a type: named types, arrays/tuples
+            TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1),
+
+            // function types bring a lot of overhead
+            TyKind::BareFn(bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
+
+            TyKind::TraitObject(param_bounds, _, _) => {
+                let has_lifetime_parameters = param_bounds.iter().any(|bound| {
+                    bound
+                        .bound_generic_params
+                        .iter()
+                        .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. }))
+                });
+                if has_lifetime_parameters {
+                    // complex trait bounds like A<'a, 'b>
+                    (50 * self.nest, 1)
+                } else {
+                    // simple trait bounds like A + B
+                    (20 * self.nest, 0)
+                }
+            },
+
+            _ => (0, 0),
+        };
+        self.score += add_score;
+        self.nest += sub_nest;
+        walk_ty(self, ty);
+        self.nest -= sub_nest;
+    }
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+}
diff --git a/clippy_lints/src/types/utils.rs b/clippy_lints/src/types/utils.rs
index 45f891ed718..0fa75f8f0a9 100644
--- a/clippy_lints/src/types/utils.rs
+++ b/clippy_lints/src/types/utils.rs
@@ -7,7 +7,7 @@ use rustc_span::source_map::Span;
 pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
     let last = last_path_segment(qpath);
     if_chain! {
-        if let Some(ref params) = last.args;
+        if let Some(params) = last.args;
         if !params.parenthesized;
         if let Some(ty) = params.args.iter().find_map(|arg| match arg {
             GenericArg::Type(ty) => Some(ty),
diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs
index d2c373db261..7a444174626 100644
--- a/clippy_lints/src/types/vec_box.rs
+++ b/clippy_lints/src/types/vec_box.rs
@@ -22,7 +22,7 @@ pub(super) fn check(
     if cx.tcx.is_diagnostic_item(sym::vec_type, def_id) {
         if_chain! {
             // Get the _ part of Vec<_>
-            if let Some(ref last) = last_path_segment(qpath).args;
+            if let Some(last) = last_path_segment(qpath).args;
             if let Some(ty) = last.args.iter().find_map(|arg| match arg {
                 GenericArg::Type(ty) => Some(ty),
                 _ => None,
@@ -33,7 +33,7 @@ pub(super) fn check(
             if let Some(def_id) = res.opt_def_id();
             if Some(def_id) == cx.tcx.lang_items().owned_box();
             // At this point, we know ty is Box<T>, now get T
-            if let Some(ref last) = last_path_segment(ty_qpath).args;
+            if let Some(last) = last_path_segment(ty_qpath).args;
             if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg {
                 GenericArg::Type(ty) => Some(ty),
                 _ => None,
diff --git a/clippy_lints/src/undropped_manually_drops.rs b/clippy_lints/src/undropped_manually_drops.rs
index b6749069176..f4f5e1233e3 100644
--- a/clippy_lints/src/undropped_manually_drops.rs
+++ b/clippy_lints/src/undropped_manually_drops.rs
@@ -35,7 +35,7 @@ declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]);
 
 impl LateLintPass<'tcx> for UndroppedManuallyDrops {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some(ref args) = match_function_call(cx, expr, &paths::DROP) {
+        if let Some(args) = match_function_call(cx, expr, &paths::DROP) {
             let ty = cx.typeck_results().expr_ty(&args[0]);
             if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop) {
                 span_lint_and_help(
diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs
index 4c13941f665..1c420a50427 100644
--- a/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/clippy_lints/src/unit_return_expecting_ord.rs
@@ -116,8 +116,8 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
         let ty = cx.tcx.erase_late_bound_regions(ret_ty);
         if ty.is_unit();
         then {
+            let body = cx.tcx.hir().body(body_id);
             if_chain! {
-                let body = cx.tcx.hir().body(body_id);
                 if let ExprKind::Block(block, _) = body.value.kind;
                 if block.expr.is_none();
                 if let Some(stmt) = block.stmts.last();
@@ -138,7 +138,7 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
 
 impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind {
+        if let ExprKind::MethodCall(_, _, args, _) = expr.kind {
             let arg_indices = get_args_to_check(cx, expr);
             for (i, trait_name) in arg_indices {
                 if i < args.len() {
diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs
index 8698a718bbd..fad647dfb26 100644
--- a/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/clippy_lints/src/unit_types/let_unit_value.rs
@@ -9,8 +9,8 @@ use rustc_middle::lint::in_external_macro;
 use super::LET_UNIT_VALUE;
 
 pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
-    if let StmtKind::Local(ref local) = stmt.kind {
-        if cx.typeck_results().pat_ty(&local.pat).is_unit() {
+    if let StmtKind::Local(local) = stmt.kind {
+        if cx.typeck_results().pat_ty(local.pat).is_unit() {
             if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() {
                 return;
             }
diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs
index 925ab577099..57be2d2f674 100644
--- a/clippy_lints/src/unit_types/unit_arg.rs
+++ b/clippy_lints/src/unit_types/unit_arg.rs
@@ -19,9 +19,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if is_questionmark_desugar_marked_call(expr) {
         return;
     }
+    let map = &cx.tcx.hir();
+    let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
     if_chain! {
-        let map = &cx.tcx.hir();
-        let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
         if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
         if is_questionmark_desugar_marked_call(parent_expr);
         then {
@@ -54,7 +54,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
 fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool {
     use rustc_span::hygiene::DesugaringKind;
-    if let ExprKind::Call(ref callee, _) = expr.kind {
+    if let ExprKind::Call(callee, _) = expr.kind {
         callee.span.is_desugaring(DesugaringKind::QuestionMark)
     } else {
         false
diff --git a/clippy_lints/src/unit_types/unit_cmp.rs b/clippy_lints/src/unit_types/unit_cmp.rs
index b3077dec5d8..85257f3113c 100644
--- a/clippy_lints/src/unit_types/unit_cmp.rs
+++ b/clippy_lints/src/unit_types/unit_cmp.rs
@@ -9,7 +9,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if expr.span.from_expansion() {
         if let Some(callee) = expr.span.source_callee() {
             if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
-                if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
+                if let ExprKind::Binary(ref cmp, left, _) = expr.kind {
                     let op = cmp.node;
                     if op.is_comparison() && cx.typeck_results().expr_ty(left).is_unit() {
                         let result = match &*symbol.as_str() {
@@ -34,7 +34,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
         return;
     }
 
-    if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
+    if let ExprKind::Binary(ref cmp, left, _) = expr.kind {
         let op = cmp.node;
         if op.is_comparison() && cx.typeck_results().expr_ty(left).is_unit() {
             let result = match op {
diff --git a/clippy_lints/src/unit_types/utils.rs b/clippy_lints/src/unit_types/utils.rs
index 4e194a05e8d..9a3750b2356 100644
--- a/clippy_lints/src/unit_types/utils.rs
+++ b/clippy_lints/src/unit_types/utils.rs
@@ -1,5 +1,5 @@
 use rustc_hir::{Expr, ExprKind};
 
 pub(super) fn is_unit_literal(expr: &Expr<'_>) -> bool {
-    matches!(expr.kind, ExprKind::Tup(ref slice) if slice.is_empty())
+    matches!(expr.kind, ExprKind::Tup(slice) if slice.is_empty())
 }
diff --git a/clippy_lints/src/unnamed_address.rs b/clippy_lints/src/unnamed_address.rs
index d5bc3de6698..9cca05b1f1a 100644
--- a/clippy_lints/src/unnamed_address.rs
+++ b/clippy_lints/src/unnamed_address.rs
@@ -77,7 +77,7 @@ impl LateLintPass<'_> for UnnamedAddress {
         }
 
         if_chain! {
-            if let ExprKind::Binary(binop, ref left, ref right) = expr.kind;
+            if let ExprKind::Binary(binop, left, right) = expr.kind;
             if is_comparison(binop.node);
             if is_trait_ptr(cx, left) && is_trait_ptr(cx, right);
             then {
@@ -93,7 +93,7 @@ impl LateLintPass<'_> for UnnamedAddress {
         }
 
         if_chain! {
-            if let ExprKind::Call(ref func, [ref _left, ref _right]) = expr.kind;
+            if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind;
             if let ExprKind::Path(ref func_qpath) = func.kind;
             if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
             if match_def_path(cx, def_id, &paths::PTR_EQ) ||
@@ -114,10 +114,10 @@ impl LateLintPass<'_> for UnnamedAddress {
         }
 
         if_chain! {
-            if let ExprKind::Binary(binop, ref left, ref right) = expr.kind;
+            if let ExprKind::Binary(binop, left, right) = expr.kind;
             if is_comparison(binop.node);
-            if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr() &&
-                cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr();
+            if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr();
+            if cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr();
             if is_fn_def(cx, left) || is_fn_def(cx, right);
             then {
                 span_lint(
diff --git a/clippy_lints/src/unnecessary_sort_by.rs b/clippy_lints/src/unnecessary_sort_by.rs
index 6becff9662a..347d858b640 100644
--- a/clippy_lints/src/unnecessary_sort_by.rs
+++ b/clippy_lints/src/unnecessary_sort_by.rs
@@ -81,9 +81,8 @@ fn mirrored_exprs(
         },
         // Two arrays with mirrored contents
         (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
-            iter::zip(*left_exprs, *right_exprs)
-                .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-        }
+            iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
+        },
         // The two exprs are function calls.
         // Check to see that the function itself and its arguments are mirrored
         (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => {
@@ -101,12 +100,11 @@ fn mirrored_exprs(
             left_segment.ident == right_segment.ident
                 && iter::zip(*left_args, *right_args)
                     .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-        }
+        },
         // Two tuples with mirrored contents
         (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => {
-            iter::zip(*left_exprs, *right_exprs)
-                .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-        }
+            iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
+        },
         // Two binary ops, which are the same operation and which have mirrored arguments
         (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => {
             left_op.node == right_op.node
@@ -143,8 +141,7 @@ fn mirrored_exprs(
                 },
             )),
         ) => {
-            (iter::zip(*left_segments, *right_segments)
-                .all(|(left, right)| left.ident == right.ident)
+            (iter::zip(*left_segments, *right_segments).all(|(left, right)| left.ident == right.ident)
                 && left_segments
                     .iter()
                     .all(|seg| &seg.ident != a_ident && &seg.ident != b_ident))
@@ -182,15 +179,15 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
         if method_path.ident.name == sym::cmp;
         then {
             let (closure_body, closure_arg, reverse) = if mirrored_exprs(
-                &cx,
-                &left_expr,
-                &left_ident,
-                &right_expr,
-                &right_ident
+                cx,
+                left_expr,
+                left_ident,
+                right_expr,
+                right_ident
             ) {
-                (Sugg::hir(cx, &left_expr, "..").to_string(), left_ident.name.to_string(), false)
-            } else if mirrored_exprs(&cx, &left_expr, &right_ident, &right_expr, &left_ident) {
-                (Sugg::hir(cx, &left_expr, "..").to_string(), right_ident.name.to_string(), true)
+                (Sugg::hir(cx, left_expr, "..").to_string(), left_ident.name.to_string(), false)
+            } else if mirrored_exprs(cx, left_expr, right_ident, right_expr, left_ident) {
+                (Sugg::hir(cx, left_expr, "..").to_string(), right_ident.name.to_string(), true)
             } else {
                 return None;
             };
diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs
index c2be457e9dc..5bb417cb1be 100644
--- a/clippy_lints/src/unnecessary_wraps.rs
+++ b/clippy_lints/src/unnecessary_wraps.rs
@@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
             if_chain! {
                 if !in_macro(ret_expr.span);
                 // Check if a function call.
-                if let ExprKind::Call(ref func, ref args) = ret_expr.kind;
+                if let ExprKind::Call(func, args) = ret_expr.kind;
                 // Get the Path of the function call.
                 if let ExprKind::Path(ref qpath) = func.kind;
                 // Check if OPTION_SOME or RESULT_OK, depending on return type.
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index 2b9479365c6..9376a2cf66a 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -1,15 +1,19 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
-use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::over;
+use clippy_utils::{
+    ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path},
+    meets_msrv,
+};
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, Pat, PatKind, PatKind::*, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::DUMMY_SP;
 
 use std::cell::Cell;
@@ -50,26 +54,50 @@ declare_clippy_lint! {
     "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`"
 }
 
-declare_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]);
+const UNNESTED_OR_PATTERNS_MSRV: RustcVersion = RustcVersion::new(1, 53, 0);
+
+#[derive(Clone, Copy)]
+pub struct UnnestedOrPatterns {
+    msrv: Option<RustcVersion>,
+}
+
+impl UnnestedOrPatterns {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]);
 
 impl EarlyLintPass for UnnestedOrPatterns {
     fn check_arm(&mut self, cx: &EarlyContext<'_>, a: &ast::Arm) {
-        lint_unnested_or_patterns(cx, &a.pat);
+        if meets_msrv(self.msrv.as_ref(), &UNNESTED_OR_PATTERNS_MSRV) {
+            lint_unnested_or_patterns(cx, &a.pat);
+        }
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
-        if let ast::ExprKind::Let(pat, _) = &e.kind {
-            lint_unnested_or_patterns(cx, pat);
+        if meets_msrv(self.msrv.as_ref(), &UNNESTED_OR_PATTERNS_MSRV) {
+            if let ast::ExprKind::Let(pat, _) = &e.kind {
+                lint_unnested_or_patterns(cx, pat);
+            }
         }
     }
 
     fn check_param(&mut self, cx: &EarlyContext<'_>, p: &ast::Param) {
-        lint_unnested_or_patterns(cx, &p.pat);
+        if meets_msrv(self.msrv.as_ref(), &UNNESTED_OR_PATTERNS_MSRV) {
+            lint_unnested_or_patterns(cx, &p.pat);
+        }
     }
 
     fn check_local(&mut self, cx: &EarlyContext<'_>, l: &ast::Local) {
-        lint_unnested_or_patterns(cx, &l.pat);
+        if meets_msrv(self.msrv.as_ref(), &UNNESTED_OR_PATTERNS_MSRV) {
+            lint_unnested_or_patterns(cx, &l.pat);
+        }
     }
+
+    extract_msrv_attr!(EarlyContext);
 }
 
 fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index 9990052e114..024ab03fd41 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/clippy_lints/src/unused_io_amount.rs
@@ -36,13 +36,13 @@ declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]);
 impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
     fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
         let expr = match s.kind {
-            hir::StmtKind::Semi(ref expr) | hir::StmtKind::Expr(ref expr) => &**expr,
+            hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr,
             _ => return,
         };
 
         match expr.kind {
-            hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => {
-                if let hir::ExprKind::Call(ref func, ref args) = res.kind {
+            hir::ExprKind::Match(res, _, _) if is_try(expr).is_some() => {
+                if let hir::ExprKind::Call(func, args) = res.kind {
                     if matches!(
                         func.kind,
                         hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _))
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
                 }
             },
 
-            hir::ExprKind::MethodCall(ref path, _, ref args, _) => match &*path.ident.as_str() {
+            hir::ExprKind::MethodCall(path, _, args, _) => match &*path.ident.as_str() {
                 "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
                     check_method_call(cx, &args[0], expr);
                 },
@@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
 }
 
 fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
-    if let hir::ExprKind::MethodCall(ref path, _, _, _) = call.kind {
+    if let hir::ExprKind::MethodCall(path, _, _, _) = call.kind {
         let symbol = &*path.ident.as_str();
         let read_trait = match_trait_method(cx, call, &paths::IO_READ);
         let write_trait = match_trait_method(cx, call, &paths::IO_WRITE);
diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs
index aef4ce75915..15343cf90f2 100644
--- a/clippy_lints/src/unused_self.rs
+++ b/clippy_lints/src/unused_self.rs
@@ -49,21 +49,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             if assoc_item.fn_has_self_parameter;
             if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
             let body = cx.tcx.hir().body(*body_id);
-            if !body.params.is_empty();
+            if let [self_param, ..] = body.params;
+            let self_hir_id = self_param.pat.hir_id;
+            if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body);
             then {
-                let self_param = &body.params[0];
-                let self_hir_id = self_param.pat.hir_id;
-                if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body) {
-                    span_lint_and_help(
-                        cx,
-                        UNUSED_SELF,
-                        self_param.span,
-                        "unused `self` argument",
-                        None,
-                        "consider refactoring to a associated function",
-                    );
-                    return;
-                }
+                span_lint_and_help(
+                    cx,
+                    UNUSED_SELF,
+                    self_param.span,
+                    "unused `self` argument",
+                    None,
+                    "consider refactoring to a associated function",
+                );
             }
         }
     }
diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs
index 329ea49024b..ce2d0b3ab2f 100644
--- a/clippy_lints/src/unused_unit.rs
+++ b/clippy_lints/src/unused_unit.rs
@@ -45,7 +45,7 @@ impl EarlyLintPass for UnusedUnit {
 
     fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
         if_chain! {
-            if let Some(ref stmt) = block.stmts.last();
+            if let Some(stmt) = block.stmts.last();
             if let ast::StmtKind::Expr(ref expr) = stmt.kind;
             if is_unit_expr(expr) && !stmt.span.from_expansion();
             then {
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index fb29acca18a..d4efee56eff 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -166,8 +166,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
         } else {
             // find `unwrap[_err]()` calls:
             if_chain! {
-                if let ExprKind::MethodCall(ref method_name, _, ref args, _) = expr.kind;
-                if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].kind;
+                if let ExprKind::MethodCall(method_name, _, args, _) = expr.kind;
+                if let ExprKind::Path(QPath::Resolved(None, path)) = args[0].kind;
                 if [sym::unwrap, sym!(unwrap_err)].contains(&method_name.ident.name);
                 let call_to_unwrap = method_name.ident.name == sym::unwrap;
                 if let Some(unwrappable) = self.unwrappables.iter()
diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs
index 0d745813beb..d17aa6d8424 100644
--- a/clippy_lints/src/unwrap_in_result.rs
+++ b/clippy_lints/src/unwrap_in_result.rs
@@ -110,31 +110,27 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> {
 }
 
 fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
-    if_chain! {
+    if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
+        let body = cx.tcx.hir().body(body_id);
+        let mut fpu = FindExpectUnwrap {
+            lcx: cx,
+            typeck_results: cx.tcx.typeck(impl_item.def_id),
+            result: Vec::new(),
+        };
+        fpu.visit_expr(&body.value);
 
-        if let ImplItemKind::Fn(_, body_id) = impl_item.kind;
-        then {
-            let body = cx.tcx.hir().body(body_id);
-            let mut fpu = FindExpectUnwrap {
-                lcx: cx,
-                typeck_results: cx.tcx.typeck(impl_item.def_id),
-                result: Vec::new(),
-            };
-            fpu.visit_expr(&body.value);
-
-            // if we've found one, lint
-            if  !fpu.result.is_empty()  {
-                span_lint_and_then(
-                    cx,
-                    UNWRAP_IN_RESULT,
-                    impl_span,
-                    "used unwrap or expect in a function that returns result or option",
-                    move |diag| {
-                        diag.help(
-                            "unwrap and expect should not be used in a function that returns result or option" );
-                        diag.span_note(fpu.result, "potential non-recoverable error(s)");
-                    });
-            }
+        // if we've found one, lint
+        if !fpu.result.is_empty() {
+            span_lint_and_then(
+                cx,
+                UNWRAP_IN_RESULT,
+                impl_span,
+                "used unwrap or expect in a function that returns result or option",
+                move |diag| {
+                    diag.help("unwrap and expect should not be used in a function that returns result or option");
+                    diag.span_note(fpu.result, "potential non-recoverable error(s)");
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/upper_case_acronyms.rs b/clippy_lints/src/upper_case_acronyms.rs
index a6d29d36862..4ac2ec55b98 100644
--- a/clippy_lints/src/upper_case_acronyms.rs
+++ b/clippy_lints/src/upper_case_acronyms.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use if_chain::if_chain;
 use itertools::Itertools;
-use rustc_ast::ast::{Item, ItemKind, Variant, VisibilityKind};
+use rustc_ast::ast::{Item, ItemKind, VisibilityKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -99,21 +98,21 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) {
 
 impl EarlyLintPass for UpperCaseAcronyms {
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) {
-        if_chain! {
-            if !in_external_macro(cx.sess(), it.span);
+        // do not lint public items or in macros
+        if !in_external_macro(cx.sess(), it.span) && !matches!(it.vis.kind, VisibilityKind::Public) {
             if matches!(
                 it.kind,
-                ItemKind::TyAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..)
-            );
-            // do not lint public items
-            if !matches!(it.vis.kind, VisibilityKind::Public);
-            then {
+                ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..)
+            ) {
                 check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
+            } else if let ItemKind::Enum(ref enumdef, _) = it.kind {
+                // check enum variants seperately because again we only want to lint on private enums and
+                // the fn check_variant does not know about the vis of the enum of its variants
+                enumdef
+                    .variants
+                    .iter()
+                    .for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive));
             }
         }
     }
-
-    fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &Variant) {
-        check_ident(cx, &v.ident, self.upper_case_acronyms_aggressive);
-    }
 }
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index 116cb8b1e1c..c6a3c58a9a2 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
                 of_trait,
                 ..
             }) => {
-                let should_check = if let TyKind::Path(QPath::Resolved(_, ref item_path)) = hir_self_ty.kind {
+                let should_check = if let TyKind::Path(QPath::Resolved(_, item_path)) = hir_self_ty.kind {
                     let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
                     parameters.as_ref().map_or(true, |params| {
                         !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
@@ -197,7 +197,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
                 for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
                     if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
                         let mut visitor = SkipTyCollector::default();
-                        visitor.visit_ty(&impl_hir_ty);
+                        visitor.visit_ty(impl_hir_ty);
                         types_to_skip.extend(visitor.types_to_skip);
                     }
                 }
@@ -333,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
                 // unit enum variants (`Enum::A`)
                 ExprKind::Path(qpath) => {
                     if expr_ty_matches(cx, expr, self_ty) {
-                        span_lint_on_qpath_resolved(cx, &qpath, true);
+                        span_lint_on_qpath_resolved(cx, qpath, true);
                     }
                 },
                 _ => (),
diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs
index 3e1b69e676b..7edb280be73 100644
--- a/clippy_lints/src/useless_conversion.rs
+++ b/clippy_lints/src/useless_conversion.rs
@@ -53,17 +53,17 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
         }
 
         match e.kind {
-            ExprKind::Match(_, ref arms, MatchSource::TryDesugar) => {
+            ExprKind::Match(_, arms, MatchSource::TryDesugar) => {
                 let e = match arms[0].body.kind {
-                    ExprKind::Ret(Some(ref e)) | ExprKind::Break(_, Some(ref e)) => e,
+                    ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e)) => e,
                     _ => return,
                 };
-                if let ExprKind::Call(_, ref args) = e.kind {
+                if let ExprKind::Call(_, args) = e.kind {
                     self.try_desugar_arm.push(args[0].hir_id);
                 }
             },
 
-            ExprKind::MethodCall(ref name, .., ref args, _) => {
+            ExprKind::MethodCall(name, .., args, _) => {
                 if match_trait_method(cx, e, &paths::INTO) && &*name.ident.as_str() == "into" {
                     let a = cx.typeck_results().expr_ty(e);
                     let b = cx.typeck_results().expr_ty(&args[0]);
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                 }
                 if match_trait_method(cx, e, &paths::INTO_ITERATOR) && name.ident.name == sym::into_iter {
                     if let Some(parent_expr) = get_parent_expr(cx, e) {
-                        if let ExprKind::MethodCall(ref parent_name, ..) = parent_expr.kind {
+                        if let ExprKind::MethodCall(parent_name, ..) = parent_expr.kind {
                             if parent_name.ident.name != sym::into_iter {
                                 return;
                             }
@@ -103,38 +103,35 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         );
                     }
                 }
-                if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into" {
-                    if_chain! {
-                        let a = cx.typeck_results().expr_ty(e);
-                        let b = cx.typeck_results().expr_ty(&args[0]);
-                        if is_type_diagnostic_item(cx, a, sym::result_type);
-                        if let ty::Adt(_, substs) = a.kind();
-                        if let Some(a_type) = substs.types().next();
-                        if TyS::same_type(a_type, b);
-
-                        then {
-                            span_lint_and_help(
-                                cx,
-                                USELESS_CONVERSION,
-                                e.span,
-                                &format!("useless conversion to the same type: `{}`", b),
-                                None,
-                                "consider removing `.try_into()`",
-                            );
-                        }
+                if_chain! {
+                    if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into";
+                    let a = cx.typeck_results().expr_ty(e);
+                    let b = cx.typeck_results().expr_ty(&args[0]);
+                    if is_type_diagnostic_item(cx, a, sym::result_type);
+                    if let ty::Adt(_, substs) = a.kind();
+                    if let Some(a_type) = substs.types().next();
+                    if TyS::same_type(a_type, b);
+                    then {
+                        span_lint_and_help(
+                            cx,
+                            USELESS_CONVERSION,
+                            e.span,
+                            &format!("useless conversion to the same type: `{}`", b),
+                            None,
+                            "consider removing `.try_into()`",
+                        );
                     }
                 }
             },
 
-            ExprKind::Call(ref path, ref args) => {
+            ExprKind::Call(path, args) => {
                 if_chain! {
                     if args.len() == 1;
                     if let ExprKind::Path(ref qpath) = path.kind;
                     if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
-                    let a = cx.typeck_results().expr_ty(e);
-                    let b = cx.typeck_results().expr_ty(&args[0]);
-
                     then {
+                        let a = cx.typeck_results().expr_ty(e);
+                        let b = cx.typeck_results().expr_ty(&args[0]);
                         if_chain! {
                             if match_def_path(cx, def_id, &paths::TRY_FROM);
                             if is_type_diagnostic_item(cx, a, sym::result_type);
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index a92c987014f..e70f8a09ebe 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -203,13 +203,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
         print!("    if let ExprKind::");
         let current = format!("{}.kind", self.current);
         match expr.kind {
-            ExprKind::Box(ref inner) => {
+            ExprKind::Box(inner) => {
                 let inner_pat = self.next("inner");
                 println!("Box(ref {}) = {};", inner_pat, current);
                 self.current = inner_pat;
                 self.visit_expr(inner);
             },
-            ExprKind::Array(ref elements) => {
+            ExprKind::Array(elements) => {
                 let elements_pat = self.next("elements");
                 println!("Array(ref {}) = {};", elements_pat, current);
                 println!("    if {}.len() == {};", elements_pat, elements.len());
@@ -218,7 +218,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     self.visit_expr(element);
                 }
             },
-            ExprKind::Call(ref func, ref args) => {
+            ExprKind::Call(func, args) => {
                 let func_pat = self.next("func");
                 let args_pat = self.next("args");
                 println!("Call(ref {}, ref {}) = {};", func_pat, args_pat, current);
@@ -230,14 +230,14 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     self.visit_expr(arg);
                 }
             },
-            ExprKind::MethodCall(ref _method_name, ref _generics, ref _args, ref _fn_span) => {
+            ExprKind::MethodCall(_method_name, ref _generics, _args, ref _fn_span) => {
                 println!(
                     "MethodCall(ref method_name, ref generics, ref args, ref fn_span) = {};",
                     current
                 );
                 println!("    // unimplemented: `ExprKind::MethodCall` is not further destructured at the moment");
             },
-            ExprKind::Tup(ref elements) => {
+            ExprKind::Tup(elements) => {
                 let elements_pat = self.next("elements");
                 println!("Tup(ref {}) = {};", elements_pat, current);
                 println!("    if {}.len() == {};", elements_pat, elements.len());
@@ -246,7 +246,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     self.visit_expr(element);
                 }
             },
-            ExprKind::Binary(ref op, ref left, ref right) => {
+            ExprKind::Binary(ref op, left, right) => {
                 let op_pat = self.next("op");
                 let left_pat = self.next("left");
                 let right_pat = self.next("right");
@@ -260,7 +260,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = right_pat;
                 self.visit_expr(right);
             },
-            ExprKind::Unary(ref op, ref inner) => {
+            ExprKind::Unary(ref op, inner) => {
                 let inner_pat = self.next("inner");
                 println!("Unary(UnOp::{:?}, ref {}) = {};", op, inner_pat, current);
                 self.current = inner_pat;
@@ -296,7 +296,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     },
                 }
             },
-            ExprKind::Cast(ref expr, ref ty) => {
+            ExprKind::Cast(expr, ty) => {
                 let cast_pat = self.next("expr");
                 let cast_ty = self.next("cast_ty");
                 let qp_label = self.next("qp");
@@ -310,13 +310,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = cast_pat;
                 self.visit_expr(expr);
             },
-            ExprKind::Type(ref expr, ref _ty) => {
+            ExprKind::Type(expr, _ty) => {
                 let cast_pat = self.next("expr");
                 println!("Type(ref {}, _) = {};", cast_pat, current);
                 self.current = cast_pat;
                 self.visit_expr(expr);
             },
-            ExprKind::Loop(ref body, _, desugaring, _) => {
+            ExprKind::Loop(body, _, desugaring, _) => {
                 let body_pat = self.next("body");
                 let des = loop_desugaring_name(desugaring);
                 let label_pat = self.next("label");
@@ -324,10 +324,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = body_pat;
                 self.visit_block(body);
             },
-            ExprKind::If(ref cond, ref then, ref opt_else) => {
+            ExprKind::If(cond, then, ref opt_else) => {
                 let cond_pat = self.next("cond");
                 let then_pat = self.next("then");
-                if let Some(ref else_) = *opt_else {
+                if let Some(else_) = *opt_else {
                     let else_pat = self.next("else_");
                     println!(
                         "If(ref {}, ref {}, Some(ref {})) = {};",
@@ -343,7 +343,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = then_pat;
                 self.visit_expr(then);
             },
-            ExprKind::Match(ref expr, ref arms, desugaring) => {
+            ExprKind::Match(expr, arms, desugaring) => {
                 let des = desugaring_name(desugaring);
                 let expr_pat = self.next("expr");
                 let arms_pat = self.next("arms");
@@ -353,18 +353,18 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 println!("    if {}.len() == {};", arms_pat, arms.len());
                 for (i, arm) in arms.iter().enumerate() {
                     self.current = format!("{}[{}].body", arms_pat, i);
-                    self.visit_expr(&arm.body);
+                    self.visit_expr(arm.body);
                     if let Some(ref guard) = arm.guard {
                         let guard_pat = self.next("guard");
                         println!("    if let Some(ref {}) = {}[{}].guard;", guard_pat, arms_pat, i);
                         match guard {
-                            hir::Guard::If(ref if_expr) => {
+                            hir::Guard::If(if_expr) => {
                                 let if_expr_pat = self.next("expr");
                                 println!("    if let Guard::If(ref {}) = {};", if_expr_pat, guard_pat);
                                 self.current = if_expr_pat;
                                 self.visit_expr(if_expr);
                             },
-                            hir::Guard::IfLet(ref if_let_pat, ref if_let_expr) => {
+                            hir::Guard::IfLet(if_let_pat, if_let_expr) => {
                                 let if_let_pat_pat = self.next("pat");
                                 let if_let_expr_pat = self.next("expr");
                                 println!(
@@ -379,26 +379,26 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                         }
                     }
                     self.current = format!("{}[{}].pat", arms_pat, i);
-                    self.visit_pat(&arm.pat);
+                    self.visit_pat(arm.pat);
                 }
             },
-            ExprKind::Closure(ref _capture_clause, ref _func, _, _, _) => {
+            ExprKind::Closure(ref _capture_clause, _func, _, _, _) => {
                 println!("Closure(ref capture_clause, ref func, _, _, _) = {};", current);
                 println!("    // unimplemented: `ExprKind::Closure` is not further destructured at the moment");
             },
-            ExprKind::Yield(ref sub, _) => {
+            ExprKind::Yield(sub, _) => {
                 let sub_pat = self.next("sub");
                 println!("Yield(ref sub) = {};", current);
                 self.current = sub_pat;
                 self.visit_expr(sub);
             },
-            ExprKind::Block(ref block, _) => {
+            ExprKind::Block(block, _) => {
                 let block_pat = self.next("block");
                 println!("Block(ref {}) = {};", block_pat, current);
                 self.current = block_pat;
                 self.visit_block(block);
             },
-            ExprKind::Assign(ref target, ref value, _) => {
+            ExprKind::Assign(target, value, _) => {
                 let target_pat = self.next("target");
                 let value_pat = self.next("value");
                 println!(
@@ -410,7 +410,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = value_pat;
                 self.visit_expr(value);
             },
-            ExprKind::AssignOp(ref op, ref target, ref value) => {
+            ExprKind::AssignOp(ref op, target, value) => {
                 let op_pat = self.next("op");
                 let target_pat = self.next("target");
                 let value_pat = self.next("value");
@@ -424,7 +424,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = value_pat;
                 self.visit_expr(value);
             },
-            ExprKind::Field(ref object, ref field_ident) => {
+            ExprKind::Field(object, ref field_ident) => {
                 let obj_pat = self.next("object");
                 let field_name_pat = self.next("field_name");
                 println!("Field(ref {}, ref {}) = {};", obj_pat, field_name_pat, current);
@@ -432,7 +432,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = obj_pat;
                 self.visit_expr(object);
             },
-            ExprKind::Index(ref object, ref index) => {
+            ExprKind::Index(object, index) => {
                 let object_pat = self.next("object");
                 let index_pat = self.next("index");
                 println!("Index(ref {}, ref {}) = {};", object_pat, index_pat, current);
@@ -447,7 +447,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = path_pat;
                 self.print_qpath(path);
             },
-            ExprKind::AddrOf(kind, mutability, ref inner) => {
+            ExprKind::AddrOf(kind, mutability, inner) => {
                 let inner_pat = self.next("inner");
                 println!(
                     "AddrOf(BorrowKind::{:?}, Mutability::{:?}, ref {}) = {};",
@@ -458,7 +458,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
             },
             ExprKind::Break(ref _destination, ref opt_value) => {
                 let destination_pat = self.next("destination");
-                if let Some(ref value) = *opt_value {
+                if let Some(value) = *opt_value {
                     let value_pat = self.next("value");
                     println!("Break(ref {}, Some(ref {})) = {};", destination_pat, value_pat, current);
                     self.current = value_pat;
@@ -474,7 +474,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 // FIXME: implement label printing
             },
             ExprKind::Ret(ref opt_value) => {
-                if let Some(ref value) = *opt_value {
+                if let Some(value) = *opt_value {
                     let value_pat = self.next("value");
                     println!("Ret(Some(ref {})) = {};", value_pat, current);
                     self.current = value_pat;
@@ -491,10 +491,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 println!("LlvmInlineAsm(_) = {};", current);
                 println!("    // unimplemented: `ExprKind::LlvmInlineAsm` is not further destructured at the moment");
             },
-            ExprKind::Struct(ref path, ref fields, ref opt_base) => {
+            ExprKind::Struct(path, fields, ref opt_base) => {
                 let path_pat = self.next("path");
                 let fields_pat = self.next("fields");
-                if let Some(ref base) = *opt_base {
+                if let Some(base) = *opt_base {
                     let base_pat = self.next("base");
                     println!(
                         "Struct(ref {}, ref {}, Some(ref {})) = {};",
@@ -516,7 +516,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = value_pat;
             },
             // FIXME: compute length (needs type info)
-            ExprKind::Repeat(ref value, _) => {
+            ExprKind::Repeat(value, _) => {
                 let value_pat = self.next("value");
                 println!("Repeat(ref {}, _) = {};", value_pat, current);
                 println!("// unimplemented: repeat count check");
@@ -526,7 +526,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
             ExprKind::Err => {
                 println!("Err = {}", current);
             },
-            ExprKind::DropTemps(ref expr) => {
+            ExprKind::DropTemps(expr) => {
                 let expr_pat = self.next("expr");
                 println!("DropTemps(ref {}) = {};", expr_pat, current);
                 self.current = expr_pat;
@@ -560,7 +560,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     BindingAnnotation::RefMut => "BindingAnnotation::RefMut",
                 };
                 let name_pat = self.next("name");
-                if let Some(ref sub) = *sub {
+                if let Some(sub) = *sub {
                     let sub_pat = self.next("sub");
                     println!(
                         "Binding({}, _, {}, Some(ref {})) = {};",
@@ -573,7 +573,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 }
                 println!("    if {}.as_str() == \"{}\";", name_pat, ident.as_str());
             },
-            PatKind::Struct(ref path, ref fields, ignore) => {
+            PatKind::Struct(ref path, fields, ignore) => {
                 let path_pat = self.next("path");
                 let fields_pat = self.next("fields");
                 println!(
@@ -585,13 +585,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 println!("    if {}.len() == {};", fields_pat, fields.len());
                 println!("    // unimplemented: field checks");
             },
-            PatKind::Or(ref fields) => {
+            PatKind::Or(fields) => {
                 let fields_pat = self.next("fields");
                 println!("Or(ref {}) = {};", fields_pat, current);
                 println!("    if {}.len() == {};", fields_pat, fields.len());
                 println!("    // unimplemented: field checks");
             },
-            PatKind::TupleStruct(ref path, ref fields, skip_pos) => {
+            PatKind::TupleStruct(ref path, fields, skip_pos) => {
                 let path_pat = self.next("path");
                 let fields_pat = self.next("fields");
                 println!(
@@ -609,25 +609,25 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = path_pat;
                 self.print_qpath(path);
             },
-            PatKind::Tuple(ref fields, skip_pos) => {
+            PatKind::Tuple(fields, skip_pos) => {
                 let fields_pat = self.next("fields");
                 println!("Tuple(ref {}, {:?}) = {};", fields_pat, skip_pos, current);
                 println!("    if {}.len() == {};", fields_pat, fields.len());
                 println!("    // unimplemented: field checks");
             },
-            PatKind::Box(ref pat) => {
+            PatKind::Box(pat) => {
                 let pat_pat = self.next("pat");
                 println!("Box(ref {}) = {};", pat_pat, current);
                 self.current = pat_pat;
                 self.visit_pat(pat);
             },
-            PatKind::Ref(ref pat, muta) => {
+            PatKind::Ref(pat, muta) => {
                 let pat_pat = self.next("pat");
                 println!("Ref(ref {}, Mutability::{:?}) = {};", pat_pat, muta, current);
                 self.current = pat_pat;
                 self.visit_pat(pat);
             },
-            PatKind::Lit(ref lit_expr) => {
+            PatKind::Lit(lit_expr) => {
                 let lit_expr_pat = self.next("lit_expr");
                 println!("Lit(ref {}) = {}", lit_expr_pat, current);
                 self.current = lit_expr_pat;
@@ -645,10 +645,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                 self.current = end_pat;
                 walk_list!(self, visit_expr, end);
             },
-            PatKind::Slice(ref start, ref middle, ref end) => {
+            PatKind::Slice(start, ref middle, end) => {
                 let start_pat = self.next("start");
                 let end_pat = self.next("end");
-                if let Some(ref middle) = middle {
+                if let Some(middle) = middle {
                     let middle_pat = self.next("middle");
                     println!(
                         "Slice(ref {}, Some(ref {}), ref {}) = {};",
@@ -678,17 +678,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
         let current = format!("{}.kind", self.current);
         match s.kind {
             // A local (let) binding:
-            StmtKind::Local(ref local) => {
+            StmtKind::Local(local) => {
                 let local_pat = self.next("local");
                 println!("Local(ref {}) = {};", local_pat, current);
-                if let Some(ref init) = local.init {
+                if let Some(init) = local.init {
                     let init_pat = self.next("init");
                     println!("    if let Some(ref {}) = {}.init;", init_pat, local_pat);
                     self.current = init_pat;
                     self.visit_expr(init);
                 }
                 self.current = format!("{}.pat", local_pat);
-                self.visit_pat(&local.pat);
+                self.visit_pat(local.pat);
             },
             // An item binding:
             StmtKind::Item(_) => {
@@ -696,7 +696,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
             },
 
             // Expr without trailing semi-colon (must have unit type):
-            StmtKind::Expr(ref e) => {
+            StmtKind::Expr(e) => {
                 let e_pat = self.next("e");
                 println!("Expr(ref {}, _) = {}", e_pat, current);
                 self.current = e_pat;
@@ -704,7 +704,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
             },
 
             // Expr with trailing semi-colon (may have any type):
-            StmtKind::Semi(ref e) => {
+            StmtKind::Semi(e) => {
                 let e_pat = self.next("e");
                 println!("Semi(ref {}, _) = {}", e_pat, current);
                 self.current = e_pat;
@@ -752,7 +752,7 @@ fn loop_desugaring_name(des: hir::LoopSource) -> &'static str {
 
 fn print_path(path: &QPath<'_>, first: &mut bool) {
     match *path {
-        QPath::Resolved(_, ref path) => {
+        QPath::Resolved(_, path) => {
             for segment in path.segments {
                 if *first {
                     *first = false;
@@ -762,7 +762,7 @@ fn print_path(path: &QPath<'_>, first: &mut bool) {
                 print!("{:?}", segment.ident.as_str());
             }
         },
-        QPath::TypeRelative(ref ty, ref segment) => match ty.kind {
+        QPath::TypeRelative(ty, segment) => match ty.kind {
             hir::TyKind::Path(ref inner_path) => {
                 print_path(inner_path, first);
                 if *first {
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index 9139a0966c5..147f823491d 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -106,7 +106,7 @@ macro_rules! define_Conf {
 
 pub use self::helpers::Conf;
 define_Conf! {
-    /// Lint: REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN. The minimum rust version that the project supports
+    /// Lint: REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, NEEDLESS_QUESTION_MARK, PTR_AS_PTR. The minimum rust version that the project supports
     (msrv, "msrv": Option<String>, None),
     /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
     (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs
index b3fe66ed428..4665eeeff7b 100644
--- a/clippy_lints/src/utils/inspector.rs
+++ b/clippy_lints/src/utils/inspector.rs
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector {
         match item.vis.node {
             hir::VisibilityKind::Public => println!("public"),
             hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
-            hir::VisibilityKind::Restricted { ref path, .. } => println!(
+            hir::VisibilityKind::Restricted { path, .. } => println!(
                 "visible in module `{}`",
                 rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false))
             ),
@@ -99,13 +99,13 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector {
         if !has_attr(cx.sess(), cx.tcx.hir().attrs(arm.hir_id)) {
             return;
         }
-        print_pat(cx, &arm.pat, 1);
+        print_pat(cx, arm.pat, 1);
         if let Some(ref guard) = arm.guard {
             println!("guard:");
             print_guard(cx, guard, 1);
         }
         println!("body:");
-        print_expr(cx, &arm.body, 1);
+        print_expr(cx, arm.body, 1);
     }
 
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) {
@@ -113,17 +113,17 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector {
             return;
         }
         match stmt.kind {
-            hir::StmtKind::Local(ref local) => {
+            hir::StmtKind::Local(local) => {
                 println!("local variable of type {}", cx.typeck_results().node_type(local.hir_id));
                 println!("pattern:");
-                print_pat(cx, &local.pat, 0);
-                if let Some(ref e) = local.init {
+                print_pat(cx, local.pat, 0);
+                if let Some(e) = local.init {
                     println!("init expression:");
                     print_expr(cx, e, 0);
                 }
             },
             hir::StmtKind::Item(_) => println!("item decl"),
-            hir::StmtKind::Expr(ref e) | hir::StmtKind::Semi(ref e) => print_expr(cx, e, 0),
+            hir::StmtKind::Expr(e) | hir::StmtKind::Semi(e) => print_expr(cx, e, 0),
         }
     }
     // fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx
@@ -151,7 +151,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
         cx.typeck_results().adjustments().get(expr.hir_id)
     );
     match expr.kind {
-        hir::ExprKind::Box(ref e) => {
+        hir::ExprKind::Box(e) => {
             println!("{}Box", ind);
             print_expr(cx, e, indent + 1);
         },
@@ -161,7 +161,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                 print_expr(cx, e, indent + 1);
             }
         },
-        hir::ExprKind::Call(ref func, args) => {
+        hir::ExprKind::Call(func, args) => {
             println!("{}Call", ind);
             println!("{}function:", ind);
             print_expr(cx, func, indent + 1);
@@ -170,7 +170,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                 print_expr(cx, arg, indent + 1);
             }
         },
-        hir::ExprKind::MethodCall(ref path, _, args, _) => {
+        hir::ExprKind::MethodCall(path, _, args, _) => {
             println!("{}MethodCall", ind);
             println!("{}method name: {}", ind, path.ident.name);
             for arg in args {
@@ -183,7 +183,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                 print_expr(cx, e, indent + 1);
             }
         },
-        hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
+        hir::ExprKind::Binary(op, lhs, rhs) => {
             println!("{}Binary", ind);
             println!("{}op: {:?}", ind, op.node);
             println!("{}lhs:", ind);
@@ -191,7 +191,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}rhs:", ind);
             print_expr(cx, rhs, indent + 1);
         },
-        hir::ExprKind::Unary(op, ref inner) => {
+        hir::ExprKind::Unary(op, inner) => {
             println!("{}Unary", ind);
             println!("{}op: {:?}", ind, op);
             print_expr(cx, inner, indent + 1);
@@ -200,12 +200,12 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}Lit", ind);
             println!("{}{:?}", ind, lit);
         },
-        hir::ExprKind::Cast(ref e, ref target) => {
+        hir::ExprKind::Cast(e, target) => {
             println!("{}Cast", ind);
             print_expr(cx, e, indent + 1);
             println!("{}target type: {:?}", ind, target);
         },
-        hir::ExprKind::Type(ref e, ref target) => {
+        hir::ExprKind::Type(e, target) => {
             println!("{}Type", ind);
             print_expr(cx, e, indent + 1);
             println!("{}target type: {:?}", ind, target);
@@ -213,16 +213,16 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
         hir::ExprKind::Loop(..) => {
             println!("{}Loop", ind);
         },
-        hir::ExprKind::If(ref cond, _, ref else_opt) => {
+        hir::ExprKind::If(cond, _, ref else_opt) => {
             println!("{}If", ind);
             println!("{}condition:", ind);
             print_expr(cx, cond, indent + 1);
-            if let Some(ref els) = *else_opt {
+            if let Some(els) = *else_opt {
                 println!("{}else:", ind);
                 print_expr(cx, els, indent + 1);
             }
         },
-        hir::ExprKind::Match(ref cond, _, ref source) => {
+        hir::ExprKind::Match(cond, _, ref source) => {
             println!("{}Match", ind);
             println!("{}condition:", ind);
             print_expr(cx, cond, indent + 1);
@@ -232,21 +232,21 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}Closure", ind);
             println!("{}clause: {:?}", ind, clause);
         },
-        hir::ExprKind::Yield(ref sub, _) => {
+        hir::ExprKind::Yield(sub, _) => {
             println!("{}Yield", ind);
             print_expr(cx, sub, indent + 1);
         },
         hir::ExprKind::Block(_, _) => {
             println!("{}Block", ind);
         },
-        hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
+        hir::ExprKind::Assign(lhs, rhs, _) => {
             println!("{}Assign", ind);
             println!("{}lhs:", ind);
             print_expr(cx, lhs, indent + 1);
             println!("{}rhs:", ind);
             print_expr(cx, rhs, indent + 1);
         },
-        hir::ExprKind::AssignOp(ref binop, ref lhs, ref rhs) => {
+        hir::ExprKind::AssignOp(ref binop, lhs, rhs) => {
             println!("{}AssignOp", ind);
             println!("{}op: {:?}", ind, binop.node);
             println!("{}lhs:", ind);
@@ -254,31 +254,31 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}rhs:", ind);
             print_expr(cx, rhs, indent + 1);
         },
-        hir::ExprKind::Field(ref e, ident) => {
+        hir::ExprKind::Field(e, ident) => {
             println!("{}Field", ind);
             println!("{}field name: {}", ind, ident.name);
             println!("{}struct expr:", ind);
             print_expr(cx, e, indent + 1);
         },
-        hir::ExprKind::Index(ref arr, ref idx) => {
+        hir::ExprKind::Index(arr, idx) => {
             println!("{}Index", ind);
             println!("{}array expr:", ind);
             print_expr(cx, arr, indent + 1);
             println!("{}index expr:", ind);
             print_expr(cx, idx, indent + 1);
         },
-        hir::ExprKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
+        hir::ExprKind::Path(hir::QPath::Resolved(ref ty, path)) => {
             println!("{}Resolved Path, {:?}", ind, ty);
             println!("{}path: {:?}", ind, path);
         },
-        hir::ExprKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => {
+        hir::ExprKind::Path(hir::QPath::TypeRelative(ty, seg)) => {
             println!("{}Relative Path, {:?}", ind, ty);
             println!("{}seg: {:?}", ind, seg);
         },
         hir::ExprKind::Path(hir::QPath::LangItem(lang_item, ..)) => {
             println!("{}Lang Item Path, {:?}", ind, lang_item.name());
         },
-        hir::ExprKind::AddrOf(kind, ref muta, ref e) => {
+        hir::ExprKind::AddrOf(kind, ref muta, e) => {
             println!("{}AddrOf", ind);
             println!("kind: {:?}", kind);
             println!("mutability: {:?}", muta);
@@ -286,18 +286,18 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
         },
         hir::ExprKind::Break(_, ref e) => {
             println!("{}Break", ind);
-            if let Some(ref e) = *e {
+            if let Some(e) = *e {
                 print_expr(cx, e, indent + 1);
             }
         },
         hir::ExprKind::Continue(_) => println!("{}Again", ind),
         hir::ExprKind::Ret(ref e) => {
             println!("{}Ret", ind);
-            if let Some(ref e) = *e {
+            if let Some(e) = *e {
                 print_expr(cx, e, indent + 1);
             }
         },
-        hir::ExprKind::InlineAsm(ref asm) => {
+        hir::ExprKind::InlineAsm(asm) => {
             println!("{}InlineAsm", ind);
             println!("{}template: {}", ind, InlineAsmTemplatePiece::to_string(asm.template));
             println!("{}options: {:?}", ind, asm.options);
@@ -321,11 +321,11 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                     hir::InlineAsmOperand::Const { anon_const } => {
                         println!("{}anon_const:", ind);
                         print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
-                    }
+                    },
                 }
             }
         },
-        hir::ExprKind::LlvmInlineAsm(ref asm) => {
+        hir::ExprKind::LlvmInlineAsm(asm) => {
             let inputs = &asm.inputs_exprs;
             let outputs = &asm.outputs_exprs;
             println!("{}LlvmInlineAsm", ind);
@@ -338,14 +338,14 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                 print_expr(cx, e, indent + 1);
             }
         },
-        hir::ExprKind::Struct(ref path, fields, ref base) => {
+        hir::ExprKind::Struct(path, fields, ref base) => {
             println!("{}Struct", ind);
             println!("{}path: {:?}", ind, path);
             for field in fields {
                 println!("{}field \"{}\":", ind, field.ident.name);
-                print_expr(cx, &field.expr, indent + 1);
+                print_expr(cx, field.expr, indent + 1);
             }
-            if let Some(ref base) = *base {
+            if let Some(base) = *base {
                 println!("{}base:", ind);
                 print_expr(cx, base, indent + 1);
             }
@@ -355,7 +355,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}anon_const:", ind);
             print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
         },
-        hir::ExprKind::Repeat(ref val, ref anon_const) => {
+        hir::ExprKind::Repeat(val, ref anon_const) => {
             println!("{}Repeat", ind);
             println!("{}value:", ind);
             print_expr(cx, val, indent + 1);
@@ -365,7 +365,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
         hir::ExprKind::Err => {
             println!("{}Err", ind);
         },
-        hir::ExprKind::DropTemps(ref e) => {
+        hir::ExprKind::DropTemps(e) => {
             println!("{}DropTemps", ind);
             print_expr(cx, e, indent + 1);
         },
@@ -378,7 +378,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
     match item.vis.node {
         hir::VisibilityKind::Public => println!("public"),
         hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
-        hir::VisibilityKind::Restricted { ref path, .. } => println!(
+        hir::VisibilityKind::Restricted { path, .. } => println!(
             "visible in module `{}`",
             rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false))
         ),
@@ -398,7 +398,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
                 println!("weird extern crate without a crate id");
             }
         },
-        hir::ItemKind::Use(ref path, ref kind) => println!("{:?}, {:?}", path, kind),
+        hir::ItemKind::Use(path, ref kind) => println!("{:?}, {:?}", path, kind),
         hir::ItemKind::Static(..) => println!("static item of type {:#?}", cx.tcx.type_of(did)),
         hir::ItemKind::Const(..) => println!("const item of type {:#?}", cx.tcx.type_of(did)),
         hir::ItemKind::Fn(..) => {
@@ -407,7 +407,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
         },
         hir::ItemKind::Mod(..) => println!("module"),
         hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi),
-        hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm),
+        hir::ItemKind::GlobalAsm(asm) => println!("global asm: {:?}", asm),
         hir::ItemKind::TyAlias(..) => {
             println!("type alias for {:?}", cx.tcx.type_of(did));
         },
@@ -457,7 +457,7 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) {
             println!("{}Binding", ind);
             println!("{}mode: {:?}", ind, mode);
             println!("{}name: {}", ind, ident.name);
-            if let Some(ref inner) = *inner {
+            if let Some(inner) = *inner {
                 println!("{}inner:", ind);
                 print_pat(cx, inner, indent + 1);
             }
@@ -482,7 +482,7 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) {
                 if field.is_shorthand {
                     println!("{}  in shorthand notation", ind);
                 }
-                print_pat(cx, &field.pat, indent + 1);
+                print_pat(cx, field.pat, indent + 1);
             }
         },
         hir::PatKind::TupleStruct(ref path, fields, opt_dots_position) => {
@@ -499,11 +499,11 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) {
                 print_pat(cx, field, indent + 1);
             }
         },
-        hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
+        hir::PatKind::Path(hir::QPath::Resolved(ref ty, path)) => {
             println!("{}Resolved Path, {:?}", ind, ty);
             println!("{}path: {:?}", ind, path);
         },
-        hir::PatKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => {
+        hir::PatKind::Path(hir::QPath::TypeRelative(ty, seg)) => {
             println!("{}Relative Path, {:?}", ind, ty);
             println!("{}seg: {:?}", ind, seg);
         },
@@ -519,16 +519,16 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) {
                 print_pat(cx, field, indent + 1);
             }
         },
-        hir::PatKind::Box(ref inner) => {
+        hir::PatKind::Box(inner) => {
             println!("{}Box", ind);
             print_pat(cx, inner, indent + 1);
         },
-        hir::PatKind::Ref(ref inner, ref muta) => {
+        hir::PatKind::Ref(inner, ref muta) => {
             println!("{}Ref", ind);
             println!("{}mutability: {:?}", ind, muta);
             print_pat(cx, inner, indent + 1);
         },
-        hir::PatKind::Lit(ref e) => {
+        hir::PatKind::Lit(e) => {
             println!("{}Lit", ind);
             print_expr(cx, e, indent + 1);
         },
@@ -552,7 +552,7 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) {
                 print_pat(cx, pat, indent + 1);
             }
             println!("i:");
-            if let Some(ref pat) = *range {
+            if let Some(pat) = *range {
                 print_pat(cx, pat, indent + 1);
             }
             println!("[y, z]:");
diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
index c496ff1fb24..cf8039d6059 100644
--- a/clippy_lints/src/utils/internal_lints.rs
+++ b/clippy_lints/src/utils/internal_lints.rs
@@ -1,8 +1,10 @@
 use crate::consts::{constant_simple, Constant};
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::match_type;
-use clippy_utils::{is_expn_of, match_def_path, match_qpath, method_calls, path_to_res, paths, run_lints, SpanlessEq};
+use clippy_utils::{
+    is_else_clause, is_expn_of, match_def_path, match_qpath, method_calls, path_to_res, paths, run_lints, SpanlessEq,
+};
 use if_chain::if_chain;
 use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId};
 use rustc_ast::visit::FnKind;
@@ -14,15 +16,17 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_hir::{
-    BinOpKind, Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Node, Path, StmtKind, Ty, TyKind, UnOp,
+    BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MatchSource, MutTy, Mutability, Node, Path, Stmt,
+    StmtKind, Ty, TyKind, UnOp,
 };
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
-use rustc_span::source_map::{Span, Spanned};
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{Symbol, SymbolStr};
+use rustc_span::{BytePos, Span};
 use rustc_typeck::hir_ty_to_ty;
 
 use std::borrow::{Borrow, Cow};
@@ -297,6 +301,13 @@ declare_clippy_lint! {
     "unnecessary conversion between Symbol and string"
 }
 
+declare_clippy_lint! {
+    /// Finds unidiomatic usage of `if_chain!`
+    pub IF_CHAIN_STYLE,
+    internal,
+    "non-idiomatic `if_chain!` usage"
+}
+
 declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
 
 impl EarlyLintPass for ClippyLintsInternal {
@@ -342,12 +353,12 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
             return;
         }
 
-        if let hir::ItemKind::Static(ref ty, Mutability::Not, body_id) = item.kind {
+        if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
             if is_lint_ref_type(cx, ty) {
                 let expr = &cx.tcx.hir().body(body_id).value;
                 if_chain! {
-                    if let ExprKind::AddrOf(_, _, ref inner_exp) = expr.kind;
-                    if let ExprKind::Struct(_, ref fields, _) = inner_exp.kind;
+                    if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind;
+                    if let ExprKind::Struct(_, fields, _) = inner_exp.kind;
                     let field = fields
                         .iter()
                         .find(|f| f.ident.as_str() == "desc")
@@ -374,7 +385,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
         {
             if let hir::ItemKind::Impl(hir::Impl {
                 of_trait: None,
-                items: ref impl_item_refs,
+                items: impl_item_refs,
                 ..
             }) = item.kind
             {
@@ -426,7 +437,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &Ty<'_>) -> bool {
     if let TyKind::Rptr(
         _,
         MutTy {
-            ty: ref inner,
+            ty: inner,
             mutbl: Mutability::Not,
         },
     ) = ty.kind
@@ -487,7 +498,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
             let fn_name = path.ident;
             if let Some(sugg) = self.map.get(&*fn_name.as_str());
             let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
@@ -566,7 +577,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
         }
 
         if_chain! {
-            if let ExprKind::Call(ref func, ref and_then_args) = expr.kind;
+            if let ExprKind::Call(func, and_then_args) = expr.kind;
             if let ExprKind::Path(ref path) = func.kind;
             if match_qpath(path, &["span_lint_and_then"]);
             if and_then_args.len() == 5;
@@ -576,10 +587,10 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
             let stmts = &block.stmts;
             if stmts.len() == 1 && block.expr.is_none();
             if let StmtKind::Semi(only_expr) = &stmts[0].kind;
-            if let ExprKind::MethodCall(ref ps, _, ref span_call_args, _) = &only_expr.kind;
-            let and_then_snippets = get_and_then_snippets(cx, and_then_args);
-            let mut sle = SpanlessEq::new(cx).deny_side_effects();
+            if let ExprKind::MethodCall(ps, _, span_call_args, _) = &only_expr.kind;
             then {
+                let and_then_snippets = get_and_then_snippets(cx, and_then_args);
+                let mut sle = SpanlessEq::new(cx).deny_side_effects();
                 match &*ps.ident.as_str() {
                     "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
                         suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args));
@@ -751,7 +762,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem {
             // Check if this is a call to utils::match_type()
             if let ExprKind::Call(fn_path, [context, ty, ty_path]) = expr.kind;
             if let ExprKind::Path(fn_qpath) = &fn_path.kind;
-            if match_qpath(&fn_qpath, &["utils", "match_type"]);
+            if match_qpath(fn_qpath, &["utils", "match_type"]);
             // Extract the path to the matched type
             if let Some(segments) = path_to_matched_type(cx, ty_path);
             let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect();
@@ -1063,3 +1074,159 @@ impl<'tcx> SymbolStrExpr<'tcx> {
         }
     }
 }
+
+declare_lint_pass!(IfChainStyle => [IF_CHAIN_STYLE]);
+
+impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
+        let (local, after, if_chain_span) = if_chain! {
+            if let [Stmt { kind: StmtKind::Local(local), .. }, after @ ..] = block.stmts;
+            if let Some(if_chain_span) = is_expn_of(block.span, "if_chain");
+            then { (local, after, if_chain_span) } else { return }
+        };
+        if is_first_if_chain_expr(cx, block.hir_id, if_chain_span) {
+            span_lint(
+                cx,
+                IF_CHAIN_STYLE,
+                if_chain_local_span(cx, local, if_chain_span),
+                "`let` expression should be above the `if_chain!`",
+            );
+        } else if local.span.ctxt() == block.span.ctxt() && is_if_chain_then(after, block.expr, if_chain_span) {
+            span_lint(
+                cx,
+                IF_CHAIN_STYLE,
+                if_chain_local_span(cx, local, if_chain_span),
+                "`let` expression should be inside `then { .. }`",
+            )
+        }
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+        let (cond, then, els) = match expr.kind {
+            ExprKind::If(cond, then, els) => (Some(cond), then, els.is_some()),
+            ExprKind::Match(
+                _,
+                [arm, ..],
+                MatchSource::IfLetDesugar {
+                    contains_else_clause: els,
+                },
+            ) => (None, arm.body, els),
+            _ => return,
+        };
+        let then_block = match then.kind {
+            ExprKind::Block(block, _) => block,
+            _ => return,
+        };
+        let if_chain_span = is_expn_of(expr.span, "if_chain");
+        if !els {
+            check_nested_if_chains(cx, expr, then_block, if_chain_span);
+        }
+        let if_chain_span = match if_chain_span {
+            None => return,
+            Some(span) => span,
+        };
+        // check for `if a && b;`
+        if_chain! {
+            if let Some(cond) = cond;
+            if let ExprKind::Binary(op, _, _) = cond.kind;
+            if op.node == BinOpKind::And;
+            if cx.sess().source_map().is_multiline(cond.span);
+            then {
+                span_lint(cx, IF_CHAIN_STYLE, cond.span, "`if a && b;` should be `if a; if b;`");
+            }
+        }
+        if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span)
+            && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span)
+        {
+            span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`")
+        }
+    }
+}
+
+fn check_nested_if_chains(
+    cx: &LateContext<'_>,
+    if_expr: &Expr<'_>,
+    then_block: &Block<'_>,
+    if_chain_span: Option<Span>,
+) {
+    #[rustfmt::skip]
+    let (head, tail) = match *then_block {
+        Block { stmts, expr: Some(tail), .. } => (stmts, tail),
+        Block {
+            stmts: &[
+                ref head @ ..,
+                Stmt { kind: StmtKind::Expr(tail) | StmtKind::Semi(tail), .. }
+            ],
+            ..
+        } => (head, tail),
+        _ => return,
+    };
+    if_chain! {
+        if matches!(tail.kind,
+            ExprKind::If(_, _, None)
+            | ExprKind::Match(.., MatchSource::IfLetDesugar { contains_else_clause: false }));
+        let sm = cx.sess().source_map();
+        if head
+            .iter()
+            .all(|stmt| matches!(stmt.kind, StmtKind::Local(..)) && !sm.is_multiline(stmt.span));
+        if if_chain_span.is_some() || !is_else_clause(cx.tcx, if_expr);
+        then {} else { return }
+    }
+    let (span, msg) = match (if_chain_span, is_expn_of(tail.span, "if_chain")) {
+        (None, Some(_)) => (if_expr.span, "this `if` can be part of the inner `if_chain!`"),
+        (Some(_), None) => (tail.span, "this `if` can be part of the outer `if_chain!`"),
+        (Some(a), Some(b)) if a != b => (b, "this `if_chain!` can be merged with the outer `if_chain!`"),
+        _ => return,
+    };
+    span_lint_and_then(cx, IF_CHAIN_STYLE, span, msg, |diag| {
+        let (span, msg) = match head {
+            [] => return,
+            [stmt] => (stmt.span, "this `let` statement can also be in the `if_chain!`"),
+            [a, .., b] => (
+                a.span.to(b.span),
+                "these `let` statements can also be in the `if_chain!`",
+            ),
+        };
+        diag.span_help(span, msg);
+    });
+}
+
+fn is_first_if_chain_expr(cx: &LateContext<'_>, hir_id: HirId, if_chain_span: Span) -> bool {
+    cx.tcx
+        .hir()
+        .parent_iter(hir_id)
+        .find(|(_, node)| {
+            #[rustfmt::skip]
+            !matches!(node, Node::Expr(Expr { kind: ExprKind::Block(..), .. }) | Node::Stmt(_))
+        })
+        .map_or(false, |(id, _)| {
+            is_expn_of(cx.tcx.hir().span(id), "if_chain") != Some(if_chain_span)
+        })
+}
+
+/// Checks a trailing slice of statements and expression of a `Block` to see if they are part
+/// of the `then {..}` portion of an `if_chain!`
+fn is_if_chain_then(stmts: &[Stmt<'_>], expr: Option<&Expr<'_>>, if_chain_span: Span) -> bool {
+    let span = if let [stmt, ..] = stmts {
+        stmt.span
+    } else if let Some(expr) = expr {
+        expr.span
+    } else {
+        // empty `then {}`
+        return true;
+    };
+    is_expn_of(span, "if_chain").map_or(true, |span| span != if_chain_span)
+}
+
+/// Creates a `Span` for `let x = ..;` in an `if_chain!` call.
+fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: Span) -> Span {
+    let mut span = local.pat.span;
+    if let Some(init) = local.init {
+        span = span.to(init.span);
+    }
+    span.adjust(if_chain_span.ctxt().outer_expn());
+    let sm = cx.sess().source_map();
+    let span = sm.span_extend_to_prev_str(span, "let", false);
+    let span = sm.span_extend_to_next_char(span, ';', false);
+    Span::new(span.lo() - BytePos(3), span.hi() + BytePos(1), span.ctxt())
+}
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index 1af9583887f..febd4b6ff7b 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_copy;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{BorrowKind, Expr, ExprKind};
+use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -49,10 +49,10 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
         if_chain! {
             if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind();
             if let ty::Slice(..) = ty.kind();
-            if let ExprKind::AddrOf(BorrowKind::Ref, _, ref addressee) = expr.kind;
+            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
             if let Some(vec_args) = higher::vec_macro(cx, addressee);
             then {
-                self.check_vec_macro(cx, &vec_args, expr.span);
+                self.check_vec_macro(cx, &vec_args, mutability, expr.span);
             }
         }
 
@@ -70,14 +70,20 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
                     .ctxt()
                     .outer_expn_data()
                     .call_site;
-                self.check_vec_macro(cx, &vec_args, span);
+                self.check_vec_macro(cx, &vec_args, Mutability::Not, span);
             }
         }
     }
 }
 
 impl UselessVec {
-    fn check_vec_macro<'tcx>(self, cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) {
+    fn check_vec_macro<'tcx>(
+        self,
+        cx: &LateContext<'tcx>,
+        vec_args: &higher::VecArgs<'tcx>,
+        mutability: Mutability,
+        span: Span,
+    ) {
         let mut applicability = Applicability::MachineApplicable;
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
@@ -87,11 +93,22 @@ impl UselessVec {
                         return;
                     }
 
-                    format!(
-                        "&[{}; {}]",
-                        snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
-                        snippet_with_applicability(cx, len.span, "len", &mut applicability)
-                    )
+                    match mutability {
+                        Mutability::Mut => {
+                            format!(
+                                "&mut [{}; {}]",
+                                snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
+                                snippet_with_applicability(cx, len.span, "len", &mut applicability)
+                            )
+                        },
+                        Mutability::Not => {
+                            format!(
+                                "&[{}; {}]",
+                                snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
+                                snippet_with_applicability(cx, len.span, "len", &mut applicability)
+                            )
+                        },
+                    }
                 } else {
                     return;
                 }
@@ -104,9 +121,22 @@ impl UselessVec {
                     }
                     let span = args[0].span.to(last.span);
 
-                    format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
+                    match mutability {
+                        Mutability::Mut => {
+                            format!(
+                                "&mut [{}]",
+                                snippet_with_applicability(cx, span, "..", &mut applicability)
+                            )
+                        },
+                        Mutability::Not => {
+                            format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
+                        },
+                    }
                 } else {
-                    "&[]".into()
+                    match mutability {
+                        Mutability::Mut => "&mut []".into(),
+                        Mutability::Not => "&[]".into(),
+                    }
                 }
             },
         };
diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs
index 8b696ed1c84..c7190e2f979 100644
--- a/clippy_lints/src/vec_init_then_push.rs
+++ b/clippy_lints/src/vec_init_then_push.rs
@@ -108,22 +108,21 @@ impl LateLintPass<'_> for VecInitThenPush {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if self.searcher.is_none() {
-            if_chain! {
-                if !in_external_macro(cx.sess(), expr.span);
-                if let ExprKind::Assign(left, right, _) = expr.kind;
-                if let Some(id) = path_to_local(left);
-                if let Some(init_kind) = get_vec_init_kind(cx, right);
-                then {
-                    self.searcher = Some(VecPushSearcher {
-                        local_id: id,
-                        init: init_kind,
-                        lhs_is_local: false,
-                        lhs_span: left.span,
-                        err_span: expr.span,
-                        found: 0,
-                    });
-                }
+        if_chain! {
+            if self.searcher.is_none();
+            if !in_external_macro(cx.sess(), expr.span);
+            if let ExprKind::Assign(left, right, _) = expr.kind;
+            if let Some(id) = path_to_local(left);
+            if let Some(init_kind) = get_vec_init_kind(cx, right);
+            then {
+                self.searcher = Some(VecPushSearcher {
+                    local_id: id,
+                    init: init_kind,
+                    lhs_is_local: false,
+                    lhs_span: left.span,
+                    err_span: expr.span,
+                    found: 0,
+                });
             }
         }
     }
diff --git a/clippy_lints/src/vec_resize_to_zero.rs b/clippy_lints/src/vec_resize_to_zero.rs
index e035d3c5cad..5540e87405f 100644
--- a/clippy_lints/src/vec_resize_to_zero.rs
+++ b/clippy_lints/src/vec_resize_to_zero.rs
@@ -30,7 +30,7 @@ declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]);
 impl<'tcx> LateLintPass<'tcx> for VecResizeToZero {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let hir::ExprKind::MethodCall(path_segment, _, ref args, _) = expr.kind;
+            if let hir::ExprKind::MethodCall(path_segment, _, args, _) = expr.kind;
             if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
             if match_def_path(cx, method_def_id, &paths::VEC_RESIZE) && args.len() == 3;
             if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = args[1].kind;
diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs
index 3b4890ad560..350b1cf25ff 100644
--- a/clippy_lints/src/zero_div_zero.rs
+++ b/clippy_lints/src/zero_div_zero.rs
@@ -31,7 +31,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // check for instances of 0.0/0.0
         if_chain! {
-            if let ExprKind::Binary(ref op, ref left, ref right) = expr.kind;
+            if let ExprKind::Binary(ref op, left, right) = expr.kind;
             if let BinOpKind::Div = op.node;
             // TODO - constant_simple does not fold many operations involving floats.
             // That's probably fine for this lint - it's pretty unlikely that someone would
diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs
index 2abd033e2a0..f93f0047f51 100644
--- a/clippy_lints/src/zero_sized_map_values.rs
+++ b/clippy_lints/src/zero_sized_map_values.rs
@@ -50,7 +50,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
             if !in_trait_impl(cx, hir_ty.hir_id);
             let ty = ty_from_hir_ty(cx, hir_ty);
             if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || match_type(cx, ty, &paths::BTREEMAP);
-            if let Adt(_, ref substs) = ty.kind();
+            if let Adt(_, substs) = ty.kind();
             let ty = substs.type_at(1);
             // Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`.
             if is_normalizable(cx, cx.param_env, ty);