about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--clippy_dev/src/bless.rs7
-rw-r--r--clippy_lints/src/approx_const.rs2
-rw-r--r--clippy_lints/src/as_conversions.rs4
-rw-r--r--clippy_lints/src/assign_ops.rs8
-rw-r--r--clippy_lints/src/blocks_in_if_conditions.rs10
-rw-r--r--clippy_lints/src/booleans.rs15
-rw-r--r--clippy_lints/src/borrow_as_ptr.rs2
-rw-r--r--clippy_lints/src/bytecount.rs6
-rw-r--r--clippy_lints/src/case_sensitive_file_extension_comparisons.rs2
-rw-r--r--clippy_lints/src/casts/cast_possible_truncation.rs6
-rw-r--r--clippy_lints/src/casts/cast_ptr_alignment.rs2
-rw-r--r--clippy_lints/src/casts/cast_sign_loss.rs4
-rw-r--r--clippy_lints/src/casts/unnecessary_cast.rs11
-rw-r--r--clippy_lints/src/cognitive_complexity.rs8
-rw-r--r--clippy_lints/src/copies.rs10
-rw-r--r--clippy_lints/src/default_numeric_fallback.rs11
-rw-r--r--clippy_lints/src/default_union_representation.rs105
-rw-r--r--clippy_lints/src/dereference.rs204
-rw-r--r--clippy_lints/src/derive.rs10
-rw-r--r--clippy_lints/src/disallowed_script_idents.rs4
-rw-r--r--clippy_lints/src/doc.rs10
-rw-r--r--clippy_lints/src/duration_subsec.rs2
-rw-r--r--clippy_lints/src/else_if_without_else.rs4
-rw-r--r--clippy_lints/src/entry.rs12
-rw-r--r--clippy_lints/src/escape.rs5
-rw-r--r--clippy_lints/src/eta_reduction.rs2
-rw-r--r--clippy_lints/src/eval_order_dependence.rs13
-rw-r--r--clippy_lints/src/exit.rs5
-rw-r--r--clippy_lints/src/explicit_write.rs4
-rw-r--r--clippy_lints/src/fallible_impl_from.rs9
-rw-r--r--clippy_lints/src/floating_point_arithmetic.rs18
-rw-r--r--clippy_lints/src/format_args.rs2
-rw-r--r--clippy_lints/src/formatting.rs6
-rw-r--r--clippy_lints/src/from_over_into.rs2
-rw-r--r--clippy_lints/src/functions/must_use.rs11
-rw-r--r--clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs10
-rw-r--r--clippy_lints/src/functions/result_unit_err.rs2
-rw-r--r--clippy_lints/src/get_last_with_len.rs4
-rw-r--r--clippy_lints/src/if_let_mutex.rs17
-rw-r--r--clippy_lints/src/implicit_hasher.rs18
-rw-r--r--clippy_lints/src/index_refutable_slice.rs12
-rw-r--r--clippy_lints/src/infinite_iter.rs4
-rw-r--r--clippy_lints/src/inherent_to_string.rs2
-rw-r--r--clippy_lints/src/items_after_statements.rs6
-rw-r--r--clippy_lints/src/len_zero.rs2
-rw-r--r--clippy_lints/src/let_underscore.rs2
-rw-r--r--clippy_lints/src/lib.register_all.rs1
-rw-r--r--clippy_lints/src/lib.register_complexity.rs1
-rw-r--r--clippy_lints/src/lib.register_lints.rs2
-rw-r--r--clippy_lints/src/lib.register_restriction.rs1
-rw-r--r--clippy_lints/src/lib.rs4
-rw-r--r--clippy_lints/src/lifetimes.rs74
-rw-r--r--clippy_lints/src/literal_representation.rs6
-rw-r--r--clippy_lints/src/loops/manual_memcpy.rs4
-rw-r--r--clippy_lints/src/loops/mod.rs2
-rw-r--r--clippy_lints/src/loops/mut_range_bound.rs9
-rw-r--r--clippy_lints/src/loops/needless_collect.rs27
-rw-r--r--clippy_lints/src/loops/needless_range_loop.rs20
-rw-r--r--clippy_lints/src/loops/never_loop.rs3
-rw-r--r--clippy_lints/src/loops/same_item_push.rs13
-rw-r--r--clippy_lints/src/loops/single_element_loop.rs2
-rw-r--r--clippy_lints/src/loops/utils.rs21
-rw-r--r--clippy_lints/src/loops/while_immutable_condition.rs15
-rw-r--r--clippy_lints/src/loops/while_let_on_iterator.rs20
-rw-r--r--clippy_lints/src/manual_async_fn.rs4
-rw-r--r--clippy_lints/src/manual_bits.rs2
-rw-r--r--clippy_lints/src/manual_non_exhaustive.rs6
-rw-r--r--clippy_lints/src/manual_ok_or.rs2
-rw-r--r--clippy_lints/src/manual_strip.rs14
-rw-r--r--clippy_lints/src/map_clone.rs6
-rw-r--r--clippy_lints/src/map_err_ignore.rs2
-rw-r--r--clippy_lints/src/map_unit_fn.rs2
-rw-r--r--clippy_lints/src/match_result_ok.rs4
-rw-r--r--clippy_lints/src/match_str_case_mismatch.rs12
-rw-r--r--clippy_lints/src/matches.rs144
-rw-r--r--clippy_lints/src/mem_replace.rs2
-rw-r--r--clippy_lints/src/methods/bind_instead_of_map.rs4
-rw-r--r--clippy_lints/src/methods/clone_on_copy.rs4
-rw-r--r--clippy_lints/src/methods/expect_fun_call.rs4
-rw-r--r--clippy_lints/src/methods/extend_with_drain.rs2
-rw-r--r--clippy_lints/src/methods/filter_map.rs6
-rw-r--r--clippy_lints/src/methods/mod.rs34
-rw-r--r--clippy_lints/src/methods/option_as_ref_deref.rs2
-rw-r--r--clippy_lints/src/methods/option_map_unwrap_or.rs16
-rw-r--r--clippy_lints/src/methods/str_splitn.rs14
-rw-r--r--clippy_lints/src/methods/unnecessary_filter_map.rs9
-rw-r--r--clippy_lints/src/methods/unnecessary_iter_cloned.rs15
-rw-r--r--clippy_lints/src/methods/unnecessary_to_owned.rs7
-rw-r--r--clippy_lints/src/methods/useless_asref.rs4
-rw-r--r--clippy_lints/src/methods/utils.rs2
-rw-r--r--clippy_lints/src/minmax.rs2
-rw-r--r--clippy_lints/src/misc.rs2
-rw-r--r--clippy_lints/src/misc_early/mod.rs4
-rw-r--r--clippy_lints/src/missing_const_for_fn.rs4
-rw-r--r--clippy_lints/src/module_style.rs4
-rw-r--r--clippy_lints/src/mut_key.rs2
-rw-r--r--clippy_lints/src/mut_mut.rs6
-rw-r--r--clippy_lints/src/mut_mutex_lock.rs4
-rw-r--r--clippy_lints/src/mut_reference.rs2
-rw-r--r--clippy_lints/src/mutable_debug_assertion.rs10
-rw-r--r--clippy_lints/src/needless_for_each.rs13
-rw-r--r--clippy_lints/src/needless_option_as_deref.rs2
-rw-r--r--clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--clippy_lints/src/needless_question_mark.rs23
-rw-r--r--clippy_lints/src/new_without_default.rs2
-rw-r--r--clippy_lints/src/non_copy_const.rs2
-rw-r--r--clippy_lints/src/non_expressive_names.rs6
-rw-r--r--clippy_lints/src/non_octal_unix_permissions.rs2
-rw-r--r--clippy_lints/src/non_send_fields_in_send_ty.rs8
-rw-r--r--clippy_lints/src/octal_escapes.rs6
-rw-r--r--clippy_lints/src/open_options.rs4
-rw-r--r--clippy_lints/src/option_if_let_else.rs2
-rw-r--r--clippy_lints/src/path_buf_push_overwrite.rs2
-rw-r--r--clippy_lints/src/ptr.rs621
-rw-r--r--clippy_lints/src/ptr_offset_with_cast.rs2
-rw-r--r--clippy_lints/src/question_mark.rs2
-rw-r--r--clippy_lints/src/ranges.rs8
-rw-r--r--clippy_lints/src/redundant_clone.rs18
-rw-r--r--clippy_lints/src/redundant_closure_call.rs12
-rw-r--r--clippy_lints/src/redundant_else.rs4
-rw-r--r--clippy_lints/src/redundant_field_names.rs4
-rw-r--r--clippy_lints/src/reference.rs57
-rw-r--r--clippy_lints/src/repeat_once.rs2
-rw-r--r--clippy_lints/src/returns.rs11
-rw-r--r--clippy_lints/src/same_name_method.rs2
-rw-r--r--clippy_lints/src/self_named_constructors.rs6
-rw-r--r--clippy_lints/src/single_char_lifetime_names.rs4
-rw-r--r--clippy_lints/src/single_component_path_imports.rs4
-rw-r--r--clippy_lints/src/size_of_in_element_count.rs2
-rw-r--r--clippy_lints/src/slow_vector_initialization.rs15
-rw-r--r--clippy_lints/src/stable_sort_primitive.rs2
-rw-r--r--clippy_lints/src/strings.rs10
-rw-r--r--clippy_lints/src/strlen_on_c_strings.rs2
-rw-r--r--clippy_lints/src/suspicious_operation_groupings.rs1
-rw-r--r--clippy_lints/src/suspicious_trait_impl.rs11
-rw-r--r--clippy_lints/src/to_digit_is_some.rs4
-rw-r--r--clippy_lints/src/to_string_in_display.rs2
-rw-r--r--clippy_lints/src/trait_bounds.rs58
-rw-r--r--clippy_lints/src/types/mod.rs14
-rw-r--r--clippy_lints/src/types/type_complexity.rs8
-rw-r--r--clippy_lints/src/undocumented_unsafe_blocks.rs9
-rw-r--r--clippy_lints/src/uninit_vec.rs4
-rw-r--r--clippy_lints/src/unit_hash.rs2
-rw-r--r--clippy_lints/src/unit_return_expecting_ord.rs8
-rw-r--r--clippy_lints/src/unit_types/unit_arg.rs2
-rw-r--r--clippy_lints/src/unnecessary_sort_by.rs14
-rw-r--r--clippy_lints/src/unnested_or_patterns.rs4
-rw-r--r--clippy_lints/src/unused_async.rs10
-rw-r--r--clippy_lints/src/unused_io_amount.rs6
-rw-r--r--clippy_lints/src/unused_self.rs2
-rw-r--r--clippy_lints/src/unwrap.rs14
-rw-r--r--clippy_lints/src/unwrap_in_result.rs9
-rw-r--r--clippy_lints/src/use_self.rs13
-rw-r--r--clippy_lints/src/utils/author.rs8
-rw-r--r--clippy_lints/src/utils/inspector.rs15
-rw-r--r--clippy_lints/src/utils/internal_lints.rs16
-rw-r--r--clippy_lints/src/utils/internal_lints/metadata_collector.rs31
-rw-r--r--clippy_lints/src/vec_init_then_push.rs2
-rw-r--r--clippy_lints/src/vec_resize_to_zero.rs2
-rw-r--r--clippy_lints/src/verbose_file_reads.rs4
-rw-r--r--clippy_lints/src/write.rs6
-rw-r--r--clippy_lints/src/zero_sized_map_values.rs6
-rw-r--r--clippy_utils/src/ast_utils.rs14
-rw-r--r--clippy_utils/src/eager_or_lazy.rs10
-rw-r--r--clippy_utils/src/hir_utils.rs6
-rw-r--r--clippy_utils/src/lib.rs105
-rw-r--r--clippy_utils/src/macros.rs6
-rw-r--r--clippy_utils/src/numeric_literal.rs9
-rw-r--r--clippy_utils/src/ptr.rs2
-rw-r--r--clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--clippy_utils/src/sugg.rs10
-rw-r--r--clippy_utils/src/ty.rs123
-rw-r--r--clippy_utils/src/usage.rs14
-rw-r--r--clippy_utils/src/visitors.rs32
-rw-r--r--doc/common_tools_writing_lints.md2
-rw-r--r--lintcheck/Cargo.toml2
-rw-r--r--rust-toolchain2
-rw-r--r--tests/ui/author/struct.stdout2
-rw-r--r--tests/ui/borrow_interior_mutable_const/others.rs6
-rw-r--r--tests/ui/borrow_interior_mutable_const/others.stderr28
-rw-r--r--tests/ui/bytecount.rs2
-rw-r--r--tests/ui/bytecount.stderr8
-rw-r--r--tests/ui/clone_on_copy.fixed3
-rw-r--r--tests/ui/clone_on_copy.rs3
-rw-r--r--tests/ui/clone_on_copy.stderr16
-rw-r--r--tests/ui/crashes/ice-8250.rs6
-rw-r--r--tests/ui/crashes/ice-8250.stderr18
-rw-r--r--tests/ui/default_union_representation.rs78
-rw-r--r--tests/ui/default_union_representation.stderr48
-rw-r--r--tests/ui/duration_subsec.fixed2
-rw-r--r--tests/ui/duration_subsec.rs2
-rw-r--r--tests/ui/eta.fixed9
-rw-r--r--tests/ui/eta.rs7
-rw-r--r--tests/ui/eta.stderr50
-rw-r--r--tests/ui/explicit_deref_methods.fixed2
-rw-r--r--tests/ui/explicit_deref_methods.rs2
-rw-r--r--tests/ui/for_loop_fixable.fixed7
-rw-r--r--tests/ui/for_loop_fixable.rs7
-rw-r--r--tests/ui/for_loop_fixable.stderr30
-rw-r--r--tests/ui/format.fixed7
-rw-r--r--tests/ui/format.rs7
-rw-r--r--tests/ui/format.stderr34
-rw-r--r--tests/ui/needless_borrow.fixed27
-rw-r--r--tests/ui/needless_borrow.rs27
-rw-r--r--tests/ui/needless_borrow.stderr76
-rw-r--r--tests/ui/needless_lifetimes.rs51
-rw-r--r--tests/ui/needless_lifetimes.stderr94
-rw-r--r--tests/ui/needless_question_mark.fixed13
-rw-r--r--tests/ui/needless_question_mark.rs13
-rw-r--r--tests/ui/needless_question_mark.stderr14
-rw-r--r--tests/ui/ptr_arg.rs35
-rw-r--r--tests/ui/ptr_arg.stderr158
-rw-r--r--tests/ui/redundant_pattern_matching_option.fixed2
-rw-r--r--tests/ui/redundant_pattern_matching_option.rs2
-rw-r--r--tests/ui/rename.fixed1
-rw-r--r--tests/ui/rename.rs1
-rw-r--r--tests/ui/rename.stderr26
-rw-r--r--tests/ui/search_is_some_fixable_none.rs2
-rw-r--r--tests/ui/search_is_some_fixable_none.stderr10
-rw-r--r--tests/ui/search_is_some_fixable_some.rs2
-rw-r--r--tests/ui/search_is_some_fixable_some.stderr10
-rw-r--r--tests/ui/single_match.rs78
-rw-r--r--tests/ui/single_match.stderr38
-rw-r--r--tests/ui/single_match_else.stderr42
-rw-r--r--tests/ui/slow_vector_initialization.rs2
-rw-r--r--tests/ui/to_string_in_display.stderr11
-rw-r--r--tests/ui/trait_duplication_in_bounds.rs22
-rw-r--r--tests/ui/trait_duplication_in_bounds.stderr24
-rw-r--r--tests/ui/unnecessary_cast.rs7
-rw-r--r--tests/ui/unnecessary_cast.stderr38
-rw-r--r--tests/ui/unnecessary_ref.fixed23
-rw-r--r--tests/ui/unnecessary_ref.rs23
-rw-r--r--tests/ui/unnecessary_ref.stderr22
-rw-r--r--tests/ui/useless_asref.fixed2
-rw-r--r--tests/ui/useless_asref.rs2
-rw-r--r--tests/ui/write_literal.rs48
-rw-r--r--tests/ui/write_literal.stderr110
-rw-r--r--tests/ui/write_literal_2.rs16
-rw-r--r--tests/ui/write_literal_2.stderr50
-rw-r--r--tests/ui/write_with_newline.rs56
-rw-r--r--tests/ui/write_with_newline.stderr72
-rw-r--r--tests/ui/writeln_empty_string.fixed10
-rw-r--r--tests/ui/writeln_empty_string.rs10
-rw-r--r--tests/ui/writeln_empty_string.stderr12
-rw-r--r--util/gh-pages/index.html5
246 files changed, 2574 insertions, 1792 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7504e3afe01..ce31c697ee1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1152,7 +1152,7 @@ Released 2021-03-25
   [#6532](https://github.com/rust-lang/rust-clippy/pull/6532)
 * [`single_match`] Suggest `if` over `if let` when possible
   [#6574](https://github.com/rust-lang/rust-clippy/pull/6574)
-* [`ref_in_deref`] Use parentheses correctly in suggestion
+* `ref_in_deref` Use parentheses correctly in suggestion
   [#6609](https://github.com/rust-lang/rust-clippy/pull/6609)
 * [`stable_sort_primitive`] Clarify error message
   [#6611](https://github.com/rust-lang/rust-clippy/pull/6611)
@@ -3101,6 +3101,7 @@ Released 2018-09-13
 [`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const
 [`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback
 [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access
+[`default_union_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_union_representation
 [`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr
 [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver
 [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
@@ -3398,7 +3399,6 @@ Released 2018-09-13
 [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
 [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
-[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
 [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
diff --git a/clippy_dev/src/bless.rs b/clippy_dev/src/bless.rs
index daf0fcc993b..dcc2502e4c5 100644
--- a/clippy_dev/src/bless.rs
+++ b/clippy_dev/src/bless.rs
@@ -9,9 +9,14 @@ use walkdir::WalkDir;
 
 use crate::clippy_project_root;
 
+#[cfg(not(windows))]
+static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
+#[cfg(windows)]
+static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
+
 static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = SyncLazy::new(|| {
     let mut path = std::env::current_exe().unwrap();
-    path.set_file_name("cargo-clippy");
+    path.set_file_name(CARGO_CLIPPY_EXE);
     fs::metadata(path).ok()?.modified().ok()
 });
 
diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs
index 5061c9d1eaf..e109ee0009e 100644
--- a/clippy_lints/src/approx_const.rs
+++ b/clippy_lints/src/approx_const.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::{meets_msrv, msrvs};
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol;
diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs
index 53704da1046..88b91d58907 100644
--- a/clippy_lints/src/as_conversions.rs
+++ b/clippy_lints/src/as_conversions.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -48,7 +48,7 @@ declare_lint_pass!(AsConversions => [AS_CONVERSIONS]);
 
 impl EarlyLintPass for AsConversions {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
 
diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs
index e16f4369da9..12c1bddf79d 100644
--- a/clippy_lints/src/assign_ops.rs
+++ b/clippy_lints/src/assign_ops.rs
@@ -6,9 +6,8 @@ use clippy_utils::{eq_expr_value, trait_ref_of_method};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -220,8 +219,6 @@ struct ExprVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
         if eq_expr_value(self.cx, self.assignee, expr) {
             self.counter += 1;
@@ -229,7 +226,4 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
 
         walk_expr(self, expr);
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/blocks_in_if_conditions.rs b/clippy_lints/src/blocks_in_if_conditions.rs
index 475fdb440d4..c4956bacf43 100644
--- a/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/clippy_lints/src/blocks_in_if_conditions.rs
@@ -5,10 +5,9 @@ use clippy_utils::ty::implements_trait;
 use clippy_utils::{differing_macro_contexts, get_parent_expr};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BlockCheckMode, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -55,14 +54,12 @@ struct ExVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if let ExprKind::Closure(_, _, eid, _, _) = expr.kind {
             // do not lint if the closure is called using an iterator (see #1141)
             if_chain! {
                 if let Some(parent) = get_parent_expr(self.cx, expr);
-                if let ExprKind::MethodCall(_, _, [self_arg, ..], _) = &parent.kind;
+                if let ExprKind::MethodCall(_, [self_arg, ..], _) = &parent.kind;
                 let caller = self.cx.typeck_results().expr_ty(self_arg);
                 if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
                 if implements_trait(self.cx, caller, iter_id, &[]);
@@ -82,9 +79,6 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
         }
         walk_expr(self, expr);
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition";
diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index 43ad0f7605c..f7449c8dc72 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -5,10 +5,9 @@ use clippy_utils::{eq_expr_value, get_trait_def_id, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp};
 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;
 use rustc_span::sym;
@@ -260,7 +259,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                 ))
             })
         },
-        ExprKind::MethodCall(path, _, args, _) if args.len() == 1 => {
+        ExprKind::MethodCall(path, args, _) if args.len() == 1 => {
             let type_of_receiver = cx.typeck_results().expr_ty(&args[0]);
             if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option)
                 && !is_type_diagnostic_item(cx, type_of_receiver, sym::Result)
@@ -452,8 +451,6 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         if !e.span.from_expansion() {
             match &e.kind {
@@ -470,9 +467,6 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
         }
         walk_expr(self, e);
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 fn implements_ord<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool {
@@ -485,8 +479,6 @@ struct NotSimplificationVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind {
             if let Some(suggestion) = simplify_not(self.cx, inner) {
@@ -504,7 +496,4 @@ impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
 
         walk_expr(self, expr);
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/borrow_as_ptr.rs b/clippy_lints/src/borrow_as_ptr.rs
index 265cdeab094..9f8eb488c29 100644
--- a/clippy_lints/src/borrow_as_ptr.rs
+++ b/clippy_lints/src/borrow_as_ptr.rs
@@ -5,7 +5,7 @@ use clippy_utils::{meets_msrv, msrvs};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, TyKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs
index 92336a54e27..02d97bf43df 100644
--- a/clippy_lints/src/bytecount.rs
+++ b/clippy_lints/src/bytecount.rs
@@ -41,9 +41,9 @@ 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(count, _, [count_recv], _) = expr.kind;
+            if let ExprKind::MethodCall(count, [count_recv], _) = expr.kind;
             if count.ident.name == sym::count;
-            if let ExprKind::MethodCall(filter, _, [filter_recv, filter_arg], _) = count_recv.kind;
+            if let ExprKind::MethodCall(filter, [filter_recv, filter_arg], _) = count_recv.kind;
             if filter.ident.name == sym!(filter);
             if let ExprKind::Closure(_, _, body_id, _, _) = filter_arg.kind;
             let body = cx.tcx.hir().body(body_id);
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
             if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind();
             if !is_local_used(cx, needle, arg_id);
             then {
-                let haystack = if let ExprKind::MethodCall(path, _, args, _) =
+                let haystack = if let ExprKind::MethodCall(path, args, _) =
                         filter_recv.kind {
                     let p = path.ident.name;
                     if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 {
diff --git a/clippy_lints/src/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
index e8f39cd3709..e71f110820c 100644
--- a/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
+++ b/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
@@ -37,7 +37,7 @@ declare_lint_pass!(CaseSensitiveFileExtensionComparisons => [CASE_SENSITIVE_FILE
 
 fn check_case_sensitive_file_extension_comparison(ctx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Span> {
     if_chain! {
-        if let ExprKind::MethodCall(PathSegment { ident, .. }, _, [obj, extension, ..], span) = expr.kind;
+        if let ExprKind::MethodCall(PathSegment { ident, .. }, [obj, extension, ..], span) = expr.kind;
         if ident.as_str() == "ends_with";
         if let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = extension.kind;
         if (2..=6).contains(&ext_literal.as_str().len());
diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index 4af412ccaf3..ea74d5acbda 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -43,7 +43,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             },
             _ => nbits,
         },
-        ExprKind::MethodCall(method, _, [left, right], _) => {
+        ExprKind::MethodCall(method, [left, right], _) => {
             if signed {
                 return nbits;
             }
@@ -54,7 +54,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             };
             apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
         },
-        ExprKind::MethodCall(method, _, [_, lo, hi], _) => {
+        ExprKind::MethodCall(method, [_, lo, hi], _) => {
             if method.ident.as_str() == "clamp" {
                 //FIXME: make this a diagnostic item
                 if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
@@ -63,7 +63,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             }
             nbits
         },
-        ExprKind::MethodCall(method, _, [_value], _) => {
+        ExprKind::MethodCall(method, [_value], _) => {
             if method.ident.name.as_str() == "signum" {
                 0 // do not lint if cast comes from a `signum` function
             } else {
diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs
index b9de5510455..079b7ff0675 100644
--- a/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
             cx.typeck_results().expr_ty(expr),
         );
         lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
-    } else if let ExprKind::MethodCall(method_path, _, [self_arg, ..], _) = &expr.kind {
+    } else if let ExprKind::MethodCall(method_path, [self_arg, ..], _) = &expr.kind {
         if_chain! {
             if method_path.ident.name == sym!(cast);
             if let Some(generic_args) = method_path.args;
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs
index c9c111a2847..75f70b77ed4 100644
--- a/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/clippy_lints/src/casts/cast_sign_loss.rs
@@ -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(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(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/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 1915d990c12..470c8c7ea26 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -23,15 +23,14 @@ pub(super) fn check(
 
         if_chain! {
             if let LitKind::Int(n, _) = lit.node;
-            if let Some(src) = snippet_opt(cx, lit.span);
+            if let Some(src) = snippet_opt(cx, cast_expr.span);
             if cast_to.is_floating_point();
             if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node);
             let from_nbits = 128 - n.leading_zeros();
             let to_nbits = fp_ty_mantissa_nbits(cast_to);
             if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal();
             then {
-                let literal_str = if is_unary_neg(cast_expr) { format!("-{}", num_lit.integer) } else { num_lit.integer.into() };
-                lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
+                lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
                 return true
             }
         }
@@ -48,7 +47,7 @@ pub(super) fn check(
             | LitKind::Float(_, LitFloatType::Suffixed(_))
                 if cast_from.kind() == cast_to.kind() =>
             {
-                if let Some(src) = snippet_opt(cx, lit.span) {
+                if let Some(src) = snippet_opt(cx, cast_expr.span) {
                     if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
                         lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
                     }
@@ -113,7 +112,3 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
         _ => 0,
     }
 }
-
-fn is_unary_neg(expr: &Expr<'_>) -> bool {
-    matches!(expr.kind, ExprKind::Unary(UnOp::Neg, _))
-}
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 84a2373efe1..85f95237549 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -5,10 +5,9 @@ use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::LimitStack;
 use rustc_ast::ast::Attribute;
-use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, BytePos};
@@ -149,8 +148,6 @@ struct CcHelper {
 }
 
 impl<'tcx> Visitor<'tcx> for CcHelper {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         walk_expr(self, e);
         match e.kind {
@@ -167,7 +164,4 @@ impl<'tcx> Visitor<'tcx> for CcHelper {
             _ => {},
         }
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index f44d370a8fd..8b79f1600ae 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -7,10 +7,10 @@ use clippy_utils::{
 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::intravisit::{self, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{source_map::Span, symbol::Symbol, BytePos};
 use std::borrow::Cow;
@@ -566,10 +566,10 @@ impl<'a, 'tcx> UsedValueFinderVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UsedValueFinderVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 
     fn visit_local(&mut self, l: &'tcx rustc_hir::Local<'tcx>) {
diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs
index 66b5f49817d..fb201d2c012 100644
--- a/clippy_lints/src/default_numeric_fallback.rs
+++ b/clippy_lints/src/default_numeric_fallback.rs
@@ -5,12 +5,11 @@ use if_chain::if_chain;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{
-    intravisit::{walk_expr, walk_stmt, NestedVisitorMap, Visitor},
+    intravisit::{walk_expr, walk_stmt, Visitor},
     Body, Expr, ExprKind, HirId, Lit, Stmt, StmtKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::{
-    hir::map::Map,
     lint::in_external_macro,
     ty::{self, FloatTy, IntTy, PolyFnSig, Ty},
 };
@@ -117,8 +116,6 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     #[allow(clippy::too_many_lines)]
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         match &expr.kind {
@@ -134,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
                 }
             },
 
-            ExprKind::MethodCall(_, _, args, _) => {
+            ExprKind::MethodCall(_, args, _) => {
                 if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
                     let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
                     for (expr, bound) in iter::zip(*args, fn_sig.inputs()) {
@@ -209,10 +206,6 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
         walk_stmt(self, stmt);
         self.ty_bounds.pop();
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'tcx>> {
diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs
new file mode 100644
index 00000000000..9b5da0bd8a6
--- /dev/null
+++ b/clippy_lints/src/default_union_representation.rs
@@ -0,0 +1,105 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_hir::{self as hir, HirId, Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+use rustc_typeck::hir_ty_to_ty;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Displays a warning when a union is declared with the default representation (without a `#[repr(C)]` attribute).
+    ///
+    /// ### Why is this bad?
+    /// Unions in Rust have unspecified layout by default, despite many people thinking that they
+    /// lay out each field at the start of the union (like C does). That is, there are no guarantees
+    /// about the offset of the fields for unions with multiple non-ZST fields without an explicitly
+    /// specified layout. These cases may lead to undefined behavior in unsafe blocks.
+    ///
+    /// ### Example
+    /// ```rust
+    /// union Foo {
+    ///     a: i32,
+    ///     b: u32,
+    /// }
+    ///
+    /// fn main() {
+    ///     let _x: u32 = unsafe {
+    ///         Foo { a: 0_i32 }.b // Undefined behaviour: `b` is allowed to be padding
+    ///     };
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// #[repr(C)]
+    /// union Foo {
+    ///     a: i32,
+    ///     b: u32,
+    /// }
+    ///
+    /// fn main() {
+    ///     let _x: u32 = unsafe {
+    ///         Foo { a: 0_i32 }.b // Now defined behaviour, this is just an i32 -> u32 transmute
+    ///     };
+    /// }
+    /// ```
+    #[clippy::version = "1.60.0"]
+    pub DEFAULT_UNION_REPRESENTATION,
+    restriction,
+    "unions without a `#[repr(C)]` attribute"
+}
+declare_lint_pass!(DefaultUnionRepresentation => [DEFAULT_UNION_REPRESENTATION]);
+
+impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if is_union_with_two_non_zst_fields(cx, item) && !has_c_repr_attr(cx, item.hir_id()) {
+            span_lint_and_help(
+                cx,
+                DEFAULT_UNION_REPRESENTATION,
+                item.span,
+                "this union has the default representation",
+                None,
+                &format!(
+                    "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
+                    cx.tcx.def_path_str(item.def_id.to_def_id())
+                ),
+            );
+        }
+    }
+}
+
+/// Returns true if the given item is a union with at least two non-ZST fields.
+fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
+    if let ItemKind::Union(data, _) = &item.kind {
+        data.fields().iter().filter(|f| !is_zst(cx, f.ty)).count() >= 2
+    } else {
+        false
+    }
+}
+
+fn is_zst(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) -> bool {
+    if hir_ty.span.from_expansion() {
+        return false;
+    }
+    let ty = hir_ty_to_ty(cx.tcx, hir_ty);
+    if let Ok(layout) = cx.layout_of(ty) {
+        layout.is_zst()
+    } else {
+        false
+    }
+}
+
+fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
+    cx.tcx.hir().attrs(hir_id).iter().any(|attr| {
+        if attr.has_name(sym::repr) {
+            if let Some(items) = attr.meta_item_list() {
+                for item in items {
+                    if item.is_word() && matches!(item.name_or_empty(), sym::C) {
+                        return true;
+                    }
+                }
+            }
+        }
+        false
+    })
+}
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index bf077a212fd..c0adab790f0 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
+use clippy_utils::sugg::has_enclosing_paren;
 use clippy_utils::ty::peel_mid_ty_refs;
 use clippy_utils::{get_parent_expr, get_parent_node, is_lint_allowed, path_to_local};
 use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
@@ -10,11 +11,10 @@ use rustc_hir::{
     Pat, PatKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
+use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{self, Ty, TyCtxt, TyS, TypeckResults};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{symbol::sym, Span};
-use std::iter;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -131,8 +131,6 @@ pub struct Dereferencing {
 struct StateData {
     /// Span of the top level expression
     span: Span,
-    /// The required mutability
-    target_mut: Mutability,
 }
 
 enum State {
@@ -141,9 +139,13 @@ enum State {
         // The number of calls in a sequence which changed the referenced type
         ty_changed_count: usize,
         is_final_ufcs: bool,
+        /// The required mutability
+        target_mut: Mutability,
     },
     DerefedBorrow {
-        count: u32,
+        count: usize,
+        required_precedence: i8,
+        msg: &'static str,
     },
 }
 
@@ -214,59 +216,98 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
                                     1
                                 },
                                 is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
-                            },
-                            StateData {
-                                span: expr.span,
                                 target_mut,
                             },
+                            StateData { span: expr.span },
                         ));
                     },
                     RefOp::AddrOf => {
                         // Find the number of times the borrow is auto-derefed.
                         let mut iter = find_adjustments(cx.tcx, typeck, expr).iter();
-                        if let Some((i, adjust)) = iter.by_ref().enumerate().find_map(|(i, adjust)| {
-                            if !matches!(adjust.kind, Adjust::Deref(_)) {
-                                Some((i, adjust))
-                            } else if !adjust.target.is_ref() {
-                                // Add one to the number of references found.
-                                Some((i + 1, adjust))
+                        let mut deref_count = 0usize;
+                        let next_adjust = loop {
+                            match iter.next() {
+                                Some(adjust) => {
+                                    if !matches!(adjust.kind, Adjust::Deref(_)) {
+                                        break Some(adjust);
+                                    } else if !adjust.target.is_ref() {
+                                        deref_count += 1;
+                                        break iter.next();
+                                    }
+                                    deref_count += 1;
+                                },
+                                None => break None,
+                            };
+                        };
+
+                        // Determine the required number of references before any can be removed. In all cases the
+                        // reference made by the current expression will be removed. After that there are four cases to
+                        // handle.
+                        //
+                        // 1. Auto-borrow will trigger in the current position, so no further references are required.
+                        // 2. Auto-deref ends at a reference, or the underlying type, so one extra needs to be left to
+                        //    handle the automatically inserted re-borrow.
+                        // 3. Auto-deref hits a user-defined `Deref` impl, so at least one reference needs to exist to
+                        //    start auto-deref.
+                        // 4. If the chain of non-user-defined derefs ends with a mutable re-borrow, and re-borrow
+                        //    adjustments will not be inserted automatically, then leave one further reference to avoid
+                        //    moving a mutable borrow.
+                        //    e.g.
+                        //        fn foo<T>(x: &mut Option<&mut T>, y: &mut T) {
+                        //            let x = match x {
+                        //                // Removing the borrow will cause `x` to be moved
+                        //                Some(x) => &mut *x,
+                        //                None => y
+                        //            };
+                        //        }
+                        let deref_msg =
+                            "this expression creates a reference which is immediately dereferenced by the compiler";
+                        let borrow_msg = "this expression borrows a value the compiler would automatically borrow";
+
+                        let (required_refs, required_precedence, msg) = if is_auto_borrow_position(parent, expr.hir_id)
+                        {
+                            (1, PREC_POSTFIX, if deref_count == 1 { borrow_msg } else { deref_msg })
+                        } else if let Some(&Adjust::Borrow(AutoBorrow::Ref(_, mutability))) =
+                            next_adjust.map(|a| &a.kind)
+                        {
+                            if matches!(mutability, AutoBorrowMutability::Mut { .. })
+                                && !is_auto_reborrow_position(parent)
+                            {
+                                (3, 0, deref_msg)
                             } else {
-                                None
-                            }
-                        }) {
-                            // Found two consecutive derefs. At least one can be removed.
-                            if i > 1 {
-                                let target_mut = iter::once(adjust)
-                                    .chain(iter)
-                                    .find_map(|adjust| match adjust.kind {
-                                        Adjust::Borrow(AutoBorrow::Ref(_, m)) => Some(m.into()),
-                                        _ => None,
-                                    })
-                                    // This default should never happen. Auto-deref always reborrows.
-                                    .unwrap_or(Mutability::Not);
-                                self.state = Some((
-                                    // Subtract one for the current borrow expression, and one to cover the last
-                                    // reference which can't be removed (it's either reborrowed, or needed for
-                                    // auto-deref to happen).
-                                    State::DerefedBorrow {
-                                        count:
-                                            // Truncation here would require more than a `u32::MAX` level reference. The compiler
-                                            // does not support this.
-                                            #[allow(clippy::cast_possible_truncation)]
-                                            { i as u32 - 2 }
-                                    },
-                                    StateData {
-                                        span: expr.span,
-                                        target_mut,
-                                    },
-                                ));
+                                (2, 0, deref_msg)
                             }
+                        } else {
+                            (2, 0, deref_msg)
+                        };
+
+                        if deref_count >= required_refs {
+                            self.state = Some((
+                                State::DerefedBorrow {
+                                    // One of the required refs is for the current borrow expression, the remaining ones
+                                    // can't be removed without breaking the code. See earlier comment.
+                                    count: deref_count - required_refs,
+                                    required_precedence,
+                                    msg,
+                                },
+                                StateData { span: expr.span },
+                            ));
                         }
                     },
                     _ => (),
                 }
             },
-            (Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method(_)) => {
+            (
+                Some((
+                    State::DerefMethod {
+                        target_mut,
+                        ty_changed_count,
+                        ..
+                    },
+                    data,
+                )),
+                RefOp::Method(_),
+            ) => {
                 self.state = Some((
                     State::DerefMethod {
                         ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) {
@@ -275,12 +316,30 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
                             ty_changed_count + 1
                         },
                         is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
+                        target_mut,
                     },
                     data,
                 ));
             },
-            (Some((State::DerefedBorrow { count }, data)), RefOp::AddrOf) if count != 0 => {
-                self.state = Some((State::DerefedBorrow { count: count - 1 }, data));
+            (
+                Some((
+                    State::DerefedBorrow {
+                        count,
+                        required_precedence,
+                        msg,
+                    },
+                    data,
+                )),
+                RefOp::AddrOf,
+            ) if count != 0 => {
+                self.state = Some((
+                    State::DerefedBorrow {
+                        count: count - 1,
+                        required_precedence,
+                        msg,
+                    },
+                    data,
+                ));
             },
 
             (Some((state, data)), _) => report(cx, expr, state, data),
@@ -361,7 +420,7 @@ fn try_parse_ref_op<'tcx>(
     expr: &'tcx Expr<'_>,
 ) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
     let (def_id, arg) = match expr.kind {
-        ExprKind::MethodCall(_, _, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
+        ExprKind::MethodCall(_, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
         ExprKind::Call(
             Expr {
                 kind: ExprKind::Path(path),
@@ -408,7 +467,7 @@ fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId,
     match parent.kind {
         // Leave deref calls in the middle of a method chain.
         // e.g. x.deref().foo()
-        ExprKind::MethodCall(_, _, [self_arg, ..], _) if self_arg.hir_id == child_id => false,
+        ExprKind::MethodCall(_, [self_arg, ..], _) if self_arg.hir_id == child_id => false,
 
         // Leave deref calls resulting in a called function
         // e.g. (x.deref())()
@@ -449,13 +508,36 @@ fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId,
         | ExprKind::Continue(..)
         | ExprKind::Ret(..)
         | ExprKind::InlineAsm(..)
-        | ExprKind::LlvmInlineAsm(..)
         | ExprKind::Struct(..)
         | ExprKind::Repeat(..)
         | ExprKind::Yield(..) => true,
     }
 }
 
+/// Checks if the given expression is in a position which can be auto-reborrowed.
+/// Note: This is only correct assuming auto-deref is already occurring.
+fn is_auto_reborrow_position(parent: Option<Node<'_>>) -> bool {
+    match parent {
+        Some(Node::Expr(parent)) => matches!(parent.kind, ExprKind::MethodCall(..) | ExprKind::Call(..)),
+        Some(Node::Local(_)) => true,
+        _ => false,
+    }
+}
+
+/// Checks if the given expression is a position which can auto-borrow.
+fn is_auto_borrow_position(parent: Option<Node<'_>>, child_id: HirId) -> bool {
+    if let Some(Node::Expr(parent)) = parent {
+        match parent.kind {
+            ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id,
+            ExprKind::Field(..) => true,
+            ExprKind::Call(f, _) => f.hir_id == child_id,
+            _ => false,
+        }
+    } else {
+        false
+    }
+}
+
 /// Adjustments are sometimes made in the parent block rather than the expression itself.
 fn find_adjustments<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -504,6 +586,7 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData)
         State::DerefMethod {
             ty_changed_count,
             is_final_ufcs,
+            target_mut,
         } => {
             let mut app = Applicability::MachineApplicable;
             let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
@@ -518,12 +601,12 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData)
             };
             let addr_of_str = if ty_changed_count < ref_count {
                 // Check if a reborrow from &mut T -> &T is required.
-                if data.target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) {
+                if target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) {
                     "&*"
                 } else {
                     ""
                 }
-            } else if data.target_mut == Mutability::Mut {
+            } else if target_mut == Mutability::Mut {
                 "&mut "
             } else {
                 "&"
@@ -539,7 +622,7 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData)
                 cx,
                 EXPLICIT_DEREF_METHODS,
                 data.span,
-                match data.target_mut {
+                match target_mut {
                     Mutability::Not => "explicit `deref` method call",
                     Mutability::Mut => "explicit `deref_mut` method call",
                 },
@@ -548,19 +631,24 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData)
                 app,
             );
         },
-        State::DerefedBorrow { .. } => {
+        State::DerefedBorrow {
+            required_precedence,
+            msg,
+            ..
+        } => {
             let mut app = Applicability::MachineApplicable;
             let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0;
             span_lint_and_sugg(
                 cx,
                 NEEDLESS_BORROW,
                 data.span,
-                &format!(
-                    "this expression borrows a reference (`{}`) that is immediately dereferenced by the compiler",
-                    cx.typeck_results().expr_ty(expr),
-                ),
+                msg,
                 "change this to",
-                snip.into(),
+                if required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) {
+                    format!("({})", snip)
+                } else {
+                    snip.into()
+                },
                 app,
             );
         },
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 097cb65f56e..6d3df260ca2 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -3,12 +3,12 @@ use clippy_utils::paths;
 use clippy_utils::ty::{implements_trait, is_copy};
 use clippy_utils::{get_trait_def_id, is_automatically_derived, is_lint_allowed, match_def_path};
 use if_chain::if_chain;
-use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
 use rustc_hir::{
     BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -382,7 +382,7 @@ struct UnsafeVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
     fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, span: Span, id: HirId) {
         if self.has_unsafe {
@@ -414,7 +414,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
         walk_expr(self, expr);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs
index 3c3f3631849..0c27c3f9255 100644
--- a/clippy_lints/src/disallowed_script_idents.rs
+++ b/clippy_lints/src/disallowed_script_idents.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_lint::{EarlyContext, EarlyLintPass, Level};
+use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use unicode_script::{Script, UnicodeScript};
 
@@ -72,7 +72,7 @@ impl EarlyLintPass for DisallowedScriptIdents {
             return;
         }
 
-        let symbols = cx.sess.parse_sess.symbol_gallery.symbols.lock();
+        let symbols = cx.sess().parse_sess.symbol_gallery.symbols.lock();
         // Sort by `Span` so that error messages make sense with respect to the
         // order of identifier locations in the code.
         let mut symbols: Vec<_> = symbols.iter().collect();
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index cb7d5ac7394..a00361e6062 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -13,10 +13,10 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::EmitterWriter;
 use rustc_errors::{Applicability, Handler, SuggestionStyle};
 use rustc_hir as hir;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AnonConst, Expr};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_parse::maybe_new_parser_from_source_str;
@@ -799,7 +799,7 @@ struct FindPanicUnwrap<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if self.panic_span.is_some() {
@@ -834,7 +834,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
     // 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 nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs
index 50dd0d84fda..24e32c09f44 100644
--- a/clippy_lints/src/duration_subsec.rs
+++ b/clippy_lints/src/duration_subsec.rs
@@ -45,7 +45,7 @@ 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, .. }, left, right) = expr.kind;
-            if let ExprKind::MethodCall(method_path, _ , args, _) = left.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/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs
index 92c56c762aa..0b9f54231c5 100644
--- a/clippy_lints/src/else_if_without_else.rs
+++ b/clippy_lints/src/else_if_without_else.rs
@@ -2,7 +2,7 @@
 
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -50,7 +50,7 @@ declare_lint_pass!(ElseIfWithoutElse => [ELSE_IF_WITHOUT_ELSE]);
 
 impl EarlyLintPass for ElseIfWithoutElse {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) {
-        if in_external_macro(cx.sess, item.span) {
+        if in_external_macro(cx.sess(), item.span) {
             return;
         }
 
diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index 3ce239273e2..1ae2e20c1e0 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -10,7 +10,7 @@ use core::fmt::Write;
 use rustc_errors::Applicability;
 use rustc_hir::{
     hir_id::HirIdSet,
-    intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
+    intravisit::{walk_expr, Visitor},
     Block, Expr, ExprKind, Guard, HirId, Pat, Stmt, StmtKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass};
@@ -245,7 +245,6 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
     match expr.kind {
         ExprKind::MethodCall(
             _,
-            _,
             [
                 map,
                 Expr {
@@ -281,7 +280,7 @@ struct InsertExpr<'tcx> {
     value: &'tcx Expr<'tcx>,
 }
 fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
-    if let ExprKind::MethodCall(_, _, [map, key, value], _) = expr.kind {
+    if let ExprKind::MethodCall(_, [map, key, value], _) = expr.kind {
         let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
         if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
             Some(InsertExpr { map, key, value })
@@ -370,11 +369,6 @@ impl<'tcx> InsertSearcher<'_, 'tcx> {
     }
 }
 impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
-    type Map = ErasedMap<'tcx>;
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         match stmt.kind {
             StmtKind::Semi(e) => {
@@ -504,7 +498,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                     self.loops.pop();
                 },
                 ExprKind::Block(block, _) => self.visit_block(block),
-                ExprKind::InlineAsm(_) | ExprKind::LlvmInlineAsm(_) => {
+                ExprKind::InlineAsm(_) => {
                     self.can_use_entry = false;
                 },
                 _ => {
diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index bc5d2f6278d..af591dd71aa 100644
--- a/clippy_lints/src/escape.rs
+++ b/clippy_lints/src/escape.rs
@@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
         }
 
         let parent_id = cx.tcx.hir().get_parent_item(hir_id);
-        let parent_node = cx.tcx.hir().find(parent_id);
+        let parent_node = cx.tcx.hir().find_by_def_id(parent_id);
 
         let mut trait_self_ty = None;
         if let Some(Node::Item(item)) = parent_node {
@@ -175,8 +175,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
                 // skip if there is a `self` parameter binding to a type
                 // that contains `Self` (i.e.: `self: Box<Self>`), see #4804
                 if let Some(trait_self_ty) = self.trait_self_ty {
-                    if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty)
-                    {
+                    if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(cmt.place.ty(), trait_self_ty) {
                         return;
                     }
                 }
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index b22515a3907..263bff4873c 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
         );
 
         if_chain!(
-            if let ExprKind::MethodCall(path, _, args, _) = body.value.kind;
+            if let ExprKind::MethodCall(path, args, _) = body.value.kind;
             if check_inputs(cx, body.params, args);
             let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap();
             let substs = cx.typeck_results().node_substs(body.value.hir_id);
diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs
index cdac9f3e6e1..65599a0587d 100644
--- a/clippy_lints/src/eval_order_dependence.rs
+++ b/clippy_lints/src/eval_order_dependence.rs
@@ -1,10 +1,9 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
 use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
 use if_chain::if_chain;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -133,8 +132,6 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
             ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e),
@@ -167,9 +164,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
     fn visit_block(&mut self, _: &'tcx Block<'_>) {
         // don't continue over blocks, LateLintPass already does that
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Walks up the AST from the given write expression (`vis.write_expr`) looking
@@ -299,8 +293,6 @@ struct ReadVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if expr.hir_id == self.last_expr.hir_id {
             return;
@@ -343,9 +335,6 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
 
         walk_expr(self, expr);
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`.
diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs
index d64cc61916c..cbf52d19334 100644
--- a/clippy_lints/src/exit.rs
+++ b/clippy_lints/src/exit.rs
@@ -34,11 +34,10 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
             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 let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(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());
+            if !is_entrypoint_fn(cx, parent.to_def_id());
             then {
                 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 98e5234e0aa..f326fd83d18 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -35,10 +35,10 @@ 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(unwrap_fun, _, [write_call], _) = expr.kind;
+            if let ExprKind::MethodCall(unwrap_fun, [write_call], _) = expr.kind;
             if unwrap_fun.ident.name == sym::unwrap;
             // match call to write_fmt
-            if let ExprKind::MethodCall(write_fun, _, [write_recv, write_arg], _) = write_call.kind;
+            if let ExprKind::MethodCall(write_fun, [write_recv, write_arg], _) = write_call.kind;
             if write_fun.ident.name == sym!(write_fmt);
             // match calls to std::io::stdout() / std::io::stderr ()
             if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs
index 02f1baf27fa..574678b5542 100644
--- a/clippy_lints/src/fallible_impl_from.rs
+++ b/clippy_lints/src/fallible_impl_from.rs
@@ -5,7 +5,6 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
@@ -68,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
 }
 
 fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef]) {
-    use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+    use rustc_hir::intravisit::{self, Visitor};
     use rustc_hir::{Expr, ImplItemKind};
 
     struct FindPanicUnwrap<'a, 'tcx> {
@@ -78,8 +77,6 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h
     }
 
     impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
-        type Map = Map<'tcx>;
-
         fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
             if let Some(macro_call) = root_macro_call_first_node(self.lcx, expr) {
                 if is_panic(self.lcx, macro_call.def_id) {
@@ -100,10 +97,6 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h
             // and check sub-expressions
             intravisit::walk_expr(self, expr);
         }
-
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
     }
 
     for impl_item in impl_items {
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index 6dcbaf68dfd..79ce53f7a5f 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -303,7 +303,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
         if value == Int(2) {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 if let Some(grandparent) = get_parent_expr(cx, parent) {
-                    if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind {
+                    if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = grandparent.kind {
                         if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
                             return;
                         }
@@ -364,13 +364,11 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
         if_chain! {
             if let ExprKind::MethodCall(
                 PathSegment { ident: lmethod_name, .. },
-                _lspan,
                 [largs_0, largs_1, ..],
                 _
             ) = &add_lhs.kind;
             if let ExprKind::MethodCall(
                 PathSegment { ident: rmethod_name, .. },
-                _rspan,
                 [rargs_0, rargs_1, ..],
                 _
             ) = &add_rhs.kind;
@@ -409,7 +407,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
         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(path, _, [self_arg, ..], _) = &lhs.kind;
+        if let ExprKind::MethodCall(path, [self_arg, ..], _) = &lhs.kind;
         if cx.typeck_results().expr_ty(self_arg).is_floating_point();
         if path.ident.name.as_str() == "exp";
         then {
@@ -453,7 +451,7 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
     ) = &expr.kind
     {
         if let Some(parent) = get_parent_expr(cx, expr) {
-            if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = parent.kind {
+            if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = parent.kind {
                 if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
                     return;
                 }
@@ -589,8 +587,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, .. }, _, args_a, _) = expr_a.kind;
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, 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() &&
@@ -615,8 +613,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
             rhs,
         ) = &expr.kind;
         if are_same_base_logs(cx, lhs, rhs);
-        if let ExprKind::MethodCall(_, _, [largs_self, ..], _) = &lhs.kind;
-        if let ExprKind::MethodCall(_, _, [rargs_self, ..], _) = &rhs.kind;
+        if let ExprKind::MethodCall(_, [largs_self, ..], _) = &lhs.kind;
+        if let ExprKind::MethodCall(_, [rargs_self, ..], _) = &rhs.kind;
         then {
             span_lint_and_sugg(
                 cx,
@@ -714,7 +712,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
             return;
         }
 
-        if let ExprKind::MethodCall(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_args.rs b/clippy_lints/src/format_args.rs
index ae423d799d7..17b0749a4a9 100644
--- a/clippy_lints/src/format_args.rs
+++ b/clippy_lints/src/format_args.rs
@@ -149,7 +149,7 @@ fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symb
 fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) {
     if_chain! {
         if !value.span.from_expansion();
-        if let ExprKind::MethodCall(_, _, [receiver], _) = value.kind;
+        if let ExprKind::MethodCall(_, [receiver], _) = value.kind;
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id);
         if is_diag_trait_item(cx, method_def_id, sym::ToString);
         let receiver_ty = cx.typeck_results().expr_ty(receiver);
diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs
index 3e85c8a9c80..ae18f8081bc 100644
--- a/clippy_lints/src/formatting.rs
+++ b/clippy_lints/src/formatting.rs
@@ -3,7 +3,7 @@ use clippy_utils::differing_macro_contexts;
 use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -207,7 +207,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
         if let ExprKind::If(_, then, Some(else_)) = &expr.kind;
         if is_block(else_) || is_if(else_);
         if !differing_macro_contexts(then.span, else_.span);
-        if !then.span.from_expansion() && !in_external_macro(cx.sess, expr.span);
+        if !then.span.from_expansion() && !in_external_macro(cx.sess(), expr.span);
 
         // workaround for rust-lang/rust#43081
         if expr.span.lo().0 != 0 && expr.span.hi().0 != 0;
@@ -259,7 +259,7 @@ fn has_unary_equivalent(bin_op: BinOpKind) -> bool {
 }
 
 fn indentation(cx: &EarlyContext<'_>, span: Span) -> usize {
-    cx.sess.source_map().lookup_char_pos(span.lo()).col.0
+    cx.sess().source_map().lookup_char_pos(span.lo()).col.0
 }
 
 /// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array
diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs
index 5ece2cc5ac4..c2f52605151 100644
--- a/clippy_lints/src/from_over_into.rs
+++ b/clippy_lints/src/from_over_into.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::{meets_msrv, msrvs};
 use if_chain::if_chain;
 use rustc_hir as hir;
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::sym;
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index f2b4aefaead..3e3718b9445 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -4,7 +4,6 @@ use rustc_hir::def_id::{DefIdSet, LocalDefId};
 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},
 };
@@ -48,7 +47,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         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() {
+        } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id).is_none() {
             check_must_use_candidate(
                 cx,
                 sig.decl,
@@ -211,8 +210,6 @@ struct StaticMutVisitor<'a, 'tcx> {
 }
 
 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};
 
@@ -220,7 +217,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
             return;
         }
         match expr.kind {
-            Call(_, args) | MethodCall(_, _, args, _) => {
+            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())
@@ -244,10 +241,6 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
             _ => {},
         }
     }
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
 }
 
 fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 834f6d2425e..830e3b32cfa 100644
--- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -1,6 +1,6 @@
 use rustc_hir::{self as hir, intravisit, HirIdSet};
 use rustc_lint::LateContext;
-use rustc_middle::{hir::map::Map, ty};
+use rustc_middle::ty;
 use rustc_span::def_id::LocalDefId;
 
 use clippy_utils::diagnostics::span_lint;
@@ -77,8 +77,6 @@ struct DerefVisitor<'a, '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) => {
@@ -90,7 +88,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
                     }
                 }
             },
-            hir::ExprKind::MethodCall(_, _, args, _) => {
+            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);
 
@@ -106,10 +104,6 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
 
         intravisit::walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
 }
 
 impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
diff --git a/clippy_lints/src/functions/result_unit_err.rs b/clippy_lints/src/functions/result_unit_err.rs
index 73f08a04989..120fcb2619c 100644
--- a/clippy_lints/src/functions/result_unit_err.rs
+++ b/clippy_lints/src/functions/result_unit_err.rs
@@ -27,7 +27,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &hir::ImplItem<'_>) {
     if let hir::ImplItemKind::Fn(ref sig, _) = item.kind {
         let is_public = cx.access_levels.is_exported(item.def_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() {
+        if is_public && trait_ref_of_method(cx, item.def_id).is_none() {
             check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
         }
     }
diff --git a/clippy_lints/src/get_last_with_len.rs b/clippy_lints/src/get_last_with_len.rs
index edca701869e..df29d9308e7 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(path, _, args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, args, _) = expr.kind;
 
             // Method name is "get"
             if path.ident.name == sym!(get);
@@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for GetLastWithLen {
             ) = &get_index_arg.kind;
 
             // LHS of subtraction is "x.len()"
-            if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args, _) = &lhs.kind;
+            if let ExprKind::MethodCall(arg_lhs_path, lhs_args, _) = &lhs.kind;
             if arg_lhs_path.ident.name == sym::len;
             if let Some(arg_lhs_struct) = lhs_args.get(0);
 
diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs
index e20741d2407..e9501700784 100644
--- a/clippy_lints/src/if_let_mutex.rs
+++ b/clippy_lints/src/if_let_mutex.rs
@@ -3,10 +3,9 @@ use clippy_utils::higher;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::SpanlessEq;
 use if_chain::if_chain;
-use rustc_hir::intravisit::{self as visit, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self as visit, Visitor};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
@@ -91,8 +90,6 @@ pub struct OppVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if let Some(mutex) = is_mutex_lock_call(self.cx, expr) {
             self.found_mutex = Some(mutex);
@@ -101,10 +98,6 @@ impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> {
         }
         visit::walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Checks if `Mutex::lock` is called in any of the branches.
@@ -115,8 +108,6 @@ pub struct ArmVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if let Some(mutex) = is_mutex_lock_call(self.cx, expr) {
             self.found_mutex = Some(mutex);
@@ -125,10 +116,6 @@ impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> {
         }
         visit::walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
@@ -140,7 +127,7 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
 
 fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if_chain! {
-        if let ExprKind::MethodCall(path, _span, [self_arg, ..], _) = &expr.kind;
+        if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
         if path.ident.as_str() == "lock";
         let ty = cx.typeck_results().expr_ty(self_arg);
         if is_type_diagnostic_item(cx, ty, sym::Mutex);
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index 6358228dd47..eed25e9bc0e 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -3,10 +3,10 @@ use std::collections::BTreeMap;
 
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, 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::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{Ty, TyS, TypeckResults};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -179,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                             )
                             .and_then(|snip| {
                                 let i = snip.find("fn")?;
-                                Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
+                                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.ctxt(), item.span.parent())
@@ -294,8 +294,6 @@ impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
 }
 
 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);
@@ -311,10 +309,6 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
 
         walk_inf(self, inf);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Looks for default-hasher-dependent constructors like `HashMap::new`.
@@ -337,7 +331,7 @@ impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     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()));
@@ -389,7 +383,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't
         walk_expr(self, e);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs
index 073313e2bad..66765210698 100644
--- a/clippy_lints/src/index_refutable_slice.rs
+++ b/clippy_lints/src/index_refutable_slice.rs
@@ -7,9 +7,9 @@ use if_chain::if_chain;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -230,10 +230,10 @@ struct SliceIndexLintingVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs
index c7db47a552b..3008e86ef8b 100644
--- a/clippy_lints/src/infinite_iter.rs
+++ b/clippy_lints/src/infinite_iter.rs
@@ -145,7 +145,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
 
 fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(method, _, 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 {
@@ -221,7 +221,7 @@ const INFINITE_COLLECTORS: &[Symbol] = &[
 
 fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(method, _, 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]);
diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs
index 60d234cd6f0..55c04a1186f 100644
--- a/clippy_lints/src/inherent_to_string.rs
+++ b/clippy_lints/src/inherent_to_string.rs
@@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
             if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);
 
             // Filters instances of to_string which are required by a trait
-            if trait_ref_of_method(cx, impl_item.hir_id()).is_none();
+            if trait_ref_of_method(cx, impl_item.def_id).is_none();
 
             then {
                 show_lint(cx, impl_item);
diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs
index b118d3c8b87..cdefe627efd 100644
--- a/clippy_lints/src/items_after_statements.rs
+++ b/clippy_lints/src/items_after_statements.rs
@@ -2,7 +2,7 @@
 
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Block, ItemKind, StmtKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -55,7 +55,7 @@ declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]);
 
 impl EarlyLintPass for ItemsAfterStatements {
     fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
-        if in_external_macro(cx.sess, item.span) {
+        if in_external_macro(cx.sess(), item.span) {
             return;
         }
 
@@ -69,7 +69,7 @@ impl EarlyLintPass for ItemsAfterStatements {
         // lint on all further items
         for stmt in stmts {
             if let StmtKind::Item(ref it) = *stmt {
-                if in_external_macro(cx.sess, it.span) {
+                if in_external_macro(cx.sess(), it.span) {
                     return;
                 }
                 if let ItemKind::MacroDef(..) = it.kind {
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index e1168c3f602..530b0a90ebd 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -370,7 +370,7 @@ fn check_for_is_empty(
 }
 
 fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
-    if let (&ExprKind::MethodCall(method_path, _, 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" {
diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs
index d03276f7f98..cb1ef01f5ba 100644
--- a/clippy_lints/src/let_underscore.rs
+++ b/clippy_lints/src/let_underscore.rs
@@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
             if let Some(init) = local.init;
             then {
                 let init_ty = cx.typeck_results().expr_ty(init);
-                let contains_sync_guard = init_ty.walk(cx.tcx).any(|inner| match inner.unpack() {
+                let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
                     GenericArgKind::Type(inner_ty) => {
                         SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
                     },
diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs
index 87fd7f99748..4721b7f2b47 100644
--- a/clippy_lints/src/lib.register_all.rs
+++ b/clippy_lints/src/lib.register_all.rs
@@ -247,7 +247,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     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),
diff --git a/clippy_lints/src/lib.register_complexity.rs b/clippy_lints/src/lib.register_complexity.rs
index a21ddf73a11..bd5ff613447 100644
--- a/clippy_lints/src/lib.register_complexity.rs
+++ b/clippy_lints/src/lib.register_complexity.rs
@@ -71,7 +71,6 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
     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(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs
index 56146a0fd3a..e5e1c052c15 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -92,6 +92,7 @@ store.register_lints(&[
     default::DEFAULT_TRAIT_ACCESS,
     default::FIELD_REASSIGN_WITH_DEFAULT,
     default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK,
+    default_union_representation::DEFAULT_UNION_REPRESENTATION,
     dereference::EXPLICIT_DEREF_METHODS,
     dereference::NEEDLESS_BORROW,
     dereference::REF_BINDING_TO_REFERENCE,
@@ -423,7 +424,6 @@ store.register_lints(&[
     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,
diff --git a/clippy_lints/src/lib.register_restriction.rs b/clippy_lints/src/lib.register_restriction.rs
index e7e2798da7d..5a89fdb05a9 100644
--- a/clippy_lints/src/lib.register_restriction.rs
+++ b/clippy_lints/src/lib.register_restriction.rs
@@ -12,6 +12,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
     LintId::of(create_dir::CREATE_DIR),
     LintId::of(dbg_macro::DBG_MACRO),
     LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK),
+    LintId::of(default_union_representation::DEFAULT_UNION_REPRESENTATION),
     LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS),
     LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
     LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index ed25d6fd297..9d42185dc0e 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -189,6 +189,7 @@ mod create_dir;
 mod dbg_macro;
 mod default;
 mod default_numeric_fallback;
+mod default_union_representation;
 mod dereference;
 mod derivable_impls;
 mod derive;
@@ -703,7 +704,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(mut_key::MutableKeyType));
     store.register_late_pass(|| Box::new(modulo_arithmetic::ModuloArithmetic));
     store.register_early_pass(|| Box::new(reference::DerefAddrOf));
-    store.register_early_pass(|| Box::new(reference::RefInDeref));
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
     store.register_late_pass(|| Box::new(to_string_in_display::ToStringInDisplay::new()));
     store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
@@ -860,6 +860,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
     store.register_late_pass(move || Box::new(borrow_as_ptr::BorrowAsPtr::new(msrv)));
     store.register_late_pass(move || Box::new(manual_bits::ManualBits::new(msrv)));
+    store.register_late_pass(|| Box::new(default_union_representation::DefaultUnionRepresentation));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
@@ -935,6 +936,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
     ls.register_renamed("clippy::if_let_some_result", "clippy::match_result_ok");
     ls.register_renamed("clippy::disallowed_type", "clippy::disallowed_types");
     ls.register_renamed("clippy::disallowed_method", "clippy::disallowed_methods");
+    ls.register_renamed("clippy::ref_in_deref", "clippy::needless_borrow");
 
     // uplifted lints
     ls.register_renamed("clippy::invalid_ref", "invalid_value");
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index 0e2b78609c2..b09c23f31e9 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -2,8 +2,7 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::trait_ref_of_method;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::intravisit::{
-    walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty,
-    NestedVisitorMap, Visitor,
+    walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty, Visitor,
 };
 use rustc_hir::FnRetTy::Return;
 use rustc_hir::{
@@ -12,10 +11,9 @@ use rustc_hir::{
     TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
 };
 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;
-use rustc_span::symbol::{kw, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -85,17 +83,18 @@ 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), None, generics, item.span, true);
         }
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
         if let ImplItemKind::Fn(ref sig, id) = item.kind {
-            let report_extra_lifetimes = trait_ref_of_method(cx, item.hir_id()).is_none();
+            let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id).is_none();
             check_fn_inner(
                 cx,
                 sig.decl,
                 Some(id),
+                None,
                 &item.generics,
                 item.span,
                 report_extra_lifetimes,
@@ -105,11 +104,11 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
         if let TraitItemKind::Fn(ref sig, ref body) = item.kind {
-            let body = match *body {
-                TraitFn::Required(_) => None,
-                TraitFn::Provided(id) => Some(id),
+            let (body, trait_sig) = match *body {
+                TraitFn::Required(sig) => (None, Some(sig)),
+                TraitFn::Provided(id) => (Some(id), None),
             };
-            check_fn_inner(cx, sig.decl, body, &item.generics, item.span, true);
+            check_fn_inner(cx, sig.decl, body, trait_sig, &item.generics, item.span, true);
         }
     }
 }
@@ -126,6 +125,7 @@ fn check_fn_inner<'tcx>(
     cx: &LateContext<'tcx>,
     decl: &'tcx FnDecl<'_>,
     body: Option<BodyId>,
+    trait_sig: Option<&[Ident]>,
     generics: &'tcx Generics<'_>,
     span: Span,
     report_extra_lifetimes: bool,
@@ -167,7 +167,7 @@ fn check_fn_inner<'tcx>(
             }
         }
     }
-    if could_use_elision(cx, decl, body, generics.params) {
+    if could_use_elision(cx, decl, body, trait_sig, generics.params) {
         span_lint(
             cx,
             NEEDLESS_LIFETIMES,
@@ -181,10 +181,31 @@ fn check_fn_inner<'tcx>(
     }
 }
 
+// elision doesn't work for explicit self types, see rust-lang/rust#69064
+fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
+    if_chain! {
+        if let Some(ident) = ident;
+        if ident.name == kw::SelfLower;
+        if !func.implicit_self.has_implicit_self();
+
+        if let Some(self_ty) = func.inputs.first();
+        then {
+            let mut visitor = RefVisitor::new(cx);
+            visitor.visit_ty(self_ty);
+
+            !visitor.all_lts().is_empty()
+        }
+        else {
+            false
+        }
+    }
+}
+
 fn could_use_elision<'tcx>(
     cx: &LateContext<'tcx>,
     func: &'tcx FnDecl<'_>,
     body: Option<BodyId>,
+    trait_sig: Option<&[Ident]>,
     named_generics: &'tcx [GenericParam<'_>],
 ) -> bool {
     // There are two scenarios where elision works:
@@ -235,11 +256,24 @@ fn could_use_elision<'tcx>(
     let input_lts = input_visitor.lts;
     let output_lts = output_visitor.lts;
 
+    if let Some(trait_sig) = trait_sig {
+        if explicit_self_type(cx, func, trait_sig.first().copied()) {
+            return false;
+        }
+    }
+
     if let Some(body_id) = body {
+        let body = cx.tcx.hir().body(body_id);
+
+        let first_ident = body.params.first().and_then(|param| param.pat.simple_ident());
+        if explicit_self_type(cx, func, first_ident) {
+            return false;
+        }
+
         let mut checker = BodyLifetimeChecker {
             lifetimes_used_in_body: false,
         };
-        checker.visit_expr(&cx.tcx.hir().body(body_id).value);
+        checker.visit_expr(&body.value);
         if checker.lifetimes_used_in_body {
             return false;
         }
@@ -354,8 +388,6 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
         self.record(&Some(*lifetime));
@@ -409,9 +441,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
         }
         walk_ty(self, ty);
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
@@ -457,8 +486,6 @@ struct LifetimeChecker {
 }
 
 impl<'tcx> Visitor<'tcx> for LifetimeChecker {
-    type Map = Map<'tcx>;
-
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
         self.map.remove(&lifetime.name.ident().name);
@@ -474,9 +501,6 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
             walk_generic_param(self, param);
         }
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, generics: &'tcx Generics<'_>) {
@@ -508,16 +532,10 @@ struct BodyLifetimeChecker {
 }
 
 impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
-    type Map = Map<'tcx>;
-
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
         if lifetime.name.ident().name != kw::Empty && lifetime.name.ident().name != kw::StaticLifetime {
             self.lifetimes_used_in_body = true;
         }
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index 130543bbbee..b7430f49229 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/clippy_lints/src/literal_representation.rs
@@ -7,7 +7,7 @@ use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use std::iter;
@@ -225,7 +225,7 @@ impl_lint_pass!(LiteralDigitGrouping => [
 
 impl EarlyLintPass for LiteralDigitGrouping {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
 
@@ -418,7 +418,7 @@ impl_lint_pass!(DecimalLiteralRepresentation => [DECIMAL_LITERAL_REPRESENTATION]
 
 impl EarlyLintPass for DecimalLiteralRepresentation {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
 
diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs
index 48c4015e07b..ef0221639aa 100644
--- a/clippy_lints/src/loops/manual_memcpy.rs
+++ b/clippy_lints/src/loops/manual_memcpy.rs
@@ -119,7 +119,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
 
     let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
         if_chain! {
-            if let ExprKind::MethodCall(method, _, len_args, _) = end.kind;
+            if let ExprKind::MethodCall(method, len_args, _) = end.kind;
             if method.ident.name == sym::len;
             if len_args.len() == 1;
             if let Some(arg) = len_args.get(0);
@@ -343,7 +343,7 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti
 
 fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
     if_chain! {
-        if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
+        if let ExprKind::MethodCall(method, args, _) = expr.kind;
         if method.ident.name == sym::clone;
         if args.len() == 1;
         if let Some(arg) = args.get(0);
diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index b03445b8cd6..5bc32acf56e 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/clippy_lints/src/loops/mod.rs
@@ -658,7 +658,7 @@ fn check_for_loop<'tcx>(
 fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
     let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
 
-    if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind {
+    if let ExprKind::MethodCall(method, [self_arg], _) = arg.kind {
         let method_name = method.ident.as_str();
         // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
         match method_name {
diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs
index 37a57d8feb1..9d8679d77c6 100644
--- a/clippy_lints/src/loops/mut_range_bound.rs
+++ b/clippy_lints/src/loops/mut_range_bound.rs
@@ -2,11 +2,10 @@ use super::MUT_RANGE_BOUND;
 use clippy_utils::diagnostics::span_lint_and_note;
 use clippy_utils::{get_enclosing_block, higher, path_to_local};
 use if_chain::if_chain;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
 use rustc_middle::{mir::FakeReadCause, ty};
 use rustc_span::source_map::Span;
 use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@@ -148,12 +147,6 @@ impl BreakAfterExprVisitor {
 }
 
 impl<'tcx> intravisit::Visitor<'tcx> for BreakAfterExprVisitor {
-    type Map = Map<'tcx>;
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if self.past_candidate {
             return;
diff --git a/clippy_lints/src/loops/needless_collect.rs b/clippy_lints/src/loops/needless_collect.rs
index 6248680aa62..f57dcc2f5c4 100644
--- a/clippy_lints/src/loops/needless_collect.rs
+++ b/clippy_lints/src/loops/needless_collect.rs
@@ -7,10 +7,10 @@ use clippy_utils::{can_move_expr_to_closure, is_trait_method, path_to_local, pat
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, HirId, HirIdSet, Local, Mutability, Node, PatKind, Stmt, StmtKind};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, TyS};
 use rustc_span::sym;
@@ -24,8 +24,8 @@ 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(method, _, args, _) = expr.kind;
-        if let ExprKind::MethodCall(chain_method, method0_span, _, _) = args[0].kind;
+        if let ExprKind::MethodCall(method, args, _) = expr.kind;
+        if let ExprKind::MethodCall(chain_method, _, _) = args[0].kind;
         if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
         then {
             let ty = cx.typeck_results().expr_ty(&args[0]);
@@ -62,7 +62,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
             span_lint_and_sugg(
                 cx,
                 NEEDLESS_COLLECT,
-                method0_span.with_hi(expr.span.hi()),
+                chain_method.ident.span.with_hi(expr.span.hi()),
                 NEEDLESS_COLLECT_MSG,
                 "replace with",
                 sugg,
@@ -79,7 +79,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                 if let StmtKind::Local(local) = stmt.kind;
                 if let PatKind::Binding(_, id, ..) = local.pat.kind;
                 if let Some(init_expr) = local.init;
-                if let ExprKind::MethodCall(method_name, collect_span, &[ref iter_source], ..) = init_expr.kind;
+                if let ExprKind::MethodCall(method_name, &[ref iter_source], ..) = init_expr.kind;
                 if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
                 let ty = cx.typeck_results().expr_ty(init_expr);
                 if is_type_diagnostic_item(cx, ty, sym::Vec) ||
@@ -101,7 +101,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                     }
 
                     // Suggest replacing iter_call with iter_replacement, and removing stmt
-                    let mut span = MultiSpan::from_span(collect_span);
+                    let mut span = MultiSpan::from_span(method_name.ident.span);
                     span.push_span_label(iter_call.span, "the iterator could be used here instead".into());
                     span_lint_hir_and_then(
                         cx,
@@ -193,7 +193,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // Check function calls on our collection
-        if let ExprKind::MethodCall(method_name, _, [recv, args @ ..], _) = &expr.kind {
+        if let ExprKind::MethodCall(method_name, [recv, args @ ..], _) = &expr.kind {
             if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) {
                 self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
                 self.visit_expr(recv);
@@ -262,11 +262,6 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
             walk_expr(self, expr);
         }
     }
-
-    type Map = Map<'tcx>;
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 impl<'tcx> IterFunctionVisitor<'_, 'tcx> {
@@ -298,7 +293,7 @@ struct UsedCountVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if path_to_local_id(expr, self.id) {
@@ -308,8 +303,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index 172d9fc39a2..9d335073e4f 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -8,10 +8,9 @@ use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
 use rustc_middle::middle::region;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Symbol};
@@ -58,8 +57,7 @@ pub(super) fn check<'tcx>(
 
                 // ensure that the indexed variable was declared before the loop, see #601
                 if let Some(indexed_extent) = indexed_extent {
-                    let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
-                    let parent_def_id = cx.tcx.hir().local_def_id(parent_id);
+                    let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
                     let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
                     let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id);
                     if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
@@ -188,7 +186,7 @@ pub(super) fn check<'tcx>(
 
 fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(method, _, 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(_, path)) = len_args[0].kind;
@@ -263,8 +261,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
                 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 parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
                         let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
                         if index_used_directly {
                             self.indexed_directly.insert(
@@ -296,12 +293,10 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             // a range index op
-            if let ExprKind::MethodCall(meth, _, [args_0, args_1, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(meth, [args_0, args_1, ..], _) = &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);
@@ -356,7 +351,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
                     self.visit_expr(expr);
                 }
             },
-            ExprKind::MethodCall(_, _, args, _) => {
+            ExprKind::MethodCall(_, args, _) => {
                 let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
                 for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) {
                     self.prefer_mutable = false;
@@ -376,7 +371,4 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
         }
         self.prefer_mutable = old;
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index bb1b3e2a1ec..a0b2302662e 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -121,7 +121,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         | ExprKind::Repeat(e, _)
         | ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id),
         ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, main_loop_id),
-        ExprKind::Array(es) | ExprKind::MethodCall(_, _, es, _) | ExprKind::Tup(es) => {
+        ExprKind::Array(es) | ExprKind::MethodCall(_, es, _) | ExprKind::Tup(es) => {
             never_loop_expr_all(&mut es.iter(), main_loop_id)
         },
         ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), main_loop_id),
@@ -181,7 +181,6 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         ExprKind::Struct(_, _, None)
         | ExprKind::Yield(_, _)
         | ExprKind::Closure(_, _, _, _, _)
-        | ExprKind::LlvmInlineAsm(_)
         | ExprKind::Path(_)
         | ExprKind::ConstBlock(_)
         | ExprKind::Lit(_)
diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs
index 2eb247de9f4..e048d744fc3 100644
--- a/clippy_lints/src/loops/same_item_push.rs
+++ b/clippy_lints/src/loops/same_item_push.rs
@@ -6,10 +6,9 @@ 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::intravisit::{walk_expr, Visitor};
 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;
 use std::iter::Iterator;
 
@@ -49,7 +48,7 @@ pub(super) fn check<'tcx>(
         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(cx.tcx).nth(1).unwrap().expect_ty();
+        let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
         if cx
             .tcx
             .lang_items()
@@ -134,8 +133,6 @@ impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         match &expr.kind {
             // Non-determinism may occur ... don't give a lint
@@ -175,10 +172,6 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
             }
         }
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 // Given some statement, determine if that statement is a push on a Vec. If it is, return
@@ -187,7 +180,7 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(&
     if_chain! {
             // Extract method being called
             if let StmtKind::Semi(semi_stmt) = &stmt.kind;
-            if let ExprKind::MethodCall(path, _, args, _) = &semi_stmt.kind;
+            if let ExprKind::MethodCall(path, args, _) = &semi_stmt.kind;
             // Figure out the parameters for the method call
             if let Some(self_expr) = args.get(0);
             if let Some(pushed_item) = args.get(1);
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs
index e39605f3e7d..15f419e4410 100644
--- a/clippy_lints/src/loops/single_element_loop.rs
+++ b/clippy_lints/src/loops/single_element_loop.rs
@@ -16,7 +16,7 @@ pub(super) fn check<'tcx>(
 ) {
     let arg_expr = match arg.kind {
         ExprKind::AddrOf(BorrowKind::Ref, _, ref_arg) => ref_arg,
-        ExprKind::MethodCall(method, _, args, _) if args.len() == 1 && method.ident.name == rustc_span::sym::iter => {
+        ExprKind::MethodCall(method, args, _) if args.len() == 1 && method.ident.name == rustc_span::sym::iter => {
             &args[0]
         },
         _ => return,
diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs
index f6b7e1bc353..eac0f03b142 100644
--- a/clippy_lints/src/loops/utils.rs
+++ b/clippy_lints/src/loops/utils.rs
@@ -3,10 +3,10 @@ use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_loc
 use if_chain::if_chain;
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor};
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, Pat, PatKind, Stmt};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::Ty;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
@@ -50,8 +50,6 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if self.done {
             return;
@@ -102,9 +100,6 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
             walk_expr(self, expr);
         }
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 enum InitializeVisitorState<'hir> {
@@ -151,7 +146,7 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_local(&mut self, l: &'tcx Local<'_>) {
         // Look for declarations of the variable
@@ -254,8 +249,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
@@ -283,8 +278,6 @@ pub(super) struct LoopNestVisitor {
 }
 
 impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
-    type Map = Map<'tcx>;
-
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         if stmt.hir_id == self.hir_id {
             self.nesting = LookFurther;
@@ -323,10 +316,6 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
         }
         walk_pat(self, pat);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs
index 5f9ebad25e8..5dcfed65c78 100644
--- a/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/clippy_lints/src/loops/while_immutable_condition.rs
@@ -5,11 +5,10 @@ use clippy_utils::usage::mutated_variables;
 use if_chain::if_chain;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::HirIdSet;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
     if constant(cx, cx.typeck_results(), cond).is_some() {
@@ -67,8 +66,6 @@ struct HasBreakOrReturnVisitor {
 }
 
 impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if self.has_break_or_return {
             return;
@@ -84,10 +81,6 @@ impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
 
         walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Collects the set of variables in an expression
@@ -123,8 +116,6 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
         match ex.kind {
             ExprKind::Path(_) => self.insert_def_id(ex),
@@ -134,8 +125,4 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
             _ => walk_expr(self, ex),
         }
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs
index 750328d1d01..20a8294a0d1 100644
--- a/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -7,7 +7,7 @@ use clippy_utils::{
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::Adjust;
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let Res::Def(_, pat_did) = pat_path.res;
         if match_def_path(cx, pat_did, &paths::OPTION_SOME);
         // check for call to `Iterator::next`
-        if let ExprKind::MethodCall(method_name, _, [iter_expr], _) = let_expr.kind;
+        if let ExprKind::MethodCall(method_name, [iter_expr], _) = let_expr.kind;
         if method_name.ident.name == sym::next;
         if is_trait_method(cx, let_expr, sym::Iterator);
         if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr);
@@ -211,11 +211,6 @@ fn uses_iter<'tcx>(cx: &LateContext<'tcx>, iter_expr: &IterExpr, container: &'tc
         uses_iter: bool,
     }
     impl<'tcx> Visitor<'tcx> for V<'_, '_, 'tcx> {
-        type Map = ErasedMap<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if self.uses_iter {
                 // return
@@ -254,11 +249,6 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
         used_iter: bool,
     }
     impl<'tcx> Visitor<'tcx> for AfterLoopVisitor<'_, '_, 'tcx> {
-        type Map = ErasedMap<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if self.used_iter {
                 return;
@@ -293,12 +283,6 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
         used_after: bool,
     }
     impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedLoopVisitor<'a, 'b, 'tcx> {
-        type Map = ErasedMap<'tcx>;
-
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_local(&mut self, l: &'tcx Local<'_>) {
             if !self.after_loop {
                 l.pat.each_binding_or_first(&mut |_, id, _, _| {
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index 86819752f90..babc6fab3c0 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
-    IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind,
+    IsAsync, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -140,7 +140,7 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
         if args.bindings.len() == 1;
         let binding = &args.bindings[0];
         if binding.ident.name == sym::Output;
-        if let TypeBindingKind::Equality{ty: output} = binding.kind;
+        if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind;
         then {
             return Some(output)
         }
diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs
index a72ef1d2de2..809aa168a7a 100644
--- a/clippy_lints/src/manual_bits.rs
+++ b/clippy_lints/src/manual_bits.rs
@@ -4,7 +4,7 @@ use clippy_utils::{match_def_path, meets_msrv, msrvs, paths};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 63a72d4fdde..33d1bb2985f 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -5,7 +5,7 @@ use clippy_utils::{meets_msrv, msrvs};
 use if_chain::if_chain;
 use rustc_ast::ast::{FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
@@ -116,7 +116,7 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants
                 |diag| {
                     if_chain! {
                         if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive));
-                        let header_span = cx.sess.source_map().span_until_char(item.span, '{');
+                        let header_span = cx.sess().source_map().span_until_char(item.span, '{');
                         if let Some(snippet) = snippet_opt(cx, header_span);
                         then {
                             diag.span_suggestion(
@@ -149,7 +149,7 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data:
             VariantData::Unit(_) => unreachable!("`VariantData::Unit` is already handled above"),
         };
 
-        cx.sess.source_map().span_until_char(item.span, delimiter)
+        cx.sess().source_map().span_until_char(item.span, delimiter)
     }
 
     let fields = data.fields();
diff --git a/clippy_lints/src/manual_ok_or.rs b/clippy_lints/src/manual_ok_or.rs
index bd083e3e9e2..bf4ab29d908 100644
--- a/clippy_lints/src/manual_ok_or.rs
+++ b/clippy_lints/src/manual_ok_or.rs
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualOkOr {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(method_segment, _, args, _) = scrutinee.kind;
+            if let ExprKind::MethodCall(method_segment, args, _) = scrutinee.kind;
             if method_segment.ident.name == sym!(map_or);
             if args.len() == 3;
             let method_receiver = &args[0];
diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs
index f8e28f1671f..aacabf303a7 100644
--- a/clippy_lints/src/manual_strip.rs
+++ b/clippy_lints/src/manual_strip.rs
@@ -6,11 +6,10 @@ use clippy_utils::{eq_expr_value, higher, match_def_path, meets_msrv, msrvs, pat
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::BinOpKind;
 use rustc_hir::{BorrowKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -75,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
 
         if_chain! {
             if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
-            if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
+            if let ExprKind::MethodCall(_, [target_arg, pattern], _) = cond.kind;
             if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
             if let ExprKind::Path(target_path) = &target_arg.kind;
             then {
@@ -133,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
 // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
 fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if_chain! {
-        if let ExprKind::MethodCall(_, _, [arg], _) = expr.kind;
+        if let ExprKind::MethodCall(_, [arg], _) = 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::STR_LEN);
         then {
@@ -203,11 +202,6 @@ fn find_stripping<'tcx>(
     }
 
     impl<'a, 'tcx> Visitor<'tcx> for StrippingFinder<'a, 'tcx> {
-        type Map = Map<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
             if_chain! {
                 if is_ref_str(self.cx, ex);
diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs
index 5b203fd3d92..3f8eeb736fb 100644
--- a/clippy_lints/src/map_clone.rs
+++ b/clippy_lints/src/map_clone.rs
@@ -5,7 +5,7 @@ use clippy_utils::{is_trait_method, meets_msrv, msrvs, peel_blocks};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty;
 use rustc_middle::ty::adjustment::Adjust;
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
         }
 
         if_chain! {
-            if let hir::ExprKind::MethodCall(method, _, 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]);
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
                                     }
                                 }
                             },
-                            hir::ExprKind::MethodCall(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);
diff --git a/clippy_lints/src/map_err_ignore.rs b/clippy_lints/src/map_err_ignore.rs
index 61f21d532c5..e3a42de0b7c 100644
--- a/clippy_lints/src/map_err_ignore.rs
+++ b/clippy_lints/src/map_err_ignore.rs
@@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
         }
 
         // check if this is a method call (e.g. x.foo())
-        if let ExprKind::MethodCall(method, _t_span, args, _) = e.kind {
+        if let ExprKind::MethodCall(method, 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_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index 58c686d95b3..0f6ac478432 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/clippy_lints/src/map_unit_fn.rs
@@ -129,7 +129,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) ->
     }
 
     match expr.kind {
-        hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _, _) => {
+        hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(..) => {
             // Calls can't be reduced any more
             Some(expr.span)
         },
diff --git a/clippy_lints/src/match_result_ok.rs b/clippy_lints/src/match_result_ok.rs
index b1839f00aae..77a4917ec58 100644
--- a/clippy_lints/src/match_result_ok.rs
+++ b/clippy_lints/src/match_result_ok.rs
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
             };
 
         if_chain! {
-            if let ExprKind::MethodCall(_, ok_span, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
+            if let ExprKind::MethodCall(ok_path, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
             if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = let_pat.kind; //get operation
             if method_chain_args(let_expr, &["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);
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
 
                 let mut applicability = Applicability::MachineApplicable;
                 let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
-                let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_span), "", &mut applicability);
+                let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_path.ident.span), "", &mut applicability);
                 let sugg = format!(
                     "{} let Ok({}) = {}",
                     ifwhile,
diff --git a/clippy_lints/src/match_str_case_mismatch.rs b/clippy_lints/src/match_str_case_mismatch.rs
index 1fc7eb72142..85aec93670b 100644
--- a/clippy_lints/src/match_str_case_mismatch.rs
+++ b/clippy_lints/src/match_str_case_mismatch.rs
@@ -2,10 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -86,16 +85,9 @@ struct MatchExprVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-
     fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
         match ex.kind {
-            ExprKind::MethodCall(segment, _, [receiver], _) if self.case_altered(segment.ident.as_str(), receiver) => {
-            },
+            ExprKind::MethodCall(segment, [receiver], _) if self.case_altered(segment.ident.as_str(), receiver) => {},
             _ => walk_expr(self, ex),
         }
     }
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 017e4a33980..e0cbadeb645 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -25,13 +25,13 @@ use rustc_hir::{
     Mutability, Node, Pat, PatKind, PathSegment, QPath, RangeEnd, TyKind,
 };
 use rustc_hir::{HirIdMap, HirIdSet};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty, TyS, VariantDef};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::{sym, symbol::kw};
-use std::cmp::Ordering;
+use std::cmp::{max, Ordering};
 use std::collections::hash_map::Entry;
 
 declare_clippy_lint! {
@@ -830,12 +830,12 @@ fn report_single_match_single_pattern(
     );
 }
 
-fn check_single_match_opt_like(
-    cx: &LateContext<'_>,
+fn check_single_match_opt_like<'a>(
+    cx: &LateContext<'a>,
     ex: &Expr<'_>,
     arms: &[Arm<'_>],
     expr: &Expr<'_>,
-    ty: Ty<'_>,
+    ty: Ty<'a>,
     els: Option<&Expr<'_>>,
 ) {
     // list of candidate `Enum`s we know will never get any more members
@@ -849,25 +849,120 @@ fn check_single_match_opt_like(
         (&paths::RESULT, "Ok"),
     ];
 
-    let path = match arms[1].pat.kind {
-        PatKind::TupleStruct(ref path, inner, _) => {
-            // Contains any non wildcard patterns (e.g., `Err(err)`)?
-            if !inner.iter().all(is_wild) {
-                return;
+    // We want to suggest to exclude an arm that contains only wildcards or forms the exhaustive
+    // match with the second branch, without enum variants in matches.
+    if !contains_only_wilds(arms[1].pat) && !form_exhaustive_matches(arms[0].pat, arms[1].pat) {
+        return;
+    }
+
+    let mut paths_and_types = Vec::new();
+    if !collect_pat_paths(&mut paths_and_types, cx, arms[1].pat, ty) {
+        return;
+    }
+
+    let in_candidate_enum = |path_info: &(String, &TyS<'_>)| -> bool {
+        let (path, ty) = path_info;
+        for &(ty_path, pat_path) in candidates {
+            if path == pat_path && match_type(cx, ty, ty_path) {
+                return true;
             }
-            rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false))
+        }
+        false
+    };
+    if paths_and_types.iter().all(in_candidate_enum) {
+        report_single_match_single_pattern(cx, ex, arms, expr, els);
+    }
+}
+
+/// Collects paths and their types from the given patterns. Returns true if the given pattern could
+/// be simplified, false otherwise.
+fn collect_pat_paths<'a>(acc: &mut Vec<(String, Ty<'a>)>, cx: &LateContext<'a>, pat: &Pat<'_>, ty: Ty<'a>) -> bool {
+    match pat.kind {
+        PatKind::Wild => true,
+        PatKind::Tuple(inner, _) => inner.iter().all(|p| {
+            let p_ty = cx.typeck_results().pat_ty(p);
+            collect_pat_paths(acc, cx, p, p_ty)
+        }),
+        PatKind::TupleStruct(ref path, ..) => {
+            let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
+                s.print_qpath(path, false);
+            });
+            acc.push((path, ty));
+            true
+        },
+        PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => {
+            acc.push((ident.to_string(), ty));
+            true
         },
-        PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => ident.to_string(),
         PatKind::Path(ref path) => {
-            rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false))
+            let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
+                s.print_qpath(path, false);
+            });
+            acc.push((path, ty));
+            true
         },
-        _ => return,
-    };
+        _ => false,
+    }
+}
 
-    for &(ty_path, pat_path) in candidates {
-        if path == *pat_path && match_type(cx, ty, ty_path) {
-            report_single_match_single_pattern(cx, ex, arms, expr, els);
-        }
+/// Returns true if the given arm of pattern matching contains wildcard patterns.
+fn contains_only_wilds(pat: &Pat<'_>) -> bool {
+    match pat.kind {
+        PatKind::Wild => true,
+        PatKind::Tuple(inner, _) | PatKind::TupleStruct(_, inner, ..) => inner.iter().all(contains_only_wilds),
+        _ => false,
+    }
+}
+
+/// Returns true if the given patterns forms only exhaustive matches that don't contain enum
+/// patterns without a wildcard.
+fn form_exhaustive_matches(left: &Pat<'_>, right: &Pat<'_>) -> bool {
+    match (&left.kind, &right.kind) {
+        (PatKind::Wild, _) | (_, PatKind::Wild) => true,
+        (PatKind::Tuple(left_in, left_pos), PatKind::Tuple(right_in, right_pos)) => {
+            // We don't actually know the position and the presence of the `..` (dotdot) operator
+            // in the arms, so we need to evaluate the correct offsets here in order to iterate in
+            // both arms at the same time.
+            let len = max(
+                left_in.len() + {
+                    if left_pos.is_some() { 1 } else { 0 }
+                },
+                right_in.len() + {
+                    if right_pos.is_some() { 1 } else { 0 }
+                },
+            );
+            let mut left_pos = left_pos.unwrap_or(usize::MAX);
+            let mut right_pos = right_pos.unwrap_or(usize::MAX);
+            let mut left_dot_space = 0;
+            let mut right_dot_space = 0;
+            for i in 0..len {
+                let mut found_dotdot = false;
+                if i == left_pos {
+                    left_dot_space += 1;
+                    if left_dot_space < len - left_in.len() {
+                        left_pos += 1;
+                    }
+                    found_dotdot = true;
+                }
+                if i == right_pos {
+                    right_dot_space += 1;
+                    if right_dot_space < len - right_in.len() {
+                        right_pos += 1;
+                    }
+                    found_dotdot = true;
+                }
+                if found_dotdot {
+                    continue;
+                }
+                if !contains_only_wilds(&left_in[i - left_dot_space])
+                    && !contains_only_wilds(&right_in[i - right_dot_space])
+                {
+                    return false;
+                }
+            }
+            true
+        },
+        _ => false,
     }
 }
 
@@ -1776,7 +1871,7 @@ mod redundant_pattern_match {
     use rustc_errors::Applicability;
     use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
     use rustc_hir::{
-        intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
+        intravisit::{walk_expr, Visitor},
         Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, Pat, PatKind, QPath, UnOp,
     };
     use rustc_lint::LateContext;
@@ -1880,11 +1975,6 @@ mod redundant_pattern_match {
             res: bool,
         }
         impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
-            type Map = ErasedMap<'tcx>;
-            fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-                NestedVisitorMap::None
-            }
-
             fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                 match expr.kind {
                     // Taking the reference of a value leaves a temporary
@@ -1914,7 +2004,7 @@ mod redundant_pattern_match {
                     },
                     // Method calls can take self by reference.
                     // e.g. In `String::new().len()` the string is a temporary value.
-                    ExprKind::MethodCall(_, _, [self_arg, args @ ..], _) => {
+                    ExprKind::MethodCall(_, [self_arg, args @ ..], _) => {
                         if !matches!(self_arg.kind, ExprKind::Path(_)) {
                             let self_by_ref = self
                                 .cx
@@ -2025,7 +2115,7 @@ mod redundant_pattern_match {
         // check that `while_let_on_iterator` lint does not trigger
         if_chain! {
             if keyword == "while";
-            if let ExprKind::MethodCall(method_path, _, _, _) = let_expr.kind;
+            if let ExprKind::MethodCall(method_path, _, _) = let_expr.kind;
             if method_path.ident.name == sym::next;
             if is_trait_method(cx, let_expr, sym::Iterator);
             then {
diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index 7fc39f17232..a184806d021 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/clippy_lints/src/mem_replace.rs
@@ -6,7 +6,7 @@ use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs
index 150bafc0f5d..ce958b8ac9f 100644
--- a/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -121,9 +121,9 @@ pub(crate) trait BindInsteadOfMap {
         });
         let (span, msg) = if_chain! {
             if can_sugg;
-            if let hir::ExprKind::MethodCall(_, span, ..) = expr.kind;
+            if let hir::ExprKind::MethodCall(segment, ..) = expr.kind;
             if let Some(msg) = Self::lint_msg(cx);
-            then { (span, msg) } else { return false; }
+            then { (segment.ident.span, msg) } else { return false; }
         };
         span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| {
             multispan_sugg_with_applicability(
diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs
index b4dacb2580c..0b38a07204e 100644
--- a/clippy_lints/src/methods/clone_on_copy.rs
+++ b/clippy_lints/src/methods/clone_on_copy.rs
@@ -81,12 +81,12 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                 // &*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, ..], _)
+                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::MethodCall(_, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
                 ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
                 | ExprKind::Field(..)
                 | ExprKind::Index(..) => true,
diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs
index 0f39470f342..d813edab687 100644
--- a/clippy_lints/src/methods/expect_fun_call.rs
+++ b/clippy_lints/src/methods/expect_fun_call.rs
@@ -28,9 +28,9 @@ pub(super) fn check<'tcx>(
         loop {
             arg_root = match &arg_root.kind {
                 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr,
-                hir::ExprKind::MethodCall(method_name, _, call_args, _) => {
+                hir::ExprKind::MethodCall(method_name, call_args, _) => {
                     if call_args.len() == 1
-                        && (method_name.ident.name == sym::as_str || method_name.ident.name == sym!(as_ref))
+                        && (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref)
                         && {
                             let arg_type = cx.typeck_results().expr_ty(&call_args[0]);
                             let base_type = arg_type.peel_refs();
diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs
index 687636f8237..a15fe609402 100644
--- a/clippy_lints/src/methods/extend_with_drain.rs
+++ b/clippy_lints/src/methods/extend_with_drain.rs
@@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
     if_chain! {
         if is_type_diagnostic_item(cx, ty, sym::Vec);
         //check source object
-        if let ExprKind::MethodCall(src_method, _, [drain_vec, drain_arg], _) = &arg.kind;
+        if let ExprKind::MethodCall(src_method, [drain_vec, drain_arg], _) = &arg.kind;
         if src_method.ident.as_str() == "drain";
         let src_ty = cx.typeck_results().expr_ty(drain_vec);
         //check if actual src type is mutable for code suggestion
diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs
index 6d8733c08b4..ba1af9f3d62 100644
--- a/clippy_lints/src/methods/filter_map.rs
+++ b/clippy_lints/src/methods/filter_map.rs
@@ -28,7 +28,7 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
             let closure_expr = peel_blocks(&body.value);
             let arg_id = body.params[0].pat.hir_id;
             match closure_expr.kind {
-                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, _, args, _) => {
+                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, args, _) => {
                     if_chain! {
                     if ident.name == method_name;
                     if let hir::ExprKind::Path(path) = &args[0].kind;
@@ -118,7 +118,7 @@ pub(super) fn check<'tcx>(
             };
             // 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 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, opt_ty.did) {
                 Some(false)
@@ -135,7 +135,7 @@ pub(super) fn check<'tcx>(
             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 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<'_>| {
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d75ab0c4b1b..18d4867b7eb 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -566,17 +566,20 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     /// Readability, this can be written more concisely as
-    /// `_.flat_map(_)`
+    /// `_.flat_map(_)` for `Iterator` or `_.and_then(_)` for `Option`
     ///
     /// ### Example
     /// ```rust
     /// let vec = vec![vec![1]];
+    /// let opt = Some(5);
     ///
     /// // Bad
     /// vec.iter().map(|x| x.iter()).flatten();
+    /// opt.map(|x| Some(x * 2)).flatten();
     ///
     /// // Good
     /// vec.iter().flat_map(|x| x.iter());
+    /// opt.and_then(|x| Some(x * 2));
     /// ```
     #[clippy::version = "1.31.0"]
     pub MAP_FLATTEN,
@@ -2039,10 +2042,10 @@ impl_lint_pass!(Methods => [
 
 /// Extracts a method call name, args, and `Span` of the method name.
 fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx str, &'tcx [hir::Expr<'tcx>], Span)> {
-    if let ExprKind::MethodCall(path, span, args, _) = recv.kind {
+    if let ExprKind::MethodCall(path, args, _) = recv.kind {
         if !args.iter().any(|e| e.span.from_expansion()) {
             let name = path.ident.name.as_str();
-            return Some((name, args, span));
+            return Some((name, args, path.ident.span));
         }
     }
     None
@@ -2060,14 +2063,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             hir::ExprKind::Call(func, args) => {
                 from_iter_instead_of_collect::check(cx, expr, args, func);
             },
-            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);
+            hir::ExprKind::MethodCall(method_call, args, _) => {
+                let method_span = method_call.ident.span;
+                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);
                 clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args);
                 inefficient_to_string::check(cx, expr, method_call.ident.name, args);
                 single_char_add_str::check(cx, expr, args);
-                into_iter_on_ref::check(cx, expr, *method_span, method_call.ident.name, args);
+                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);
                 unnecessary_to_owned::check(cx, expr, method_call.ident.name, args);
             },
@@ -2090,7 +2094,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             return;
         }
         let name = impl_item.ident.name.as_str();
-        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
 
@@ -2166,10 +2170,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
 
             // walk the return type and check for Self (this does not check associated types)
             if let Some(self_adt) = self_ty.ty_adt_def() {
-                if contains_adt_constructor(cx.tcx, ret_ty, self_adt) {
+                if contains_adt_constructor(ret_ty, self_adt) {
                     return;
                 }
-            } else if contains_ty(cx.tcx, ret_ty, self_ty) {
+            } else if contains_ty(ret_ty, self_ty) {
                 return;
             }
 
@@ -2178,12 +2182,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 // one of the associated types must be Self
                 for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
                     if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
+                        let assoc_ty = match projection_predicate.term {
+                            ty::Term::Ty(ty) => ty,
+                            ty::Term::Const(_c) => continue,
+                        };
                         // walk the associated type and check for Self
                         if let Some(self_adt) = self_ty.ty_adt_def() {
-                            if contains_adt_constructor(cx.tcx, projection_predicate.ty, self_adt) {
+                            if contains_adt_constructor(assoc_ty, self_adt) {
                                 return;
                             }
-                        } else if contains_ty(cx.tcx, projection_predicate.ty, self_ty) {
+                        } else if contains_ty(assoc_ty, self_ty) {
                             return;
                         }
                     }
@@ -2232,7 +2240,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             if let TraitItemKind::Fn(_, _) = item.kind;
             let ret_ty = return_ty(cx, item.hir_id());
             let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
-            if !contains_ty(cx.tcx, ret_ty, self_ty);
+            if !contains_ty(ret_ty, self_ty);
 
             then {
                 span_lint(
diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs
index fa74a8f3dc3..ba2d2914315 100644
--- a/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -56,7 +56,7 @@ pub(super) fn check<'tcx>(
             let closure_expr = peel_blocks(&closure_body.value);
 
             match &closure_expr.kind {
-                hir::ExprKind::MethodCall(_, _, args, _) => {
+                hir::ExprKind::MethodCall(_, args, _) => {
                     if_chain! {
                         if args.len() == 1;
                         if path_to_local_id(&args[0], closure_body.params[0].pat.hir_id);
diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs
index 2faa6a69f81..9c6f4211031 100644
--- a/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -5,10 +5,10 @@ use clippy_utils::ty::is_copy;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_path, Visitor};
 use rustc_hir::{self, HirId, Path};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
 
@@ -97,15 +97,15 @@ struct UnwrapVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
     fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
         self.identifiers.insert(ident(path));
         walk_path(self, path);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
@@ -116,7 +116,7 @@ struct MapExprVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
     fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
         if self.identifiers.contains(&ident(path)) {
@@ -126,8 +126,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> {
         walk_path(self, path);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs
index 514bdadc442..926c25b4b40 100644
--- a/clippy_lints/src/methods/str_splitn.rs
+++ b/clippy_lints/src/methods/str_splitn.rs
@@ -45,16 +45,16 @@ pub(super) fn check_manual_split_once(
         IterUsageKind::Next | IterUsageKind::Second => {
             let self_deref = {
                 let adjust = cx.typeck_results().expr_adjustments(self_arg);
-                if adjust.is_empty() {
+                if adjust.len() < 2 {
                     String::new()
                 } else if cx.typeck_results().expr_ty(self_arg).is_box()
                     || adjust
                         .iter()
                         .any(|a| matches!(a.kind, Adjust::Deref(Some(_))) || a.target.is_box())
                 {
-                    format!("&{}", "*".repeat(adjust.len() - 1))
+                    format!("&{}", "*".repeat(adjust.len().saturating_sub(1)))
                 } else {
-                    "*".repeat(adjust.len() - 2)
+                    "*".repeat(adjust.len().saturating_sub(2))
                 }
             };
             if matches!(usage.kind, IterUsageKind::Next) {
@@ -132,7 +132,7 @@ fn parse_iter_usage<'tcx>(
 ) -> Option<IterUsage> {
     let (kind, span) = match iter.next() {
         Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
-            let (name, args) = if let ExprKind::MethodCall(name, _, [_, args @ ..], _) = e.kind {
+            let (name, args) = if let ExprKind::MethodCall(name, [_, args @ ..], _) = e.kind {
                 (name, args)
             } else {
                 return None;
@@ -173,7 +173,7 @@ fn parse_iter_usage<'tcx>(
                         } else {
                             if_chain! {
                                 if let Some((_, Node::Expr(next_expr))) = iter.next();
-                                if let ExprKind::MethodCall(next_name, _, [_], _) = next_expr.kind;
+                                if let ExprKind::MethodCall(next_name, [_], _) = next_expr.kind;
                                 if next_name.ident.name == sym::next;
                                 if next_expr.span.ctxt() == ctxt;
                                 if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id);
@@ -217,7 +217,7 @@ fn parse_iter_usage<'tcx>(
                 }
             },
             _ if e.span.ctxt() != ctxt => (None, span),
-            ExprKind::MethodCall(name, _, [_], _)
+            ExprKind::MethodCall(name, [_], _)
                 if name.ident.name == sym::unwrap
                     && cx
                         .typeck_results()
@@ -289,7 +289,7 @@ fn check_iter<'tcx>(
 ) -> bool {
     match iter.next() {
         Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
-            let (name, args) = if let ExprKind::MethodCall(name, _, [_, args @ ..], _) = e.kind {
+            let (name, args) = if let ExprKind::MethodCall(name, [_, args @ ..], _) = e.kind {
                 (name, args)
             } else {
                 return false;
diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs
index 59bdfb923ed..784014f0d87 100644
--- a/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -2,10 +2,9 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::{is_lang_ctor, is_trait_method, path_to_local_id};
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
 use rustc_middle::ty::{self, TyS};
 use rustc_span::sym;
 
@@ -113,8 +112,6 @@ impl<'a, 'tcx> ReturnVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
         if let hir::ExprKind::Ret(Some(expr)) = &expr.kind {
             let (found_mapping, found_filtering) = check_expression(self.cx, self.arg_id, expr);
@@ -124,8 +121,4 @@ impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> {
             walk_expr(self, expr);
         }
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 5999245ea7d..65e94c5f44a 100644
--- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -4,10 +4,11 @@ use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
 use clippy_utils::{fn_def_id, get_parent_expr, path_to_local_id, usage};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, HirId, LangItem, Mutability, Pat};
 use rustc_lint::LateContext;
-use rustc_middle::{hir::map::Map, ty};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty;
 use rustc_span::{sym, Symbol};
 
 use super::UNNECESSARY_TO_OWNED;
@@ -44,7 +45,7 @@ pub fn check_for_loop_iter(
         if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
         then {
             let snippet = if_chain! {
-                if let ExprKind::MethodCall(maybe_iter_method_name, _, [collection], _) = receiver.kind;
+                if let ExprKind::MethodCall(maybe_iter_method_name, [collection], _) = receiver.kind;
                 if maybe_iter_method_name.ident.name == sym::iter;
 
                 if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
@@ -139,10 +140,10 @@ struct CloneOrCopyVisitor<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
@@ -154,7 +155,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
                         self.addr_of_exprs.push(parent);
                         return;
                     },
-                    ExprKind::MethodCall(_, _, args, _) => {
+                    ExprKind::MethodCall(_, args, _) => {
                         if_chain! {
                             if args.iter().skip(1).all(|arg| !self.is_binding(arg));
                             if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index e5b6d296b2d..b67bfb6597b 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -243,9 +243,10 @@ fn check_other_call_arg<'tcx>(
         if if trait_predicate.def_id() == deref_trait_id {
             if let [projection_predicate] = projection_predicates[..] {
                 let normalized_ty =
-                    cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.ty);
+                    cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term);
                 implements_trait(cx, receiver_ty, deref_trait_id, &[])
-                    && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty)
+                    && get_associated_type(cx, receiver_ty, deref_trait_id,
+                    "Target").map_or(false, |ty| ty::Term::Ty(ty) == normalized_ty)
             } else {
                 false
             }
@@ -312,7 +313,7 @@ fn get_callee_substs_and_args<'tcx>(
         }
     }
     if_chain! {
-        if let ExprKind::MethodCall(_, _, args, _) = expr.kind;
+        if let ExprKind::MethodCall(_, args, _) = expr.kind;
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         then {
             let substs = cx.typeck_results().node_substs(expr.hir_id);
diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs
index e0b1de68b37..ca5d33ee8b0 100644
--- a/clippy_lints/src/methods/useless_asref.rs
+++ b/clippy_lints/src/methods/useless_asref.rs
@@ -23,8 +23,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
             // allow the `as_ref` or `as_mut` if it is followed by another method call
             if_chain! {
                 if let Some(parent) = get_parent_expr(cx, expr);
-                if let hir::ExprKind::MethodCall(_, ref span, _, _) = parent.kind;
-                if span != &expr.span;
+                if let hir::ExprKind::MethodCall(segment, ..) = parent.kind;
+                if segment.ident.span != expr.span;
                 then {
                     return;
                 }
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index 24b44f819f4..c4cf994aaca 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -24,7 +24,7 @@ pub(super) fn derefs_to_slice<'tcx>(
         }
     }
 
-    if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind {
+    if let hir::ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind {
         if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) {
             Some(self_arg)
         } else {
diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs
index a6450aec4f7..cf9770f5c1f 100644
--- a/clippy_lints/src/minmax.rs
+++ b/clippy_lints/src/minmax.rs
@@ -86,7 +86,7 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
                 None
             }
         },
-        ExprKind::MethodCall(path, _, 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 8db71d1e967..3918bdbdf43 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -523,7 +523,7 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     }
 
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, [ref self_arg, ..], _) = expr.kind;
+        if let ExprKind::MethodCall(method_name, [ref self_arg, ..], _) = 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)
diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs
index 6e09e25109f..d955fad7d41 100644
--- a/clippy_lints/src/misc_early/mod.rs
+++ b/clippy_lints/src/misc_early/mod.rs
@@ -12,7 +12,7 @@ use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
 use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -342,7 +342,7 @@ impl EarlyLintPass for MiscEarlyLints {
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
 
diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs
index a8d41050856..bad9e0be82e 100644
--- a/clippy_lints/src/missing_const_for_fn.rs
+++ b/clippy_lints/src/missing_const_for_fn.rs
@@ -5,7 +5,7 @@ use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, meets_msrv, msr
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
                 }
             },
             FnKind::Method(_, sig, ..) => {
-                if trait_ref_of_method(cx, hir_id).is_some()
+                if trait_ref_of_method(cx, def_id).is_some()
                     || already_const(sig.header)
                     || method_accepts_dropable(cx, sig.decl.inputs)
                 {
diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index 3b65f80cba2..b8dfe996880 100644
--- a/clippy_lints/src/module_style.rs
+++ b/clippy_lints/src/module_style.rs
@@ -80,9 +80,9 @@ impl EarlyLintPass for ModStyle {
             return;
         }
 
-        let files = cx.sess.source_map().files();
+        let files = cx.sess().source_map().files();
 
-        let trim_to_src = if let RealFileName::LocalPath(p) = &cx.sess.opts.working_dir {
+        let trim_to_src = if let RealFileName::LocalPath(p) = &cx.sess().opts.working_dir {
             p.to_string_lossy()
         } else {
             return;
diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index 5fe887a4573..1bdd805f658 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/clippy_lints/src/mut_key.rs
@@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
 
     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() {
+            if trait_ref_of_method(cx, item.def_id).is_none() {
                 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 bcbea8f1e66..cb16f00047a 100644
--- a/clippy_lints/src/mut_mut.rs
+++ b/clippy_lints/src/mut_mut.rs
@@ -3,7 +3,6 @@ use clippy_utils::higher;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -47,8 +46,6 @@ pub struct MutVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
         if in_external_macro(self.cx.sess(), expr.span) {
             return;
@@ -114,7 +111,4 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
 
         intravisit::walk_ty(self, ty);
     }
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/mut_mutex_lock.rs b/clippy_lints/src/mut_mutex_lock.rs
index b1e6308d2e1..7871be41d62 100644
--- a/clippy_lints/src/mut_mutex_lock.rs
+++ b/clippy_lints/src/mut_mutex_lock.rs
@@ -49,7 +49,7 @@ declare_lint_pass!(MutMutexLock => [MUT_MUTEX_LOCK]);
 impl<'tcx> LateLintPass<'tcx> for MutMutexLock {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, method_span, [self_arg, ..], _) = &ex.kind;
+            if let ExprKind::MethodCall(path, [self_arg, ..], _) = &ex.kind;
             if path.ident.name == sym!(lock);
             let ty = cx.typeck_results().expr_ty(self_arg);
             if let ty::Ref(_, inner_ty, Mutability::Mut) = ty.kind();
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMutexLock {
                 span_lint_and_sugg(
                     cx,
                     MUT_MUTEX_LOCK,
-                    *method_span,
+                    path.ident.span,
                     "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference",
                     "change this to",
                     "get_mut".to_owned(),
diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs
index 22834cf61ee..5c3e505c06c 100644
--- a/clippy_lints/src/mut_reference.rs
+++ b/clippy_lints/src/mut_reference.rs
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                     );
                 }
             },
-            ExprKind::MethodCall(path, _, 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 49d4b3a1850..4ba68c8eacd 100644
--- a/clippy_lints/src/mutable_debug_assertion.rs
+++ b/clippy_lints/src/mutable_debug_assertion.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
@@ -84,7 +84,7 @@ impl<'a, 'tcx> MutArgVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         match expr.kind {
@@ -111,7 +111,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
         walk_expr(self, expr);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs
index 19d58f7474b..6cf513b214e 100644
--- a/clippy_lints/src/needless_for_each.rs
+++ b/clippy_lints/src/needless_for_each.rs
@@ -1,10 +1,9 @@
 use rustc_errors::Applicability;
 use rustc_hir::{
-    intravisit::{walk_expr, NestedVisitorMap, Visitor},
+    intravisit::{walk_expr, 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};
 
@@ -57,12 +56,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
 
         if_chain! {
             // Check the method name is `for_each`.
-            if let ExprKind::MethodCall(method_name, _, [for_each_recv, for_each_arg], _) = expr.kind;
+            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;
+            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!(
@@ -136,8 +135,6 @@ struct RetCollector {
 }
 
 impl<'tcx> Visitor<'tcx> for RetCollector {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &Expr<'_>) {
         match expr.kind {
             ExprKind::Ret(..) => {
@@ -160,8 +157,4 @@ impl<'tcx> Visitor<'tcx> for RetCollector {
 
         walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/needless_option_as_deref.rs b/clippy_lints/src/needless_option_as_deref.rs
index 0931fec149e..21d8263390a 100644
--- a/clippy_lints/src/needless_option_as_deref.rs
+++ b/clippy_lints/src/needless_option_as_deref.rs
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for OptionNeedlessDeref {
 
         if_chain! {
             if is_type_diagnostic_item(cx,outer_ty,sym::Option);
-            if let ExprKind::MethodCall(path, _, [sub_expr], _) = expr.kind;
+            if let ExprKind::MethodCall(path, [sub_expr], _) = expr.kind;
             let symbol = path.ident.as_str();
             if symbol == "as_deref" || symbol == "as_deref_mut";
             if TyS::same_type( outer_ty, typeck.expr_ty(sub_expr) );
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 35877d51c0c..ebd4fb0bf51 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -118,7 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
 
         let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
-            .filter(|p| !p.is_global(cx.tcx))
+            .filter(|p| !p.is_global())
             .filter_map(|obligation| {
                 // Note that we do not want to deal with qualified predicates here.
                 match obligation.predicate.kind().no_bound_vars() {
diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs
index 0e7ae43ce2d..d4c823d1c1a 100644
--- a/clippy_lints/src/needless_question_mark.rs
+++ b/clippy_lints/src/needless_question_mark.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionSome, ResultOk};
-use rustc_hir::{Body, Expr, ExprKind, LangItem, MatchSource, QPath};
+use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyS;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -88,7 +88,26 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
     }
 
     fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
-        check(cx, body.value.peel_blocks());
+        if let Some(GeneratorKind::Async(AsyncGeneratorKind::Fn)) = body.generator_kind {
+            if let ExprKind::Block(
+                Block {
+                    expr:
+                        Some(Expr {
+                            kind: ExprKind::DropTemps(async_body),
+                            ..
+                        }),
+                    ..
+                },
+                _,
+            ) = body.value.kind
+            {
+                if let ExprKind::Block(Block { expr: Some(expr), .. }, ..) = async_body.kind {
+                    check(cx, expr);
+                }
+            }
+        } else {
+            check(cx, body.value.peel_blocks());
+        }
     }
 }
 
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index f0c0c89ca8f..aec95530bba 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                             if sig.decl.inputs.is_empty();
                             if name == sym::new;
                             if cx.access_levels.is_reachable(impl_item.def_id);
-                            let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id));
+                            let self_def_id = cx.tcx.hir().get_parent_item(id);
                             let self_ty = cx.tcx.type_of(self_def_id);
                             if TyS::same_type(self_ty, return_ty(cx, id));
                             if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 7d2ff083b7e..21ac6548b01 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
         if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind {
-            let item_def_id = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+            let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id());
             let item = cx.tcx.hir().expect_item(item_def_id);
 
             match &item.kind {
diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs
index 39a37e3e378..0d0c88b02c7 100644
--- a/clippy_lints/src/non_expressive_names.rs
+++ b/clippy_lints/src/non_expressive_names.rs
@@ -3,7 +3,7 @@ use rustc_ast::ast::{
     self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
 };
 use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
@@ -356,7 +356,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
 
 impl EarlyLintPass for NonExpressiveNames {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if in_external_macro(cx.sess, item.span) {
+        if in_external_macro(cx.sess(), item.span) {
             return;
         }
 
@@ -371,7 +371,7 @@ impl EarlyLintPass for NonExpressiveNames {
     }
 
     fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) {
-        if in_external_macro(cx.sess, item.span) {
+        if in_external_macro(cx.sess(), item.span) {
             return;
         }
 
diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs
index e46fee4cac5..ed022b9d529 100644
--- a/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/clippy_lints/src/non_octal_unix_permissions.rs
@@ -43,7 +43,7 @@ declare_lint_pass!(NonOctalUnixPermissions => [NON_OCTAL_UNIX_PERMISSIONS]);
 impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         match &expr.kind {
-            ExprKind::MethodCall(path, _, [func, param], _) => {
+            ExprKind::MethodCall(path, [func, param], _) => {
                 let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
 
                 if_chain! {
diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs
index 203f03d3603..ab1559c85d8 100644
--- a/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
                                 non_send_fields.push(NonSendField {
                                     def: field_def,
                                     ty: field_ty,
-                                    generic_params: collect_generic_params(cx, field_ty),
+                                    generic_params: collect_generic_params(field_ty),
                                 })
                             }
                         }
@@ -171,8 +171,8 @@ impl<'tcx> NonSendField<'tcx> {
 
 /// Given a type, collect all of its generic parameters.
 /// Example: `MyStruct<P, Box<Q, R>>` => `vec![P, Q, R]`
-fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
-    ty.walk(cx.tcx)
+fn collect_generic_params(ty: Ty<'_>) -> Vec<Ty<'_>> {
+    ty.walk()
         .filter_map(|inner| match inner.unpack() {
             GenericArgKind::Type(inner_ty) => Some(inner_ty),
             _ => None,
@@ -226,7 +226,7 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t
 
 /// Checks if the type contains any pointer-like types in substs (including nested ones)
 fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool {
-    for ty_node in target_ty.walk(cx.tcx) {
+    for ty_node in target_ty.walk() {
         if let GenericArgKind::Type(inner_ty) = ty_node.unpack() {
             match inner_ty.kind() {
                 ty::RawPtr(_) => {
diff --git a/clippy_lints/src/octal_escapes.rs b/clippy_lints/src/octal_escapes.rs
index e0da12f77fc..c19cea66104 100644
--- a/clippy_lints/src/octal_escapes.rs
+++ b/clippy_lints/src/octal_escapes.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_ast::token::{Lit, LitKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
@@ -51,7 +51,7 @@ declare_lint_pass!(OctalEscapes => [OCTAL_ESCAPES]);
 
 impl EarlyLintPass for OctalEscapes {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
 
@@ -101,7 +101,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
         // construct a replacement escape
         // the maximum value is \077, or \x3f, so u8 is sufficient here
         if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) {
-            write!(&mut suggest_1, "\\x{:02x}", n).unwrap();
+            write!(suggest_1, "\\x{:02x}", n).unwrap();
         }
 
         // append the null byte as \x00 and the following digits literally
diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs
index 1b9285c2298..5a0b5042018 100644
--- a/clippy_lints/src/open_options.rs
+++ b/clippy_lints/src/open_options.rs
@@ -32,7 +32,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(path, _, [self_arg, ..], _) = &e.kind {
+        if let ExprKind::MethodCall(path, [self_arg, ..], _) = &e.kind {
             let obj_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
             if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
                 let mut options = Vec::new();
@@ -60,7 +60,7 @@ enum OpenOption {
 }
 
 fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
-    if let ExprKind::MethodCall(path, _, 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_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index 953de0f72a8..c9f807f2aa3 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -68,7 +68,7 @@ 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(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)
     } else {
diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs
index e58ca95fa04..3f940ce61c0 100644
--- a/clippy_lints/src/path_buf_push_overwrite.rs
+++ b/clippy_lints/src/path_buf_push_overwrite.rs
@@ -46,7 +46,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(path, _, 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/ptr.rs b/clippy_lints/src/ptr.rs
index c08a19d520b..77bf5f002f7 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -1,30 +1,36 @@
 //! Checks for usage of  `&Vec[_]` and `&String`.
 
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::ptr::get_spans;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::walk_ptrs_hir_ty;
-use clippy_utils::{expr_path_res, is_lint_allowed, match_any_diagnostic_items, paths};
+use clippy_utils::ty::expr_sig;
+use clippy_utils::{
+    expr_path_res, get_expr_use_or_unification_node, is_lint_allowed, match_any_diagnostic_items, path_to_local, paths,
+};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
+use rustc_hir::def_id::DefId;
+use rustc_hir::hir_id::HirIdMap;
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{
-    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, Impl, ImplItem, ImplItemKind, Item, ItemKind,
-    Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
+    self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, FnRetTy, GenericArg,
+    ImplItemKind, ItemKind, Lifetime, LifetimeName, Mutability, Node, Param, ParamName, PatKind, QPath, TraitFn,
+    TraitItem, TraitItemKind, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::{self, AssocItems, AssocKind, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, MultiSpan};
-use std::borrow::Cow;
+use std::fmt;
+use std::iter;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// This lint checks for function arguments of type `&String`
-    /// or `&Vec` unless the references are mutable. It will also suggest you
-    /// replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()`
-    /// calls.
+    /// This lint checks for function arguments of type `&String`, `&Vec`,
+    /// `&PathBuf`, and `Cow<_>`. It will also suggest you replace `.clone()` calls
+    /// with the appropriate `.to_owned()`/`to_string()` calls.
     ///
     /// ### Why is this bad?
     /// Requiring the argument to be of the specific size
@@ -32,28 +38,7 @@ declare_clippy_lint! {
     /// or `&str` usually suffice and can be obtained from other types, too.
     ///
     /// ### Known problems
-    /// The lint does not follow data. So if you have an
-    /// argument `x` and write `let y = x; y.clone()` the lint will not suggest
-    /// changing that `.clone()` to `.to_owned()`.
-    ///
-    /// Other functions called from this function taking a `&String` or `&Vec`
-    /// argument may also fail to compile if you change the argument. Applying
-    /// this lint on them will fix the problem, but they may be in other crates.
-    ///
-    /// One notable example of a function that may cause issues, and which cannot
-    /// easily be changed due to being in the standard library is `Vec::contains`.
-    /// when called on a `Vec<Vec<T>>`. If a `&Vec` is passed to that method then
-    /// it will compile, but if a `&[T]` is passed then it will not compile.
-    ///
-    /// ```ignore
-    /// fn cannot_take_a_slice(v: &Vec<u8>) -> bool {
-    ///     let vec_of_vecs: Vec<Vec<u8>> = some_other_fn();
-    ///
-    ///     vec_of_vecs.contains(v)
-    /// }
-    /// ```
-    ///
-    /// Also there may be `fn(&Vec)`-typed references pointing to your function.
+    /// There may be `fn(&Vec)`-typed references pointing to your function.
     /// If you have them, you will get a compiler error after applying this lint's
     /// suggestions. You then have the choice to undo your changes or change the
     /// type of the reference.
@@ -155,32 +140,90 @@ declare_clippy_lint! {
 declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE]);
 
 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, Some(body_id));
-        }
-    }
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
+        if let TraitItemKind::Fn(sig, trait_method) = &item.kind {
+            if matches!(trait_method, TraitFn::Provided(_)) {
+                // Handled by check body.
+                return;
+            }
 
-    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
-        if let ImplItemKind::Fn(ref sig, body_id) = item.kind {
-            let parent_item = cx.tcx.hir().get_parent_item(item.hir_id());
-            if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) {
-                if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = it.kind {
-                    return; // ignore trait impls
-                }
+            check_mut_from_ref(cx, sig.decl);
+            for arg in check_fn_args(
+                cx,
+                cx.tcx.fn_sig(item.def_id).skip_binder().inputs(),
+                sig.decl.inputs,
+                &[],
+            )
+            .filter(|arg| arg.mutability() == Mutability::Not)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    PTR_ARG,
+                    arg.span,
+                    &arg.build_msg(),
+                    "change this to",
+                    format!("{}{}", arg.ref_prefix, arg.deref_ty.display(cx)),
+                    Applicability::Unspecified,
+                );
             }
-            check_fn(cx, sig.decl, Some(body_id));
         }
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
-        if let TraitItemKind::Fn(ref sig, ref trait_method) = item.kind {
-            let body_id = if let TraitFn::Provided(b) = *trait_method {
-                Some(b)
-            } else {
-                None
-            };
-            check_fn(cx, sig.decl, body_id);
+    fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
+        let hir = cx.tcx.hir();
+        let mut parents = hir.parent_iter(body.value.hir_id);
+        let (item_id, decl, is_trait_item) = match parents.next() {
+            Some((_, Node::Item(i))) => {
+                if let ItemKind::Fn(sig, ..) = &i.kind {
+                    (i.def_id, sig.decl, false)
+                } else {
+                    return;
+                }
+            },
+            Some((_, Node::ImplItem(i))) => {
+                if !matches!(parents.next(),
+                    Some((_, Node::Item(i))) if matches!(&i.kind, ItemKind::Impl(i) if i.of_trait.is_none())
+                ) {
+                    return;
+                }
+                if let ImplItemKind::Fn(sig, _) = &i.kind {
+                    (i.def_id, sig.decl, false)
+                } else {
+                    return;
+                }
+            },
+            Some((_, Node::TraitItem(i))) => {
+                if let TraitItemKind::Fn(sig, _) = &i.kind {
+                    (i.def_id, sig.decl, true)
+                } else {
+                    return;
+                }
+            },
+            _ => return,
+        };
+
+        check_mut_from_ref(cx, decl);
+        let sig = cx.tcx.fn_sig(item_id).skip_binder();
+        let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, body.params)
+            .filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not)
+            .collect();
+        let results = check_ptr_arg_usage(cx, body, &lint_args);
+
+        for (result, args) in results.iter().zip(lint_args.iter()).filter(|(r, _)| !r.skip) {
+            span_lint_and_then(cx, PTR_ARG, args.span, &args.build_msg(), |diag| {
+                diag.multipart_suggestion(
+                    "change this to",
+                    iter::once((args.span, format!("{}{}", args.ref_prefix, args.deref_ty.display(cx))))
+                        .chain(result.replacements.iter().map(|r| {
+                            (
+                                r.expr_span,
+                                format!("{}{}", snippet_opt(cx, r.self_span).unwrap(), r.replacement),
+                            )
+                        }))
+                        .collect(),
+                    Applicability::Unspecified,
+                );
+            });
         }
     }
 
@@ -247,154 +290,210 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     }
 }
 
-#[allow(clippy::too_many_lines)]
-fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, opt_body_id: Option<BodyId>) {
-    let body = opt_body_id.map(|id| cx.tcx.hir().body(id));
-
-    for (idx, arg) in decl.inputs.iter().enumerate() {
-        // Honor the allow attribute on parameters. See issue 5644.
-        if let Some(body) = &body {
-            if is_lint_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
-                continue;
-            }
-        }
+#[derive(Default)]
+struct PtrArgResult {
+    skip: bool,
+    replacements: Vec<PtrArgReplacement>,
+}
 
-        let (item_name, path) = if_chain! {
-            if let TyKind::Rptr(_, MutTy { ty, mutbl: Mutability::Not }) = arg.kind;
-            if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
-            if let Res::Def(_, did) = path.res;
-            if let Some(item_name) = cx.tcx.get_diagnostic_name(did);
-            then {
-                (item_name, path)
-            } else {
-                continue
-            }
-        };
+struct PtrArgReplacement {
+    expr_span: Span,
+    self_span: Span,
+    replacement: &'static str,
+}
 
-        match item_name {
-            sym::Vec => {
-                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
-                    span_lint_and_then(
-                        cx,
-                        PTR_ARG,
-                        arg.span,
-                        "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
-                         with non-Vec-based slices",
-                        |diag| {
-                            if let Some(ref snippet) = get_only_generic_arg_snippet(cx, arg) {
-                                diag.span_suggestion(
-                                    arg.span,
-                                    "change this to",
-                                    format!("&[{}]", snippet),
-                                    Applicability::Unspecified,
-                                );
-                            }
-                            for (clonespan, suggestion) in spans {
-                                diag.span_suggestion(
-                                    clonespan,
-                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
-                                        Cow::Owned(format!("change `{}` to", x))
-                                    }),
-                                    suggestion.into(),
-                                    Applicability::Unspecified,
-                                );
-                            }
-                        },
-                    );
-                }
+struct PtrArg<'tcx> {
+    idx: usize,
+    span: Span,
+    ty_did: DefId,
+    ty_name: Symbol,
+    method_renames: &'static [(&'static str, &'static str)],
+    ref_prefix: RefPrefix,
+    deref_ty: DerefTy<'tcx>,
+    deref_assoc_items: Option<(DefId, &'tcx AssocItems<'tcx>)>,
+}
+impl PtrArg<'_> {
+    fn build_msg(&self) -> String {
+        format!(
+            "writing `&{}{}` instead of `&{}{}` involves a new object where a slice will do",
+            self.ref_prefix.mutability.prefix_str(),
+            self.ty_name,
+            self.ref_prefix.mutability.prefix_str(),
+            self.deref_ty.argless_str(),
+        )
+    }
+
+    fn mutability(&self) -> Mutability {
+        self.ref_prefix.mutability
+    }
+}
+
+struct RefPrefix {
+    lt: LifetimeName,
+    mutability: Mutability,
+}
+impl fmt::Display for RefPrefix {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use fmt::Write;
+        f.write_char('&')?;
+        match self.lt {
+            LifetimeName::Param(ParamName::Plain(name)) => {
+                name.fmt(f)?;
+                f.write_char(' ')?;
             },
-            sym::String => {
-                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
-                    span_lint_and_then(
-                        cx,
-                        PTR_ARG,
-                        arg.span,
-                        "writing `&String` instead of `&str` involves a new object where a slice will do",
-                        |diag| {
-                            diag.span_suggestion(arg.span, "change this to", "&str".into(), Applicability::Unspecified);
-                            for (clonespan, suggestion) in spans {
-                                diag.span_suggestion_short(
-                                    clonespan,
-                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
-                                        Cow::Owned(format!("change `{}` to", x))
-                                    }),
-                                    suggestion.into(),
-                                    Applicability::Unspecified,
-                                );
-                            }
-                        },
-                    );
+            LifetimeName::Underscore => f.write_str("'_ ")?,
+            LifetimeName::Static => f.write_str("'static ")?,
+            _ => (),
+        }
+        f.write_str(self.mutability.prefix_str())
+    }
+}
+
+struct DerefTyDisplay<'a, 'tcx>(&'a LateContext<'tcx>, &'a DerefTy<'tcx>);
+impl fmt::Display for DerefTyDisplay<'_, '_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use std::fmt::Write;
+        match self.1 {
+            DerefTy::Str => f.write_str("str"),
+            DerefTy::Path => f.write_str("Path"),
+            DerefTy::Slice(hir_ty, ty) => {
+                f.write_char('[')?;
+                match hir_ty.and_then(|s| snippet_opt(self.0, s)) {
+                    Some(s) => f.write_str(&s)?,
+                    None => ty.fmt(f)?,
                 }
+                f.write_char(']')
             },
-            sym::PathBuf => {
-                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
-                    span_lint_and_then(
-                        cx,
-                        PTR_ARG,
-                        arg.span,
-                        "writing `&PathBuf` instead of `&Path` involves a new object where a slice will do",
-                        |diag| {
-                            diag.span_suggestion(
-                                arg.span,
+        }
+    }
+}
+
+enum DerefTy<'tcx> {
+    Str,
+    Path,
+    Slice(Option<Span>, Ty<'tcx>),
+}
+impl<'tcx> DerefTy<'tcx> {
+    fn argless_str(&self) -> &'static str {
+        match *self {
+            Self::Str => "str",
+            Self::Path => "Path",
+            Self::Slice(..) => "[_]",
+        }
+    }
+
+    fn display<'a>(&'a self, cx: &'a LateContext<'tcx>) -> DerefTyDisplay<'a, 'tcx> {
+        DerefTyDisplay(cx, self)
+    }
+}
+
+fn check_fn_args<'cx, 'tcx: 'cx>(
+    cx: &'cx LateContext<'tcx>,
+    tys: &'tcx [Ty<'_>],
+    hir_tys: &'tcx [hir::Ty<'_>],
+    params: &'tcx [Param<'_>],
+) -> impl Iterator<Item = PtrArg<'tcx>> + 'cx {
+    tys.iter()
+        .zip(hir_tys.iter())
+        .enumerate()
+        .filter_map(|(i, (ty, hir_ty))| {
+            if_chain! {
+                if let ty::Ref(_, ty, mutability) = *ty.kind();
+                if let ty::Adt(adt, substs) = *ty.kind();
+
+                if let TyKind::Rptr(lt, ref ty) = hir_ty.kind;
+                if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind;
+
+                // Check that the name as typed matches the actual name of the type.
+                // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec`
+                if let [.., name] = path.segments;
+                if cx.tcx.item_name(adt.did) == name.ident.name;
+
+                if !is_lint_allowed(cx, PTR_ARG, hir_ty.hir_id);
+                if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id));
+
+                then {
+                    let (method_renames, deref_ty, deref_impl_id) = match cx.tcx.get_diagnostic_name(adt.did) {
+                        Some(sym::Vec) => (
+                            [("clone", ".to_owned()")].as_slice(),
+                            DerefTy::Slice(
+                                name.args
+                                    .and_then(|args| args.args.first())
+                                    .and_then(|arg| if let GenericArg::Type(ty) = arg {
+                                        Some(ty.span)
+                                    } else {
+                                        None
+                                    }),
+                                substs.type_at(0),
+                            ),
+                            cx.tcx.lang_items().slice_impl()
+                        ),
+                        Some(sym::String) => (
+                            [("clone", ".to_owned()"), ("as_str", "")].as_slice(),
+                            DerefTy::Str,
+                            cx.tcx.lang_items().str_impl()
+                        ),
+                        Some(sym::PathBuf) => (
+                            [("clone", ".to_path_buf()"), ("as_path", "")].as_slice(),
+                            DerefTy::Path,
+                            None,
+                        ),
+                        Some(sym::Cow) => {
+                            let ty_name = name.args
+                                .and_then(|args| {
+                                    args.args.iter().find_map(|a| match a {
+                                        GenericArg::Type(x) => Some(x),
+                                        _ => None,
+                                    })
+                                })
+                                .and_then(|arg| snippet_opt(cx, arg.span))
+                                .unwrap_or_else(|| substs.type_at(1).to_string());
+                            span_lint_and_sugg(
+                                cx,
+                                PTR_ARG,
+                                hir_ty.span,
+                                "using a reference to `Cow` is not recommended",
                                 "change this to",
-                                "&Path".into(),
+                                format!("&{}{}", mutability.prefix_str(), ty_name),
                                 Applicability::Unspecified,
                             );
-                            for (clonespan, suggestion) in spans {
-                                diag.span_suggestion_short(
-                                    clonespan,
-                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
-                                        Cow::Owned(format!("change `{}` to", x))
-                                    }),
-                                    suggestion.into(),
-                                    Applicability::Unspecified,
-                                );
-                            }
+                            return None;
                         },
-                    );
-                }
-            },
-            sym::Cow => {
-                if_chain! {
-                    if let [ref bx] = *path.segments;
-                    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,
+                        _ => return None,
+                    };
+                    return Some(PtrArg {
+                        idx: i,
+                        span: hir_ty.span,
+                        ty_did: adt.did,
+                        ty_name: name.ident.name,
+                        method_renames,
+                        ref_prefix: RefPrefix {
+                            lt: lt.name,
+                            mutability,
+                        },
+                        deref_ty,
+                        deref_assoc_items: deref_impl_id.map(|id| (id, cx.tcx.associated_items(id))),
                     });
-                    let replacement = snippet_opt(cx, inner.span);
-                    if let Some(r) = replacement;
-                    then {
-                        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,
-                        );
-                    }
                 }
-            },
-            _ => {},
-        }
-    }
+            }
+            None
+        })
+}
 
+fn check_mut_from_ref(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
     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
+            for (_, mutbl, argspan) in decl
                 .inputs
                 .iter()
                 .filter_map(get_rptr_lm)
                 .filter(|&(lt, _, _)| lt.name == out.name)
             {
-                if *mutbl == Mutability::Mut {
+                if mutbl == Mutability::Mut {
                     return;
                 }
-                immutables.push(*argspan);
+                immutables.push(argspan);
             }
             if immutables.is_empty() {
                 return;
@@ -413,24 +512,158 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, opt_body_id: Option<BodyId>
     }
 }
 
-fn get_only_generic_arg_snippet(cx: &LateContext<'_>, arg: &Ty<'_>) -> Option<String> {
-    if_chain! {
-        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,
-        }).collect();
-        if types.len() == 1;
-        then {
-            snippet_opt(cx, types[0].span)
-        } else {
-            None
+#[allow(clippy::too_many_lines)]
+fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: &[PtrArg<'tcx>]) -> Vec<PtrArgResult> {
+    struct V<'cx, 'tcx> {
+        cx: &'cx LateContext<'tcx>,
+        /// Map from a local id to which argument it came from (index into `Self::args` and
+        /// `Self::results`)
+        bindings: HirIdMap<usize>,
+        /// The arguments being checked.
+        args: &'cx [PtrArg<'tcx>],
+        /// The results for each argument (len should match args.len)
+        results: Vec<PtrArgResult>,
+        /// The number of arguments which can't be linted. Used to return early.
+        skip_count: usize,
+    }
+    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
+        type NestedFilter = nested_filter::OnlyBodies;
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.cx.tcx.hir()
+        }
+
+        fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
+
+        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
+            if self.skip_count == self.args.len() {
+                return;
+            }
+
+            // Check if this is local we care about
+            let args_idx = match path_to_local(e).and_then(|id| self.bindings.get(&id)) {
+                Some(&i) => i,
+                None => return walk_expr(self, e),
+            };
+            let args = &self.args[args_idx];
+            let result = &mut self.results[args_idx];
+
+            // Helper function to handle early returns.
+            let mut set_skip_flag = || {
+                if result.skip {
+                    self.skip_count += 1;
+                }
+                result.skip = true;
+            };
+
+            match get_expr_use_or_unification_node(self.cx.tcx, e) {
+                Some((Node::Stmt(_), _)) => (),
+                Some((Node::Local(l), _)) => {
+                    // Only trace simple bindings. e.g `let x = y;`
+                    if let PatKind::Binding(BindingAnnotation::Unannotated, id, _, None) = l.pat.kind {
+                        self.bindings.insert(id, args_idx);
+                    } else {
+                        set_skip_flag();
+                    }
+                },
+                Some((Node::Expr(e), child_id)) => match e.kind {
+                    ExprKind::Call(f, expr_args) => {
+                        let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
+                        if expr_sig(self.cx, f)
+                            .map(|sig| sig.input(i).skip_binder().peel_refs())
+                            .map_or(true, |ty| match *ty.kind() {
+                                ty::Param(_) => true,
+                                ty::Adt(def, _) => def.did == args.ty_did,
+                                _ => false,
+                            })
+                        {
+                            // Passed to a function taking the non-dereferenced type.
+                            set_skip_flag();
+                        }
+                    },
+                    ExprKind::MethodCall(name, expr_args @ [self_arg, ..], _) => {
+                        let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
+                        if i == 0 {
+                            // Check if the method can be renamed.
+                            let name = name.ident.as_str();
+                            if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) {
+                                result.replacements.push(PtrArgReplacement {
+                                    expr_span: e.span,
+                                    self_span: self_arg.span,
+                                    replacement,
+                                });
+                                return;
+                            }
+                        }
+
+                        let id = if let Some(x) = self.cx.typeck_results().type_dependent_def_id(e.hir_id) {
+                            x
+                        } else {
+                            set_skip_flag();
+                            return;
+                        };
+
+                        match *self.cx.tcx.fn_sig(id).skip_binder().inputs()[i].peel_refs().kind() {
+                            ty::Param(_) => {
+                                set_skip_flag();
+                            },
+                            // If the types match check for methods which exist on both types. e.g. `Vec::len` and
+                            // `slice::len`
+                            ty::Adt(def, _)
+                                if def.did == args.ty_did
+                                    && (i != 0
+                                        || self.cx.tcx.trait_of_item(id).is_some()
+                                        || !args.deref_assoc_items.map_or(false, |(id, items)| {
+                                            items
+                                                .find_by_name_and_kind(self.cx.tcx, name.ident, AssocKind::Fn, id)
+                                                .is_some()
+                                        })) =>
+                            {
+                                set_skip_flag();
+                            },
+                            _ => (),
+                        }
+                    },
+                    // Indexing is fine for currently supported types.
+                    ExprKind::Index(e, _) if e.hir_id == child_id => (),
+                    _ => set_skip_flag(),
+                },
+                _ => set_skip_flag(),
+            }
         }
     }
+
+    let mut skip_count = 0;
+    let mut results = args.iter().map(|_| PtrArgResult::default()).collect::<Vec<_>>();
+    let mut v = V {
+        cx,
+        bindings: args
+            .iter()
+            .enumerate()
+            .filter_map(|(i, arg)| {
+                let param = &body.params[arg.idx];
+                match param.pat.kind {
+                    PatKind::Binding(BindingAnnotation::Unannotated, id, _, None)
+                        if !is_lint_allowed(cx, PTR_ARG, param.hir_id) =>
+                    {
+                        Some((id, i))
+                    },
+                    _ => {
+                        skip_count += 1;
+                        results[arg.idx].skip = true;
+                        None
+                    },
+                }
+            })
+            .collect(),
+        args,
+        results,
+        skip_count,
+    };
+    v.visit_expr(&body.value);
+    v.results
 }
 
-fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
+fn get_rptr_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
     if let TyKind::Rptr(ref lt, ref m) = ty.kind {
         Some((lt, m.mutbl, ty.span))
     } else {
diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs
index 964564b5794..b907f38afbb 100644
--- a/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/clippy_lints/src/ptr_offset_with_cast.rs
@@ -93,7 +93,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(path_segment, _, [arg_0, arg_1, ..], _) = &expr.kind {
+    if let ExprKind::MethodCall(path_segment, [arg_0, arg_1, ..], _) = &expr.kind {
         if is_expr_ty_raw_ptr(cx, arg_0) {
             if path_segment.ident.name == sym::offset {
                 return Some((arg_0, arg_1, Method::Offset));
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index c765c8962cf..6f634ded5fe 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -58,7 +58,7 @@ impl QuestionMark {
     fn check_is_none_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
             if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
-            if let ExprKind::MethodCall(segment, _, args, _) = &cond.kind;
+            if let ExprKind::MethodCall(segment, args, _) = &cond.kind;
             if let Some(subject) = args.get(0);
             if (Self::option_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_none)) ||
                 (Self::result_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_err));
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index a1e67c33abf..8065ed3ffc5 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -8,7 +8,7 @@ use if_chain::if_chain;
 use rustc_ast::ast::RangeLimits;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, QPath};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -190,7 +190,7 @@ 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(path, _, args, _) => {
+            ExprKind::MethodCall(path, args, _) => {
                 check_range_zip_with_len(cx, path, args, expr.span);
             },
             ExprKind::Binary(ref op, l, r) => {
@@ -331,13 +331,13 @@ fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args:
         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 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::hir(zip_arg);
         if is_integer_const(cx, start, 0);
         // `.len()` call
-        if let ExprKind::MethodCall(len_path, _, len_args, _) = end.kind;
+        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;
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index 1991a01fb60..3e0e32857f1 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -14,7 +14,7 @@ use rustc_middle::mir::{
     visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
     Mutability,
 };
-use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt};
+use rustc_middle::ty::{self, fold::TypeVisitor, Ty};
 use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis, ResultsCursor};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::{BytePos, Span};
@@ -575,7 +575,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
                 self.possible_borrower.add(borrowed.local, lhs);
             },
             other => {
-                if ContainsRegion(self.cx.tcx)
+                if ContainsRegion
                     .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
                     .is_continue()
                 {
@@ -624,10 +624,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
                 .flat_map(HybridBitSet::iter)
                 .collect();
 
-            if ContainsRegion(self.cx.tcx)
-                .visit_ty(self.body.local_decls[*dest].ty)
-                .is_break()
-            {
+            if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
                 mutable_variables.push(*dest);
             }
 
@@ -703,15 +700,12 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> {
     }
 }
 
-struct ContainsRegion<'tcx>(TyCtxt<'tcx>);
+struct ContainsRegion;
 
-impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> {
+impl TypeVisitor<'_> for ContainsRegion {
     type BreakTy = ();
-    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
-        Some(self.0)
-    }
 
-    fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
         ControlFlow::BREAK
     }
 }
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index 0de282542fc..5a25008e95e 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/clippy_lints/src/redundant_closure_call.rs
@@ -8,8 +8,8 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor as HirVisitor;
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -62,7 +62,7 @@ impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
 
 impl EarlyLintPass for RedundantClosureCall {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
         if_chain! {
@@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                 count: usize,
             }
             impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
-                type Map = Map<'tcx>;
+                type NestedFilter = nested_filter::OnlyBodies;
 
                 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                     if_chain! {
@@ -121,8 +121,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                     hir_visit::walk_expr(self, expr);
                 }
 
-                fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
-                    hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+                fn nested_visit_map(&mut self) -> Self::Map {
+                    self.cx.tcx.hir()
                 }
             }
             let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 };
diff --git a/clippy_lints/src/redundant_else.rs b/clippy_lints/src/redundant_else.rs
index 93dbe936d58..73088ce1a87 100644
--- a/clippy_lints/src/redundant_else.rs
+++ b/clippy_lints/src/redundant_else.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind};
 use rustc_ast::visit::{walk_expr, Visitor};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -46,7 +46,7 @@ declare_lint_pass!(RedundantElse => [REDUNDANT_ELSE]);
 
 impl EarlyLintPass for RedundantElse {
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) {
-        if in_external_macro(cx.sess, stmt.span) {
+        if in_external_macro(cx.sess(), stmt.span) {
             return;
         }
         // Only look at expressions that are a whole statement
diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs
index 0dea4a784b2..40a62fd6d20 100644
--- a/clippy_lints/src/redundant_field_names.rs
+++ b/clippy_lints/src/redundant_field_names.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{meets_msrv, msrvs};
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -55,7 +55,7 @@ impl EarlyLintPass for RedundantFieldNames {
             return;
         }
 
-        if in_external_macro(cx.sess, expr.span) {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
         if let ExprKind::Struct(ref se) = expr.kind {
diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs
index b2448372370..811a7bb9c15 100644
--- a/clippy_lints/src/reference.rs
+++ b/clippy_lints/src/reference.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
 use rustc_errors::Applicability;
@@ -104,59 +103,3 @@ impl EarlyLintPass for DerefAddrOf {
         }
     }
 }
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for references in expressions that use
-    /// auto dereference.
-    ///
-    /// ### Why is this bad?
-    /// The reference is a no-op and is automatically
-    /// dereferenced by the compiler and makes the code less clear.
-    ///
-    /// ### Example
-    /// ```rust
-    /// struct Point(u32, u32);
-    /// let point = Point(30, 20);
-    /// let x = (&point).0;
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// # struct Point(u32, u32);
-    /// # let point = Point(30, 20);
-    /// let x = point.0;
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub REF_IN_DEREF,
-    complexity,
-    "Use of reference in auto dereference expression."
-}
-
-declare_lint_pass!(RefInDeref => [REF_IN_DEREF]);
-
-impl EarlyLintPass for RefInDeref {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
-        if_chain! {
-            if let ExprKind::Field(ref object, _) = e.kind;
-            if let ExprKind::Paren(ref parened) = object.kind;
-            if let ExprKind::AddrOf(_, _, ref inner) = parened.kind;
-            then {
-                let applicability = if inner.span.from_expansion() {
-                    Applicability::MaybeIncorrect
-                } else {
-                    Applicability::MachineApplicable
-                };
-                let sugg = Sugg::ast(cx, inner, "_").maybe_par();
-                span_lint_and_sugg(
-                    cx,
-                    REF_IN_DEREF,
-                    object.span,
-                    "creating a reference that is immediately dereferenced",
-                    "try this",
-                    sugg.to_string(),
-                    applicability,
-                );
-            }
-        }
-    }
-}
diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs
index b5dd2de6337..898c70ace66 100644
--- a/clippy_lints/src/repeat_once.rs
+++ b/clippy_lints/src/repeat_once.rs
@@ -46,7 +46,7 @@ declare_lint_pass!(RepeatOnce => [REPEAT_ONCE]);
 impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, [receiver, count], _) = &expr.kind;
             if path.ident.name == sym!(repeat);
             if constant_context(cx, cx.typeck_results()).expr(count) == Some(Constant::Int(1));
             if !receiver.span.from_expansion();
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 112ccdcdd42..8068fa22d9c 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -4,10 +4,9 @@ use clippy_utils::{fn_def_id, path_to_local_id};
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -287,8 +286,6 @@ struct BorrowVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if self.borrows {
             return;
@@ -301,14 +298,10 @@ impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
                 .fn_sig(def_id)
                 .output()
                 .skip_binder()
-                .walk(self.cx.tcx)
+                .walk()
                 .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
         }
 
         walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/same_name_method.rs b/clippy_lints/src/same_name_method.rs
index 1bbaa104e60..22b45896955 100644
--- a/clippy_lints/src/same_name_method.rs
+++ b/clippy_lints/src/same_name_method.rs
@@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
                                         .filter(|assoc_item| {
                                             matches!(assoc_item.kind, AssocKind::Fn)
                                         })
-                                        .map(|assoc_item| assoc_item.ident.name)
+                                        .map(|assoc_item| assoc_item.name)
                                         .collect()
                                 }else{
                                     BTreeSet::new()
diff --git a/clippy_lints/src/self_named_constructors.rs b/clippy_lints/src/self_named_constructors.rs
index d386663e498..123d0ad0457 100644
--- a/clippy_lints/src/self_named_constructors.rs
+++ b/clippy_lints/src/self_named_constructors.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
             _ => return,
         }
 
-        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
         let ret_ty = return_ty(cx, impl_item.hir_id());
@@ -63,10 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
 
         // Ensure method is constructor-like
         if let Some(self_adt) = self_ty.ty_adt_def() {
-            if !contains_adt_constructor(cx.tcx, ret_ty, self_adt) {
+            if !contains_adt_constructor(ret_ty, self_adt) {
                 return;
             }
-        } else if !contains_ty(cx.tcx, ret_ty, self_ty) {
+        } else if !contains_ty(ret_ty, self_ty) {
             return;
         }
 
diff --git a/clippy_lints/src/single_char_lifetime_names.rs b/clippy_lints/src/single_char_lifetime_names.rs
index ee82666b5af..aa306a630c4 100644
--- a/clippy_lints/src/single_char_lifetime_names.rs
+++ b/clippy_lints/src/single_char_lifetime_names.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{GenericParam, GenericParamKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -43,7 +43,7 @@ declare_lint_pass!(SingleCharLifetimeNames => [SINGLE_CHAR_LIFETIME_NAMES]);
 
 impl EarlyLintPass for SingleCharLifetimeNames {
     fn check_generic_param(&mut self, ctx: &EarlyContext<'_>, param: &GenericParam) {
-        if in_external_macro(ctx.sess, param.ident.span) {
+        if in_external_macro(ctx.sess(), param.ident.span) {
             return;
         }
 
diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs
index 28d32203da9..961cdb317e7 100644
--- a/clippy_lints/src/single_component_path_imports.rs
+++ b/clippy_lints/src/single_component_path_imports.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use rustc_ast::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind, VisibilityKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{edition::Edition, symbol::kw, Span, Symbol};
 
@@ -37,7 +37,7 @@ declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]
 
 impl EarlyLintPass for SingleComponentPathImports {
     fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
-        if cx.sess.opts.edition < Edition::Edition2018 {
+        if cx.sess().opts.edition < Edition::Edition2018 {
             return;
         }
         check_mod(cx, &krate.items);
diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs
index 9b195f3c0a2..c7c57ab426d 100644
--- a/clippy_lints/src/size_of_in_element_count.rs
+++ b/clippy_lints/src/size_of_in_element_count.rs
@@ -108,7 +108,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
     };
     if_chain! {
         // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
-        if let ExprKind::MethodCall(method_path, _, [ptr_self, .., count], _) = expr.kind;
+        if let ExprKind::MethodCall(method_path, [ptr_self, .., count], _) = expr.kind;
         let method_ident = method_path.ident.as_str();
         if METHODS.iter().any(|m| *m == &*method_ident);
 
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index 1ae772ef70b..b4ad5dcbe3e 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -5,10 +5,9 @@ use clippy_utils::{get_enclosing_block, is_expr_path_def_path, path_to_local, pa
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
 use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, 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::symbol::sym;
 
@@ -198,7 +197,7 @@ 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(path, _, [self_arg, extend_arg], _) = expr.kind;
+            if let ExprKind::MethodCall(path, [self_arg, extend_arg], _) = expr.kind;
             if path_to_local_id(self_arg, self.vec_alloc.local_id);
             if path.ident.name == sym!(extend);
             if self.is_repeat_take(extend_arg);
@@ -213,7 +212,7 @@ 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(path, _, [self_arg, len_arg, fill_arg], _) = expr.kind;
+            if let ExprKind::MethodCall(path, [self_arg, len_arg, fill_arg], _) = expr.kind;
             if path_to_local_id(self_arg, self.vec_alloc.local_id);
             if path.ident.name == sym!(resize);
 
@@ -233,7 +232,7 @@ 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(take_path, _, 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)`
@@ -270,8 +269,6 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         if self.initialization_found {
             match stmt.kind {
@@ -308,8 +305,4 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
 
         walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/stable_sort_primitive.rs b/clippy_lints/src/stable_sort_primitive.rs
index 20e38dc564e..bcd28b42978 100644
--- a/clippy_lints/src/stable_sort_primitive.rs
+++ b/clippy_lints/src/stable_sort_primitive.rs
@@ -87,7 +87,7 @@ struct LintDetection {
 
 fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintDetection> {
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
+        if let ExprKind::MethodCall(method_name, args, _) = &expr.kind;
         if let Some(slice) = &args.get(0);
         if let Some(method) = SortingKind::from_stable_name(method_name.ident.name.as_str());
         if let Some(slice_type) = is_slice_of_primitives(cx, slice);
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index b4a71aefd43..3573f632a36 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -282,7 +282,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(path, _, args, _) = &e.kind;
+            if let ExprKind::MethodCall(path, args, _) = &e.kind;
             if path.ident.name == sym!(as_bytes);
             if let ExprKind::Lit(lit) = &args[0].kind;
             if let LitKind::Str(lit_content, _) = &lit.node;
@@ -324,9 +324,9 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(path, _, [recv], _) = &e.kind;
+            if let ExprKind::MethodCall(path, [recv], _) = &e.kind;
             if path.ident.name == sym!(into_bytes);
-            if let ExprKind::MethodCall(path, _, [recv], _) = &recv.kind;
+            if let ExprKind::MethodCall(path, [recv], _) = &recv.kind;
             if matches!(path.ident.name.as_str(), "to_owned" | "to_string");
             if let ExprKind::Lit(lit) = &recv.kind;
             if let LitKind::Str(lit_content, _) = &lit.node;
@@ -384,7 +384,7 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]);
 impl<'tcx> LateLintPass<'tcx> for StrToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
             if path.ident.name == sym!(to_string);
             let ty = cx.typeck_results().expr_ty(self_arg);
             if let ty::Ref(_, ty, ..) = ty.kind();
@@ -434,7 +434,7 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]);
 impl<'tcx> LateLintPass<'tcx> for StringToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
             if path.ident.name == sym!(to_string);
             let ty = cx.typeck_results().expr_ty(self_arg);
             if is_type_diagnostic_item(cx, ty, sym::String);
diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs
index d6e948a7560..7bc9cf742e6 100644
--- a/clippy_lints/src/strlen_on_c_strings.rs
+++ b/clippy_lints/src/strlen_on_c_strings.rs
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings {
             if let ExprKind::Path(path) = &func.kind;
             if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id();
             if match_libc_symbol(cx, did, "strlen");
-            if let ExprKind::MethodCall(path, _, [self_arg], _) = recv.kind;
+            if let ExprKind::MethodCall(path, [self_arg], _) = recv.kind;
             if !recv.span.from_expansion();
             if path.ident.name == sym::as_ptr;
             then {
diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs
index ca725918e87..c3d984fb5ae 100644
--- a/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/clippy_lints/src/suspicious_operation_groupings.rs
@@ -567,7 +567,6 @@ fn ident_difference_expr_with_base_location(
         | (Repeat(_, _), Repeat(_, _))
         | (Struct(_), Struct(_))
         | (MacCall(_), MacCall(_))
-        | (LlvmInlineAsm(_), LlvmInlineAsm(_))
         | (InlineAsm(_), InlineAsm(_))
         | (Ret(_), Ret(_))
         | (Continue(_), Continue(_))
diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs
index a3195de81d1..4294464dbf6 100644
--- a/clippy_lints/src/suspicious_trait_impl.rs
+++ b/clippy_lints/src/suspicious_trait_impl.rs
@@ -2,9 +2,8 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
 use if_chain::if_chain;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -66,7 +65,7 @@ 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 let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
+            if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn);
             if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
             let body = cx.tcx.hir().body(body_id);
             let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
@@ -104,8 +103,6 @@ struct BinaryExprVisitor {
 }
 
 impl<'tcx> Visitor<'tcx> for BinaryExprVisitor {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
         match expr.kind {
             hir::ExprKind::Binary(..)
@@ -116,8 +113,4 @@ impl<'tcx> Visitor<'tcx> for BinaryExprVisitor {
 
         walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs
index 5eb58b47838..aa6c01b3a7c 100644
--- a/clippy_lints/src/to_digit_is_some.rs
+++ b/clippy_lints/src/to_digit_is_some.rs
@@ -39,12 +39,12 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]);
 impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if_chain! {
-            if let hir::ExprKind::MethodCall(is_some_path, _, is_some_args, _) = &expr.kind;
+            if let hir::ExprKind::MethodCall(is_some_path, is_some_args, _) = &expr.kind;
             if is_some_path.ident.name.as_str() == "is_some";
             if let [to_digit_expr] = &**is_some_args;
             then {
                 let match_result = match &to_digit_expr.kind {
-                    hir::ExprKind::MethodCall(to_digits_path, _, to_digit_args, _) => {
+                    hir::ExprKind::MethodCall(to_digits_path, to_digit_args, _) => {
                         if_chain! {
                             if let [char_arg, radix_arg] = &**to_digit_args;
                             if to_digits_path.ident.name.as_str() == "to_digit";
diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs
index f8b6bdcd3e1..03060d78fc5 100644
--- a/clippy_lints/src/to_string_in_display.rs
+++ b/clippy_lints/src/to_string_in_display.rs
@@ -93,7 +93,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(path, _, [ref self_arg, ..], _) = expr.kind;
+            if let ExprKind::MethodCall(path, [ref self_arg, ..], _) = 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_diag_trait_item(cx, expr_def_id, sym::ToString);
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 6369aafe3f9..5257f5302cd 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::{SpanlessEq, SpanlessHash};
 use core::hash::{Hash, Hasher};
 use if_chain::if_chain;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) {
         let Generics { where_clause, .. } = &item.generics;
-        let mut self_bounds_set = FxHashSet::default();
+        let mut self_bounds_map = FxHashMap::default();
 
         for predicate in where_clause.predicates {
             if_chain! {
@@ -108,27 +108,29 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
                         )
                     ) = cx.tcx.hir().get_if_local(*def_id);
                 then {
-                    if self_bounds_set.is_empty() {
+                    if self_bounds_map.is_empty() {
                         for bound in self_bounds.iter() {
-                            let Some((self_res, _)) = get_trait_res_span_from_bound(bound) else { continue };
-                            self_bounds_set.insert(self_res);
+                            let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { continue };
+                            self_bounds_map.insert(self_res, self_segments);
                         }
                     }
 
                     bound_predicate
                         .bounds
                         .iter()
-                        .filter_map(get_trait_res_span_from_bound)
-                        .for_each(|(trait_item_res, span)| {
-                            if self_bounds_set.get(&trait_item_res).is_some() {
-                                span_lint_and_help(
-                                    cx,
-                                    TRAIT_DUPLICATION_IN_BOUNDS,
-                                    span,
-                                    "this trait bound is already specified in trait declaration",
-                                    None,
-                                    "consider removing this trait bound",
-                                );
+                        .filter_map(get_trait_info_from_bound)
+                        .for_each(|(trait_item_res, trait_item_segments, span)| {
+                            if let Some(self_segments) = self_bounds_map.get(&trait_item_res) {
+                                if SpanlessEq::new(cx).eq_path_segments(self_segments, trait_item_segments) {
+                                    span_lint_and_help(
+                                        cx,
+                                        TRAIT_DUPLICATION_IN_BOUNDS,
+                                        span,
+                                        "this trait bound is already specified in trait declaration",
+                                        None,
+                                        "consider removing this trait bound",
+                                    );
+                                }
                             }
                         });
                 }
@@ -137,14 +139,6 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
     }
 }
 
-fn get_trait_res_span_from_bound(bound: &GenericBound<'_>) -> Option<(Res, Span)> {
-    if let GenericBound::Trait(t, _) = bound {
-        Some((t.trait_ref.path.res, t.span))
-    } else {
-        None
-    }
-}
-
 impl TraitBounds {
     fn check_type_repetition<'tcx>(self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
         struct SpanlessTy<'cx, 'tcx> {
@@ -231,7 +225,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
             let res = param
                 .bounds
                 .iter()
-                .filter_map(get_trait_res_span_from_bound)
+                .filter_map(get_trait_info_from_bound)
                 .collect::<Vec<_>>();
             map.insert(*ident, res);
         }
@@ -245,10 +239,10 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
             if let Some(segment) = segments.first();
             if let Some(trait_resolutions_direct) = map.get(&segment.ident);
             then {
-                for (res_where, _) in bound_predicate.bounds.iter().filter_map(get_trait_res_span_from_bound) {
-                    if let Some((_, span_direct)) = trait_resolutions_direct
+                for (res_where, _,  _) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
+                    if let Some((_, _, span_direct)) = trait_resolutions_direct
                                                 .iter()
-                                                .find(|(res_direct, _)| *res_direct == res_where) {
+                                                .find(|(res_direct, _, _)| *res_direct == res_where) {
                         span_lint_and_help(
                             cx,
                             TRAIT_DUPLICATION_IN_BOUNDS,
@@ -263,3 +257,11 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
         }
     }
 }
+
+fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'a [PathSegment<'a>], Span)> {
+    if let GenericBound::Trait(t, _) = bound {
+        Some((t.trait_ref.path.res, t.trait_ref.path.segments, t.span))
+    } else {
+        None
+    }
+}
diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs
index 9d57505e55e..67cc8913318 100644
--- a/clippy_lints/src/types/mod.rs
+++ b/clippy_lints/src/types/mod.rs
@@ -312,12 +312,12 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO
 
 impl<'tcx> LateLintPass<'tcx> for Types {
     fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
-        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
-        };
+        let is_in_trait_impl =
+            if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id)) {
+                matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
+            } else {
+                false
+            };
 
         let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(id));
 
@@ -353,7 +353,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
         match item.kind {
             ImplItemKind::Const(ty, _) => {
                 let is_in_trait_impl = if let Some(hir::Node::Item(item)) =
-                    cx.tcx.hir().find(cx.tcx.hir().get_parent_item(item.hir_id()))
+                    cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()))
                 {
                     matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
                 } else {
diff --git a/clippy_lints/src/types/type_complexity.rs b/clippy_lints/src/types/type_complexity.rs
index 20c136407a1..5ca4023aa5c 100644
--- a/clippy_lints/src/types/type_complexity.rs
+++ b/clippy_lints/src/types/type_complexity.rs
@@ -1,9 +1,8 @@
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_inf, walk_ty, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_inf, walk_ty, 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;
@@ -37,8 +36,6 @@ struct TypeComplexityVisitor {
 }
 
 impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
-    type Map = Map<'tcx>;
-
     fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
         self.score += 1;
         walk_inf(self, inf);
@@ -78,7 +75,4 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
         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/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs
index 697ed267e2f..e42c6c63ede 100644
--- a/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -2,11 +2,10 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::is_lint_allowed;
 use clippy_utils::source::{indent_of, reindent_multiline, snippet};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, HirId, Local, UnsafeSource};
 use rustc_lexer::TokenKind;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -114,12 +113,6 @@ impl LateLintPass<'_> for UndocumentedUnsafeBlocks {
 }
 
 impl<'v> Visitor<'v> for UndocumentedUnsafeBlocks {
-    type Map = Map<'v>;
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-
     fn visit_expr(&mut self, ex: &'v Expr<'v>) {
         match ex.kind {
             ExprKind::Block(_, _) => self.local_level = self.local_level.saturating_add(1),
diff --git a/clippy_lints/src/uninit_vec.rs b/clippy_lints/src/uninit_vec.rs
index 2ffaf24f942..6d909c34690 100644
--- a/clippy_lints/src/uninit_vec.rs
+++ b/clippy_lints/src/uninit_vec.rs
@@ -177,7 +177,7 @@ fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt
                     });
                 }
             },
-            ExprKind::MethodCall(path, _, [self_expr, _], _) if is_reserve(cx, path, self_expr) => {
+            ExprKind::MethodCall(path, [self_expr, _], _) if is_reserve(cx, path, self_expr) => {
                 return Some(TargetVec {
                     location: VecLocation::Expr(self_expr),
                     init_kind: None,
@@ -211,7 +211,7 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
         }
     });
     match expr.kind {
-        ExprKind::MethodCall(path, _, [self_expr, _], _) => {
+        ExprKind::MethodCall(path, [self_expr, _], _) => {
             let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
             if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" {
                 Some((self_expr, expr.span))
diff --git a/clippy_lints/src/unit_hash.rs b/clippy_lints/src/unit_hash.rs
index dcf8a9d7c84..88ca0cb20a1 100644
--- a/clippy_lints/src/unit_hash.rs
+++ b/clippy_lints/src/unit_hash.rs
@@ -49,7 +49,7 @@ declare_lint_pass!(UnitHash => [UNIT_HASH]);
 impl<'tcx> LateLintPass<'tcx> for UnitHash {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if_chain! {
-            if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
+            if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind;
             if name_ident.ident.name == sym::hash;
             if let [recv, state_param] = args;
             if cx.typeck_results().expr_ty(recv).is_unit();
diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs
index fe35ff33d35..eee1229e1ef 100644
--- a/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/clippy_lints/src/unit_return_expecting_ord.rs
@@ -98,9 +98,11 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
                         if trait_pred.self_ty() == inp;
                         if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
                         then {
-                            if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) {
+                            if ord_preds.iter().any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty()) {
                                 args_to_check.push((i, "Ord".to_string()));
-                            } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) {
+                            } else if partial_ord_preds.iter().any(|pord| {
+                                pord.self_ty() == return_ty_pred.term.ty().unwrap()
+                            }) {
                                 args_to_check.push((i, "PartialOrd".to_string()));
                             }
                         }
@@ -141,7 +143,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(_, _, 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/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs
index 57be2d2f674..97d92f10e1c 100644
--- a/clippy_lints/src/unit_types/unit_arg.rs
+++ b/clippy_lints/src/unit_types/unit_arg.rs
@@ -30,7 +30,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
     }
 
     match expr.kind {
-        ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
+        ExprKind::Call(_, args) | ExprKind::MethodCall(_, args, _) => {
             let args_to_recover = args
                 .iter()
                 .filter(|arg| {
diff --git a/clippy_lints/src/unnecessary_sort_by.rs b/clippy_lints/src/unnecessary_sort_by.rs
index d024577f485..e6c260ed96a 100644
--- a/clippy_lints/src/unnecessary_sort_by.rs
+++ b/clippy_lints/src/unnecessary_sort_by.rs
@@ -93,10 +93,7 @@ fn mirrored_exprs(
         // The two exprs are method calls.
         // Check to see that the function is the same and the arguments are mirrored
         // This is enough because the receiver of the method is listed in the arguments
-        (
-            ExprKind::MethodCall(left_segment, _, left_args, _),
-            ExprKind::MethodCall(right_segment, _, right_args, _),
-        ) => {
+        (ExprKind::MethodCall(left_segment, left_args, _), ExprKind::MethodCall(right_segment, right_args, _)) => {
             left_segment.ident == right_segment.ident
                 && iter::zip(*left_args, *right_args)
                     .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
@@ -165,7 +162,7 @@ fn mirrored_exprs(
 
 fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
     if_chain! {
-        if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
+        if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind;
         if let name = name_ident.ident.name.to_ident_string();
         if name == "sort_by" || name == "sort_unstable_by";
         if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args;
@@ -175,7 +172,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
             Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
             Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. }
         ] = &closure_body.params;
-        if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr], _) = &closure_body.value.kind;
+        if let ExprKind::MethodCall(method_path, [ref left_expr, ref right_expr], _) = &closure_body.value.kind;
         if method_path.ident.name == sym::cmp;
         then {
             let (closure_body, closure_arg, reverse) = if mirrored_exprs(
@@ -224,10 +221,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
 
 fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
-    matches!(ty.kind(), ty::Ref(..))
-        || ty
-            .walk(cx.tcx)
-            .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+    matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
 }
 
 impl LateLintPass<'_> for UnnecessarySortBy {
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index 0bd151fed91..1d4fe9cfd3c 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -291,7 +291,7 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize)
 fn extend_with_struct_pat(
     qself1: &Option<ast::QSelf>,
     path1: &ast::Path,
-    fps1: &mut Vec<ast::PatField>,
+    fps1: &mut [ast::PatField],
     rest1: bool,
     start: usize,
     alternatives: &mut Vec<P<Pat>>,
@@ -332,7 +332,7 @@ fn extend_with_struct_pat(
 /// while also requiring `ps1[..n] ~ ps2[..n]` (pre) and `ps1[n + 1..] ~ ps2[n + 1..]` (post),
 /// where `~` denotes semantic equality.
 fn extend_with_matching_product(
-    targets: &mut Vec<P<Pat>>,
+    targets: &mut [P<Pat>],
     start: usize,
     alternatives: &mut Vec<P<Pat>>,
     predicate: impl Fn(&PatKind, &[P<Pat>], usize) -> bool,
diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs
index 1ccb78425c2..2b89398ecd6 100644
--- a/clippy_lints/src/unused_async.rs
+++ b/clippy_lints/src/unused_async.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, YieldSource};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 
@@ -43,7 +43,7 @@ struct AsyncFnVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         if let ExprKind::Yield(_, YieldSource::Await { .. }) = ex.kind {
@@ -52,8 +52,8 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
         walk_expr(self, ex);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index 287ac5b4a90..323cf83ffcf 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/clippy_lints/src/unused_io_amount.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
                     check_map_error(cx, res, expr);
                 }
             },
-            hir::ExprKind::MethodCall(path, _, [ref arg_0, ..], _) => match path.ident.as_str() {
+            hir::ExprKind::MethodCall(path, [ref arg_0, ..], _) => match path.ident.as_str() {
                 "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
                     check_map_error(cx, arg_0, expr);
                 },
@@ -94,7 +94,7 @@ fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> {
 
 fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
     let mut call = call;
-    while let hir::ExprKind::MethodCall(path, _, args, _) = call.kind {
+    while let hir::ExprKind::MethodCall(path, args, _) = call.kind {
         if matches!(path.ident.as_str(), "or" | "or_else" | "ok") {
             call = &args[0];
         } else {
@@ -110,7 +110,7 @@ fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<
 }
 
 fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) {
-    if let hir::ExprKind::MethodCall(path, _, _, _) = call.kind {
+    if let hir::ExprKind::MethodCall(path, _, _) = call.kind {
         let symbol = path.ident.as_str();
         let read_trait = if is_await {
             match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs
index aa105580ee3..fd9d5b52e50 100644
--- a/clippy_lints/src/unused_self.rs
+++ b/clippy_lints/src/unused_self.rs
@@ -42,7 +42,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
         if impl_item.span.from_expansion() {
             return;
         }
-        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
         let parent_item = cx.tcx.hir().expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.def_id);
         if_chain! {
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index 918fa5f7dc1..e9840487013 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -4,10 +4,10 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{differing_macro_contexts, path_to_local, usage::is_potentially_mutated};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, PathSegment, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::Ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -154,7 +154,7 @@ fn collect_unwrap_info<'tcx>(
         return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false);
     } else {
         if_chain! {
-            if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
+            if let ExprKind::MethodCall(method_name, args, _) = &expr.kind;
             if let Some(local_id) = path_to_local(&args[0]);
             let ty = cx.typeck_results().expr_ty(&args[0]);
             let name = method_name.ident.as_str();
@@ -215,7 +215,7 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         // Shouldn't lint when `expr` is in macro.
@@ -231,7 +231,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
         } else {
             // find `unwrap[_err]()` calls:
             if_chain! {
-                if let ExprKind::MethodCall(method_name, _, [self_arg, ..], _) = expr.kind;
+                if let ExprKind::MethodCall(method_name, [self_arg, ..], _) = expr.kind;
                 if let Some(id) = path_to_local(self_arg);
                 if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name);
                 let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name);
@@ -297,8 +297,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs
index 994df85cb8a..2c13f1049b5 100644
--- a/clippy_lints/src/unwrap_in_result.rs
+++ b/clippy_lints/src/unwrap_in_result.rs
@@ -3,10 +3,9 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{method_chain_args, return_ty};
 use if_chain::if_chain;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Expr, ImplItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
@@ -81,8 +80,6 @@ struct FindExpectUnwrap<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         // check for `expect`
         if let Some(arglists) = method_chain_args(expr, &["expect"]) {
@@ -107,10 +104,6 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> {
         // and check sub-expressions
         intravisit::walk_expr(self, expr);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index a86db58741e..be20282b3b8 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -8,11 +8,10 @@ use rustc_hir::{
     self as hir,
     def::{CtorOf, DefKind, Res},
     def_id::LocalDefId,
-    intravisit::{walk_inf, walk_ty, NestedVisitorMap, Visitor},
+    intravisit::{walk_inf, walk_ty, Visitor},
     Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind,
 };
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
@@ -170,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
                 //
                 // See also https://github.com/rust-lang/rust-clippy/issues/2894.
                 for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
-                    if trait_sem_ty.walk(cx.tcx).any(|inner| inner == self_ty.into()) {
+                    if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
                         let mut visitor = SkipTyCollector::default();
                         visitor.visit_ty(impl_hir_ty);
                         types_to_skip.extend(visitor.types_to_skip);
@@ -262,8 +261,6 @@ struct SkipTyCollector {
 }
 
 impl<'tcx> Visitor<'tcx> for SkipTyCollector {
-    type Map = Map<'tcx>;
-
     fn visit_infer(&mut self, inf: &hir::InferArg) {
         self.types_to_skip.push(inf.hir_id);
 
@@ -274,10 +271,6 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector {
 
         walk_ty(self, hir_ty);
     }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 fn span_lint(cx: &LateContext<'_>, span: Span) {
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index 7751c593e43..d23c85c033b 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -402,9 +402,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 self.expr(func);
                 self.slice(args, |e| self.expr(e));
             },
-            ExprKind::MethodCall(method_name, _, args, _) => {
+            ExprKind::MethodCall(method_name, args, _) => {
                 bind!(self, method_name, args);
-                kind!("MethodCall({method_name}, _, {args}, _)");
+                kind!("MethodCall({method_name}, {args}, _)");
                 self.ident(field!(method_name.ident));
                 self.slice(args, |e| self.expr(e));
             },
@@ -547,10 +547,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 kind!("InlineAsm(_)");
                 out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment");
             },
-            ExprKind::LlvmInlineAsm(_) => {
-                kind!("LlvmInlineAsm(_)");
-                out!("// unimplemented: `ExprKind::LlvmInlineAsm` is not further destructured at the moment");
-            },
             ExprKind::Struct(qpath, fields, base) => {
                 bind!(self, qpath, fields);
                 opt_bind!(self, base);
diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs
index e90b6b73b34..b58325ac73e 100644
--- a/clippy_lints/src/utils/inspector.rs
+++ b/clippy_lints/src/utils/inspector.rs
@@ -149,7 +149,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             }
             print_expr(cx, init, indent + 1);
         },
-        hir::ExprKind::MethodCall(path, _, args, _) => {
+        hir::ExprKind::MethodCall(path, args, _) => {
             println!("{}MethodCall", ind);
             println!("{}method name: {}", ind, path.ident.name);
             for arg in args {
@@ -304,19 +304,6 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                 }
             }
         },
-        hir::ExprKind::LlvmInlineAsm(asm) => {
-            let inputs = &asm.inputs_exprs;
-            let outputs = &asm.outputs_exprs;
-            println!("{}LlvmInlineAsm", ind);
-            println!("{}inputs:", ind);
-            for e in inputs.iter() {
-                print_expr(cx, e, indent + 1);
-            }
-            println!("{}outputs:", ind);
-            for e in outputs.iter() {
-                print_expr(cx, e, indent + 1);
-            }
-        },
         hir::ExprKind::Struct(path, fields, ref base) => {
             println!("{}Struct", ind);
             println!("{}path: {:?}", ind, path);
diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
index 9c3dcc8e96a..f170ff69154 100644
--- a/clippy_lints/src/utils/internal_lints.rs
+++ b/clippy_lints/src/utils/internal_lints.rs
@@ -17,13 +17,13 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::CRATE_HIR_ID;
-use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::{
     BinOpKind, Block, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty, TyKind,
     UnOp,
 };
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty;
 use rustc_semver::RustcVersion;
@@ -544,7 +544,7 @@ struct LintCollector<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
     fn visit_path(&mut self, path: &'tcx Path<'_>, _: HirId) {
         if path.segments.len() == 1 {
@@ -552,8 +552,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
@@ -584,7 +584,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, [self_arg, ..], _) = &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(self_arg).peel_refs();
@@ -666,7 +666,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
             if let ExprKind::Closure(_, _, body_id, _, _) = &and_then_args[4].kind;
             let body = cx.tcx.hir().body(*body_id);
             let only_expr = peel_blocks_with_stmt(&body.value);
-            if let ExprKind::MethodCall(ps, _, span_call_args, _) = &only_expr.kind;
+            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();
@@ -1098,7 +1098,7 @@ impl InterningDefinedSymbol {
         };
         if_chain! {
             // is a method call
-            if let ExprKind::MethodCall(_, _, [item], _) = call.kind;
+            if let ExprKind::MethodCall(_, [item], _) = call.kind;
             if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id);
             let ty = cx.typeck_results().expr_ty(item);
             // ...on either an Ident or a Symbol
diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 4e46d79dc08..3547f0b4e0a 100644
--- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -19,8 +19,9 @@ use rustc_hir::{
     self as hir, def::DefKind, intravisit, intravisit::Visitor, ExprKind, Item, ItemKind, Mutability, QPath,
 };
 use rustc_lint::{CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId};
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::symbol::Ident;
 use rustc_span::{sym, Loc, Span, Symbol};
 use serde::{ser::SerializeStruct, Serialize, Serializer};
 use std::collections::BinaryHeap;
@@ -579,9 +580,11 @@ fn get_lint_group_and_level_or_lint(
     lint_name: &str,
     item: &Item<'_>,
 ) -> Option<(String, &'static str)> {
-    let result = cx
-        .lint_store
-        .check_lint_name(cx.sess(), lint_name, Some(sym::clippy), &[]);
+    let result = cx.lint_store.check_lint_name(
+        lint_name,
+        Some(sym::clippy),
+        &[Ident::with_dummy_span(sym::clippy)].into_iter().collect(),
+    );
     if let CheckLintNameResult::Tool(Ok(lint_lst)) = result {
         if let Some(group) = get_lint_group(cx, lint_lst[0]) {
             if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) {
@@ -738,10 +741,10 @@ impl<'a, 'hir> LintResolver<'a, 'hir> {
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
-    type Map = Map<'hir>;
+    type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 
     fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
@@ -792,10 +795,10 @@ impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> {
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
-    type Map = Map<'hir>;
+    type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 
     fn visit_path(&mut self, path: &'hir hir::Path<'hir>, _id: hir::HirId) {
@@ -875,10 +878,10 @@ impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> {
 }
 
 impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
-    type Map = Map<'hir>;
+    type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::All(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 
     fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
@@ -897,7 +900,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
                     self.add_single_span_suggestion();
                 }
             },
-            ExprKind::MethodCall(path, _path_span, arg, _arg_span) => {
+            ExprKind::MethodCall(path, arg, _arg_span) => {
                 let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&arg[0]));
                 if match_type(self.cx, self_ty, &paths::DIAGNOSTIC_BUILDER) {
                     let called_method = path.ident.name.as_str().to_string();
diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs
index 43474da3450..fbf2b3e081b 100644
--- a/clippy_lints/src/vec_init_then_push.rs
+++ b/clippy_lints/src/vec_init_then_push.rs
@@ -125,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush {
         if let Some(searcher) = self.searcher.take() {
             if_chain! {
                 if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind;
-                if let ExprKind::MethodCall(path, _, [self_arg, _], _) = expr.kind;
+                if let ExprKind::MethodCall(path, [self_arg, _], _) = expr.kind;
                 if path_to_local_id(self_arg, searcher.local_id);
                 if path.ident.name.as_str() == "push";
                 then {
diff --git a/clippy_lints/src/vec_resize_to_zero.rs b/clippy_lints/src/vec_resize_to_zero.rs
index 3441d9ccdfa..4d86abd0fa1 100644
--- a/clippy_lints/src/vec_resize_to_zero.rs
+++ b/clippy_lints/src/vec_resize_to_zero.rs
@@ -31,7 +31,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, _, 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/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs
index ebdaff1e676..8e2ddd225fd 100644
--- a/clippy_lints/src/verbose_file_reads.rs
+++ b/clippy_lints/src/verbose_file_reads.rs
@@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for VerboseFileReads {
 
 fn is_file_read_to_end<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind;
+        if let ExprKind::MethodCall(method_name, exprs, _) = expr.kind;
         if method_name.ident.as_str() == "read_to_end";
         if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind;
         let ty = cx.typeck_results().expr_ty(&exprs[0]);
@@ -75,7 +75,7 @@ fn is_file_read_to_end<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) ->
 
 fn is_file_read_to_string<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind;
+        if let ExprKind::MethodCall(method_name, exprs, _) = expr.kind;
         if method_name.ident.as_str() == "read_to_string";
         if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind;
         let ty = cx.typeck_results().expr_ty(&exprs[0]);
diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs
index f9add927b49..b0044695ea8 100644
--- a/clippy_lints/src/write.rs
+++ b/clippy_lints/src/write.rs
@@ -9,7 +9,7 @@ use rustc_ast::token::{self, LitKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::Applicability;
 use rustc_lexer::unescape::{self, EscapeError};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_parse::parser;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{kw, Symbol};
@@ -290,7 +290,7 @@ impl EarlyLintPass for Write {
     fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &MacCall) {
         fn is_build_script(cx: &EarlyContext<'_>) -> bool {
             // Cargo sets the crate name for build scripts to `build_script_build`
-            cx.sess
+            cx.sess()
                 .opts
                 .crate_name
                 .as_ref()
@@ -529,7 +529,7 @@ impl Write {
     /// ```
     #[allow(clippy::too_many_lines)]
     fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) {
-        let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None);
+        let mut parser = parser::Parser::new(&cx.sess().parse_sess, tts, false, None);
         let expr = if is_write {
             match parser
                 .parse_expr()
diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs
index eb8436a501d..70b0560e676 100644
--- a/clippy_lints/src/zero_sized_map_values.rs
+++ b/clippy_lints/src/zero_sized_map_values.rs
@@ -69,7 +69,11 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
 
 fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(hir_id);
-    if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(parent_id)) {
+    let second_parent_id = cx
+        .tcx
+        .hir()
+        .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(parent_id));
+    if let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(second_parent_id) {
         if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
             return true;
         }
diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs
index 3d3180521ab..3f4043ad052 100644
--- a/clippy_utils/src/ast_utils.rs
+++ b/clippy_utils/src/ast_utils.rs
@@ -645,11 +645,19 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool {
     }
 }
 
-pub fn eq_assoc_constraint(l: &AssocTyConstraint, r: &AssocTyConstraint) -> bool {
-    use AssocTyConstraintKind::*;
+fn eq_term(l: &Term, r: &Term) -> bool {
+    match (l, r) {
+        (Term::Ty(l), Term::Ty(r)) => eq_ty(l, r),
+        (Term::Const(l), Term::Const(r)) => eq_anon_const(l, r),
+        _ => false,
+    }
+}
+
+pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool {
+    use AssocConstraintKind::*;
     eq_id(l.ident, r.ident)
         && match (&l.kind, &r.kind) {
-            (Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r),
+            (Equality { term: l }, Equality { term: r }) => eq_term(l, r),
             (Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound),
             _ => false,
         }
diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs
index c3936ec95d4..eb9efec3f16 100644
--- a/clippy_utils/src/eager_or_lazy.rs
+++ b/clippy_utils/src/eager_or_lazy.rs
@@ -12,7 +12,7 @@
 use crate::ty::{all_predicates_of, is_copy};
 use crate::visitors::is_const_evaluatable;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, PredicateKind};
@@ -104,11 +104,6 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
     }
 
     impl<'cx, 'tcx> Visitor<'tcx> for V<'cx, 'tcx> {
-        type Map = ErasedMap<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             use EagernessSuggestion::{ForceNoChange, Lazy, NoChange};
             if self.eagerness == ForceNoChange {
@@ -146,7 +141,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                     self.eagerness |= NoChange;
                     return;
                 },
-                ExprKind::MethodCall(name, _, args, _) => {
+                ExprKind::MethodCall(name, args, _) => {
                     self.eagerness |= self
                         .cx
                         .typeck_results()
@@ -180,7 +175,6 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 | ExprKind::Continue(_)
                 | ExprKind::Ret(_)
                 | ExprKind::InlineAsm(_)
-                | ExprKind::LlvmInlineAsm(_)
                 | ExprKind::Yield(..)
                 | ExprKind::Err => {
                     self.eagerness = ForceNoChange;
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 5a08a411dd1..ed573ad9056 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -258,7 +258,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                             && self.eq_expr(l.body, r.body)
                     })
             },
-            (&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
+            (&ExprKind::MethodCall(l_path, l_args, _), &ExprKind::MethodCall(r_path, r_args, _)) => {
                 self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
             },
             (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
@@ -683,7 +683,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 }
                 self.hash_pat(pat);
             },
-            ExprKind::LlvmInlineAsm(..) | ExprKind::Err => {},
+            ExprKind::Err => {},
             ExprKind::Lit(ref l) => {
                 l.node.hash(&mut self.s);
             },
@@ -713,7 +713,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
                 s.hash(&mut self.s);
             },
-            ExprKind::MethodCall(path, ref _tys, args, ref _fn_span) => {
+            ExprKind::MethodCall(path, args, ref _fn_span) => {
                 self.hash_name(path.ident.name);
                 self.hash_exprs(args);
             },
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 5c97535dcdf..a2f1f469651 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -70,9 +70,9 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
-use rustc_hir::intravisit::{walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
 use rustc_hir::{
@@ -82,7 +82,6 @@ use rustc_hir::{
     Target, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
 };
 use rustc_lint::{LateContext, Level, Lint, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::ty as rustc_ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
@@ -90,7 +89,6 @@ use rustc_middle::ty::binding::BindingMode;
 use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture};
 use rustc_semver::RustcVersion;
 use rustc_session::Session;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::original_sp;
 use rustc_span::sym;
@@ -119,25 +117,15 @@ pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool
 
 #[macro_export]
 macro_rules! extract_msrv_attr {
-    (LateContext) => {
-        extract_msrv_attr!(@LateContext, ());
-    };
-    (EarlyContext) => {
-        extract_msrv_attr!(@EarlyContext);
-    };
-    (@$context:ident$(, $call:tt)?) => {
+    ($context:ident) => {
         fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
-            use $crate::get_unique_inner_attr;
-            match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") {
+            let sess = rustc_lint::LintContext::sess(cx);
+            match $crate::get_unique_inner_attr(sess, attrs, "msrv") {
                 Some(msrv_attr) => {
                     if let Some(msrv) = msrv_attr.value_str() {
-                        self.msrv = $crate::parse_msrv(
-                            &msrv.to_string(),
-                            Some(cx.sess$($call)?),
-                            Some(msrv_attr.span),
-                        );
+                        self.msrv = $crate::parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span));
                     } else {
-                        cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute");
+                        sess.span_err(msrv_attr.span, "bad clippy attribute");
                     }
                 },
                 _ => (),
@@ -216,7 +204,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
 /// ```
 pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(id);
-    match cx.tcx.hir().get(parent_id) {
+    match cx.tcx.hir().get_by_def_id(parent_id) {
         Node::Item(&Item {
             kind: ItemKind::Const(..) | ItemKind::Static(..),
             ..
@@ -607,12 +595,13 @@ pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
 ///     }
 /// }
 /// ```
-pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> {
+pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> Option<&'tcx TraitRef<'tcx>> {
     // Get the implemented trait for the current function
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
     let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
     if_chain! {
-        if parent_impl != hir::CRATE_HIR_ID;
-        if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
+        if parent_impl != CRATE_DEF_ID;
+        if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl);
         if let hir::ItemKind::Impl(impl_) = &item.kind;
         then { return impl_.of_trait.as_ref(); }
     }
@@ -810,8 +799,7 @@ pub fn can_move_expr_to_closure_no_visit<'tcx>(
         | ExprKind::Continue(_)
         | ExprKind::Ret(_)
         | ExprKind::Yield(..)
-        | ExprKind::InlineAsm(_)
-        | ExprKind::LlvmInlineAsm(_) => false,
+        | ExprKind::InlineAsm(_) => false,
         // Accessing a field of a local value can only be done if the type isn't
         // partially moved.
         ExprKind::Field(
@@ -982,11 +970,6 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
         captures: HirIdMap<CaptureKind>,
     }
     impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
-        type Map = ErasedMap<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if !self.allow_closure {
                 return;
@@ -1009,8 +992,8 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
                         };
                         if !self.locals.contains(&local_id) {
                             let capture = match capture.info.capture_kind {
-                                UpvarCapture::ByValue(_) => CaptureKind::Value,
-                                UpvarCapture::ByRef(borrow) => match borrow.kind {
+                                UpvarCapture::ByValue => CaptureKind::Value,
+                                UpvarCapture::ByRef(kind) => match kind {
                                     BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
                                     BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
                                         CaptureKind::Ref(Mutability::Mut)
@@ -1066,13 +1049,13 @@ pub fn method_calls<'tcx>(
 
     let mut current = expr;
     for _ in 0..max_depth {
-        if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
+        if let ExprKind::MethodCall(path, args, _) = &current.kind {
             if args.iter().any(|e| e.span.from_expansion()) {
                 break;
             }
             method_names.push(path.ident.name);
             arg_lists.push(&**args);
-            spans.push(*span);
+            spans.push(path.ident.span);
             current = &args[0];
         } else {
             break;
@@ -1093,7 +1076,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec
     let mut matched = Vec::with_capacity(methods.len());
     for method_name in methods.iter().rev() {
         // method chains are stored last -> first
-        if let ExprKind::MethodCall(path, _, args, _) = current.kind {
+        if let ExprKind::MethodCall(path, args, _) = current.kind {
             if path.ident.name.as_str() == *method_name {
                 if args.iter().any(|e| e.span.from_expansion()) {
                     return None;
@@ -1122,14 +1105,13 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
 /// Returns `true` if the expression is in the program's `#[panic_handler]`.
 pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     let parent = cx.tcx.hir().get_parent_item(e.hir_id);
-    let def_id = cx.tcx.hir().local_def_id(parent).to_def_id();
-    Some(def_id) == cx.tcx.lang_items().panic_impl()
+    Some(parent.to_def_id()) == cx.tcx.lang_items().panic_impl()
 }
 
 /// Gets the name of the item the expression is in, if available.
 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
-    match cx.tcx.hir().find(parent_id) {
+    match cx.tcx.hir().find_by_def_id(parent_id) {
         Some(
             Node::Item(Item { ident, .. })
             | Node::TraitItem(TraitItem { ident, .. })
@@ -1145,16 +1127,11 @@ pub struct ContainsName {
 }
 
 impl<'tcx> Visitor<'tcx> for ContainsName {
-    type Map = Map<'tcx>;
-
     fn visit_name(&mut self, _: Span, name: Symbol) {
         if self.name == name {
             self.result = true;
         }
     }
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
 }
 
 /// Checks if an `Expr` contains a certain name.
@@ -1639,7 +1616,7 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool
             return true;
         }
         prev_enclosing_node = Some(enclosing_node);
-        enclosing_node = map.get_parent_item(enclosing_node);
+        enclosing_node = map.local_def_id_to_hir_id(map.get_parent_item(enclosing_node));
     }
 
     false
@@ -1793,7 +1770,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
                 None
             }
         },
-        ExprKind::MethodCall(_, _, _, _) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
+        ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
         _ => None,
     };
 
@@ -1850,7 +1827,8 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
 }
 
 /// Gets the node where an expression is either used, or it's type is unified with another branch.
-pub fn get_expr_use_or_unification_node<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
+/// Returns both the node and the `HirId` of the closest child node.
+pub fn get_expr_use_or_unification_node<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<(Node<'tcx>, HirId)> {
     let mut child_id = expr.hir_id;
     let mut iter = tcx.hir().parent_iter(child_id);
     loop {
@@ -1862,9 +1840,9 @@ pub fn get_expr_use_or_unification_node<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>
                 ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id,
                 ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id,
                 ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None,
-                _ => break Some(Node::Expr(expr)),
+                _ => break Some((Node::Expr(expr), child_id)),
             },
-            Some((_, node)) => break Some(node),
+            Some((_, node)) => break Some((node, child_id)),
         }
     }
 }
@@ -1873,18 +1851,21 @@ pub fn get_expr_use_or_unification_node<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>
 pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
     !matches!(
         get_expr_use_or_unification_node(tcx, expr),
-        None | Some(Node::Stmt(Stmt {
-            kind: StmtKind::Expr(_)
-                | StmtKind::Semi(_)
-                | StmtKind::Local(Local {
-                    pat: Pat {
-                        kind: PatKind::Wild,
+        None | Some((
+            Node::Stmt(Stmt {
+                kind: StmtKind::Expr(_)
+                    | StmtKind::Semi(_)
+                    | StmtKind::Local(Local {
+                        pat: Pat {
+                            kind: PatKind::Wild,
+                            ..
+                        },
                         ..
-                    },
-                    ..
-                }),
-            ..
-        }))
+                    }),
+                ..
+            }),
+            _
+        ))
     )
 }
 
@@ -1956,7 +1937,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
         .predicates_of(did)
         .predicates
         .iter()
-        .filter_map(|(p, _)| if p.is_global(cx.tcx) { Some(*p) } else { None });
+        .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
     traits::impossible_predicates(
         cx.tcx,
         traits::elaborate_predicates(cx.tcx, predicates)
@@ -2002,7 +1983,7 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
     if is_primitive {
         // if we have wrappers like Array, Slice or Tuple, print these
         // and get the type enclosed in the slice ref
-        match expr_type.peel_refs().walk(cx.tcx).nth(1).unwrap().expect_ty().kind() {
+        match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
             rustc_ty::Slice(..) => return Some("slice".into()),
             rustc_ty::Array(..) => return Some("array".into()),
             rustc_ty::Tuple(..) => return Some("tuple".into()),
@@ -2010,7 +1991,7 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
                 // is_recursively_primitive_type() should have taken care
                 // of the rest and we can rely on the type that is found
                 let refs_peeled = expr_type.peel_refs();
-                return Some(refs_peeled.walk(cx.tcx).last().unwrap().to_string());
+                return Some(refs_peeled.walk().last().unwrap().to_string());
             },
         }
     }
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index a3e336d701c..b7a242cf90a 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -191,13 +191,13 @@ impl<'a> PanicExpn<'a> {
         if !macro_backtrace(expr.span).any(|macro_call| is_panic(cx, macro_call.def_id)) {
             return None;
         }
-        let ExprKind::Call(callee, [arg]) = expr.kind else { return None };
-        let ExprKind::Path(QPath::Resolved(_, path)) = callee.kind else { return None };
+        let ExprKind::Call(callee, [arg]) = &expr.kind else { return None };
+        let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else { return None };
         let result = match path.segments.last().unwrap().ident.as_str() {
             "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
             "panic" | "panic_str" => Self::Str(arg),
             "panic_display" => {
-                let ExprKind::AddrOf(_, _, e) = arg.kind else { return None };
+                let ExprKind::AddrOf(_, _, e) = &arg.kind else { return None };
                 Self::Display(e)
             },
             "panic_fmt" => Self::Format(FormatArgsExpn::parse(cx, arg)?),
diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs
index 68dd1b29845..908ff822712 100644
--- a/clippy_utils/src/numeric_literal.rs
+++ b/clippy_utils/src/numeric_literal.rs
@@ -51,7 +51,14 @@ impl<'a> NumericLiteral<'a> {
     }
 
     pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<'a>> {
-        if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) {
+        let unsigned_src = src.strip_prefix('-').map_or(src, |s| s);
+        if lit_kind.is_numeric()
+            && unsigned_src
+                .trim_start()
+                .chars()
+                .next()
+                .map_or(false, |c| c.is_digit(10))
+        {
             let (unsuffixed, suffix) = split_suffix(src, lit_kind);
             let float = matches!(lit_kind, LitKind::Float(..));
             Some(NumericLiteral::new(unsuffixed, suffix, float))
diff --git a/clippy_utils/src/ptr.rs b/clippy_utils/src/ptr.rs
index 17d9a505bc9..649b7b9940a 100644
--- a/clippy_utils/src/ptr.rs
+++ b/clippy_utils/src/ptr.rs
@@ -36,7 +36,7 @@ fn extract_clone_suggestions<'tcx>(
         if abort {
             return false;
         }
-        if let ExprKind::MethodCall(seg, _, [recv], _) = expr.kind {
+        if let ExprKind::MethodCall(seg, [recv], _) = expr.kind {
             if path_to_local_id(recv, id) {
                 if seg.ident.name.as_str() == "capacity" {
                     abort = true;
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index 8bdc9a9ea16..7512039a480 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -86,7 +86,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
 }
 
 fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
-    for arg in ty.walk(tcx) {
+    for arg in ty.walk() {
         let ty = match arg.unpack() {
             GenericArgKind::Type(ty) => ty,
 
@@ -233,8 +233,6 @@ fn check_statement<'tcx>(
         // just an assignment
         StatementKind::SetDiscriminant { place, .. } => check_place(tcx, **place, span, body),
 
-        StatementKind::LlvmInlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
-
         StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => {
             check_operand(tcx, dst, span, body)?;
             check_operand(tcx, src, span, body)?;
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index 87bc8232dde..fa63ddff253 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -147,7 +147,6 @@ impl<'a> Sugg<'a> {
             | hir::ExprKind::Field(..)
             | hir::ExprKind::Index(..)
             | hir::ExprKind::InlineAsm(..)
-            | hir::ExprKind::LlvmInlineAsm(..)
             | hir::ExprKind::ConstBlock(..)
             | hir::ExprKind::Lit(..)
             | hir::ExprKind::Loop(..)
@@ -205,7 +204,6 @@ impl<'a> Sugg<'a> {
             | ast::ExprKind::ForLoop(..)
             | ast::ExprKind::Index(..)
             | ast::ExprKind::InlineAsm(..)
-            | ast::ExprKind::LlvmInlineAsm(..)
             | ast::ExprKind::ConstBlock(..)
             | ast::ExprKind::Lit(..)
             | ast::ExprKind::Loop(..)
@@ -388,7 +386,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
 }
 
 /// Return `true` if `sugg` is enclosed in parenthesis.
-fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool {
+pub fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool {
     let mut chars = sugg.as_ref().chars();
     if chars.next() == Some('(') {
         let mut depth = 1;
@@ -865,7 +863,7 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
     /// indicates whether the function from `parent_expr` takes its args by double reference
     fn func_takes_arg_by_double_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir_id: HirId) -> bool {
         let (call_args, inputs) = match parent_expr.kind {
-            ExprKind::MethodCall(_, _, call_args, _) => {
+            ExprKind::MethodCall(_, call_args, _) => {
                 if let Some(method_did) = self.cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) {
                     (call_args, self.cx.tcx.fn_sig(method_did).skip_binder().inputs())
                 } else {
@@ -917,7 +915,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                     match &parent_expr.kind {
                         // given expression is the self argument and will be handled completely by the compiler
                         // i.e.: `|x| x.is_something()`
-                        ExprKind::MethodCall(_, _, [self_expr, ..], _) if self_expr.hir_id == cmt.hir_id => {
+                        ExprKind::MethodCall(_, [self_expr, ..], _) if self_expr.hir_id == cmt.hir_id => {
                             self.suggestion_start
                                 .push_str(&format!("{}{}", start_snip, ident_str_with_proj));
                             self.next_pos = span.hi();
@@ -925,7 +923,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         },
                         // item is used in a call
                         // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
-                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [_, call_args @ ..], _) => {
+                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, [_, call_args @ ..], _) => {
                             let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
                             let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
 
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 72317447159..d057da73302 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -5,19 +5,22 @@
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
+use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{TyKind, Unsafety};
+use rustc_hir::{Expr, TyKind, Unsafety};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, AdtDef, IntTy, Predicate, Ty, TyCtxt, TypeFoldable, UintTy};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
+use rustc_middle::ty::{
+    self, AdtDef, Binder, FnSig, IntTy, Predicate, PredicateKind, Ty, TyCtxt, TypeFoldable, UintTy,
+};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::query::normalize::AtExt;
 use std::iter;
 
-use crate::{match_def_path, must_use_attr};
+use crate::{expr_path_res, match_def_path, must_use_attr};
 
 // Checks if the given type implements copy.
 pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -37,8 +40,8 @@ pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool
 }
 
 /// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
-pub fn contains_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool {
-    ty.walk(tcx).any(|inner| match inner.unpack() {
+pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
+    ty.walk().any(|inner| match inner.unpack() {
         GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty),
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
     })
@@ -46,8 +49,8 @@ pub fn contains_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, other_ty: Ty<'tcx>) ->
 
 /// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
 /// constructor.
-pub fn contains_adt_constructor<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, adt: &'tcx AdtDef) -> bool {
-    ty.walk(tcx).any(|inner| match inner.unpack() {
+pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool {
+    ty.walk().any(|inner| match inner.unpack() {
         GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
     })
@@ -221,7 +224,7 @@ fn is_normalizable_helper<'tcx>(
                         .iter()
                         .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
                 }),
-                _ => ty.walk(cx.tcx).all(|generic_arg| match generic_arg.unpack() {
+                _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
                     GenericArgKind::Type(inner_ty) if inner_ty != ty => {
                         is_normalizable_helper(cx, param_env, inner_ty, cache)
                     },
@@ -410,3 +413,105 @@ pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(P
     })
     .flatten()
 }
+
+/// A signature for a function like type.
+#[derive(Clone, Copy)]
+pub enum ExprFnSig<'tcx> {
+    Sig(Binder<'tcx, FnSig<'tcx>>),
+    Closure(Binder<'tcx, FnSig<'tcx>>),
+    Trait(Binder<'tcx, Ty<'tcx>>, Option<Binder<'tcx, Ty<'tcx>>>),
+}
+impl<'tcx> ExprFnSig<'tcx> {
+    /// Gets the argument type at the given offset.
+    pub fn input(self, i: usize) -> Binder<'tcx, Ty<'tcx>> {
+        match self {
+            Self::Sig(sig) => sig.input(i),
+            Self::Closure(sig) => sig.input(0).map_bound(|ty| ty.tuple_element_ty(i).unwrap()),
+            Self::Trait(inputs, _) => inputs.map_bound(|ty| ty.tuple_element_ty(i).unwrap()),
+        }
+    }
+
+    /// Gets the result type, if one could be found. Note that the result type of a trait may not be
+    /// specified.
+    pub fn output(self) -> Option<Binder<'tcx, Ty<'tcx>>> {
+        match self {
+            Self::Sig(sig) | Self::Closure(sig) => Some(sig.output()),
+            Self::Trait(_, output) => output,
+        }
+    }
+}
+
+/// If the expression is function like, get the signature for it.
+pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnSig<'tcx>> {
+    if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) = expr_path_res(cx, expr) {
+        Some(ExprFnSig::Sig(cx.tcx.fn_sig(id)))
+    } else {
+        let ty = cx.typeck_results().expr_ty_adjusted(expr).peel_refs();
+        match *ty.kind() {
+            ty::Closure(_, subs) => Some(ExprFnSig::Closure(subs.as_closure().sig())),
+            ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).subst(cx.tcx, subs))),
+            ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig)),
+            ty::Dynamic(bounds, _) => {
+                let lang_items = cx.tcx.lang_items();
+                match bounds.principal() {
+                    Some(bound)
+                        if Some(bound.def_id()) == lang_items.fn_trait()
+                            || Some(bound.def_id()) == lang_items.fn_once_trait()
+                            || Some(bound.def_id()) == lang_items.fn_mut_trait() =>
+                    {
+                        let output = bounds
+                            .projection_bounds()
+                            .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id()))
+                            .map(|p| p.map_bound(|p| p.term.ty().expect("return type was a const")));
+                        Some(ExprFnSig::Trait(bound.map_bound(|b| b.substs.type_at(0)), output))
+                    },
+                    _ => None,
+                }
+            },
+            ty::Param(_) | ty::Projection(..) => {
+                let mut inputs = None;
+                let mut output = None;
+                let lang_items = cx.tcx.lang_items();
+
+                for (pred, _) in all_predicates_of(cx.tcx, cx.typeck_results().hir_owner.to_def_id()) {
+                    let mut is_input = false;
+                    if let Some(ty) = pred
+                        .kind()
+                        .map_bound(|pred| match pred {
+                            PredicateKind::Trait(p)
+                                if (lang_items.fn_trait() == Some(p.def_id())
+                                    || lang_items.fn_mut_trait() == Some(p.def_id())
+                                    || lang_items.fn_once_trait() == Some(p.def_id()))
+                                    && p.self_ty() == ty =>
+                            {
+                                is_input = true;
+                                Some(p.trait_ref.substs.type_at(1))
+                            },
+                            PredicateKind::Projection(p)
+                                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
+                                    && p.projection_ty.self_ty() == ty =>
+                            {
+                                is_input = false;
+                                p.term.ty()
+                            },
+                            _ => None,
+                        })
+                        .transpose()
+                    {
+                        if is_input && inputs.is_none() {
+                            inputs = Some(ty);
+                        } else if !is_input && output.is_none() {
+                            output = Some(ty);
+                        } else {
+                            // Multiple different fn trait impls. Is this even allowed?
+                            return None;
+                        }
+                    }
+                }
+
+                inputs.map(|ty| ExprFnSig::Trait(ty, output))
+            },
+            _ => None,
+        }
+    }
+}
diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs
index 2066915e1d1..405e306359b 100644
--- a/clippy_utils/src/usage.rs
+++ b/clippy_utils/src/usage.rs
@@ -6,7 +6,7 @@ use rustc_hir::HirIdSet;
 use rustc_hir::{Expr, ExprKind, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty;
 use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@@ -96,18 +96,12 @@ impl<'tcx> ParamBindingIdCollector {
     }
 }
 impl<'tcx> intravisit::Visitor<'tcx> for ParamBindingIdCollector {
-    type Map = Map<'tcx>;
-
     fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
         if let hir::PatKind::Binding(_, hir_id, ..) = pat.kind {
             self.binding_hir_ids.push(hir_id);
         }
         intravisit::walk_pat(self, pat);
     }
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
 }
 
 pub struct BindingUsageFinder<'a, 'tcx> {
@@ -127,7 +121,7 @@ impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> {
     }
 }
 impl<'a, 'tcx> intravisit::Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         if !self.usage_found {
@@ -143,8 +137,8 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs
index b60cd4736f3..40451b17a9c 100644
--- a/clippy_utils/src/visitors.rs
+++ b/clippy_utils/src/visitors.rs
@@ -1,12 +1,13 @@
 use crate::path_to_local_id;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{self, walk_block, walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
 use rustc_hir::{
     Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Stmt, UnOp, Unsafety,
 };
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty;
 
 /// Convenience method for creating a `Visitor` with just `visit_expr` overridden and nested
@@ -19,9 +20,9 @@ pub fn expr_visitor<'tcx>(cx: &LateContext<'tcx>, f: impl FnMut(&'tcx Expr<'tcx>
         f: F,
     }
     impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> bool> Visitor<'tcx> for V<'tcx, F> {
-        type Map = Map<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::OnlyBodies(self.hir)
+        type NestedFilter = nested_filter::OnlyBodies;
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.hir
         }
 
         fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
@@ -40,11 +41,6 @@ pub fn expr_visitor<'tcx>(cx: &LateContext<'tcx>, f: impl FnMut(&'tcx Expr<'tcx>
 pub fn expr_visitor_no_bodies<'tcx>(f: impl FnMut(&'tcx Expr<'tcx>) -> bool) -> impl Visitor<'tcx> {
     struct V<F>(F);
     impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> bool> Visitor<'tcx> for V<F> {
-        type Map = intravisit::ErasedMap<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::None
-        }
-
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if (self.0)(e) {
                 walk_expr(self, e);
@@ -113,12 +109,6 @@ where
     }
 
     impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder<F> {
-        type Map = Map<'hir>;
-
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-            intravisit::NestedVisitorMap::None
-        }
-
         fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) {
             intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt);
         }
@@ -237,9 +227,9 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) ->
         is_const: bool,
     }
     impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
-        type Map = Map<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+        type NestedFilter = nested_filter::OnlyBodies;
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.cx.tcx.hir()
         }
 
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
@@ -327,9 +317,9 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
         is_unsafe: bool,
     }
     impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
-        type Map = Map<'tcx>;
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-            NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+        type NestedFilter = nested_filter::OnlyBodies;
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.cx.tcx.hir()
         }
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if self.is_unsafe {
diff --git a/doc/common_tools_writing_lints.md b/doc/common_tools_writing_lints.md
index 207b0be1548..6c8a3dc418b 100644
--- a/doc/common_tools_writing_lints.md
+++ b/doc/common_tools_writing_lints.md
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for MyStructLint {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if_chain! {
             // Check our expr is calling a method
-            if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..], _) = &expr.kind;
+            if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind;
             // Check the name of this method is `some_method`
             if path.ident.name == sym!(some_method);
             // Optionally, check the type of the self argument.
diff --git a/lintcheck/Cargo.toml b/lintcheck/Cargo.toml
index f33f1b65eab..c694037021a 100644
--- a/lintcheck/Cargo.toml
+++ b/lintcheck/Cargo.toml
@@ -13,7 +13,7 @@ publish = false
 clap = "2.33"
 flate2 = "1.0"
 fs_extra = "1.2"
-rayon = "1.5"
+rayon = "1.5.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 tar = "0.4"
diff --git a/rust-toolchain b/rust-toolchain
index e6a58e92072..e23dc73ab08 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-01-13"
+channel = "nightly-2022-01-27"
 components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/tests/ui/author/struct.stdout b/tests/ui/author/struct.stdout
index ded5abd8d33..5e78b7c9de7 100644
--- a/tests/ui/author/struct.stdout
+++ b/tests/ui/author/struct.stdout
@@ -53,7 +53,7 @@ if_chain! {
     }
 }
 if_chain! {
-    if let ExprKind::MethodCall(method_name, _, args, _) = expr.kind;
+    if let ExprKind::MethodCall(method_name, args, _) = expr.kind;
     if method_name.ident.as_str() == "test";
     if args.len() == 1;
     if let ExprKind::Path(ref qpath) = args[0].kind;
diff --git a/tests/ui/borrow_interior_mutable_const/others.rs b/tests/ui/borrow_interior_mutable_const/others.rs
index 4327f12c37c..eefeb1decb6 100644
--- a/tests/ui/borrow_interior_mutable_const/others.rs
+++ b/tests/ui/borrow_interior_mutable_const/others.rs
@@ -1,9 +1,5 @@
 #![warn(clippy::borrow_interior_mutable_const)]
-#![allow(
-    clippy::declare_interior_mutable_const,
-    clippy::ref_in_deref,
-    clippy::needless_borrow
-)]
+#![allow(clippy::declare_interior_mutable_const, clippy::needless_borrow)]
 #![allow(const_item_mutation)]
 
 use std::borrow::Cow;
diff --git a/tests/ui/borrow_interior_mutable_const/others.stderr b/tests/ui/borrow_interior_mutable_const/others.stderr
index f146b97cf61..9a908cf30e9 100644
--- a/tests/ui/borrow_interior_mutable_const/others.stderr
+++ b/tests/ui/borrow_interior_mutable_const/others.stderr
@@ -1,5 +1,5 @@
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:58:5
+  --> $DIR/others.rs:54:5
    |
 LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
    |     ^^^^^^
@@ -8,7 +8,7 @@ LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:59:16
+  --> $DIR/others.rs:55:16
    |
 LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
    |                ^^^^^^
@@ -16,7 +16,7 @@ LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:62:22
+  --> $DIR/others.rs:58:22
    |
 LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
    |                      ^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:63:25
+  --> $DIR/others.rs:59:25
    |
 LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
    |                         ^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:64:27
+  --> $DIR/others.rs:60:27
    |
 LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
    |                           ^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:65:26
+  --> $DIR/others.rs:61:26
    |
 LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
    |                          ^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:76:14
+  --> $DIR/others.rs:72:14
    |
 LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
    |              ^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:77:14
+  --> $DIR/others.rs:73:14
    |
 LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
    |              ^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:78:19
+  --> $DIR/others.rs:74:19
    |
 LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
    |                   ^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:79:14
+  --> $DIR/others.rs:75:14
    |
 LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    |              ^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:80:13
+  --> $DIR/others.rs:76:13
    |
 LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
    |             ^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:86:13
+  --> $DIR/others.rs:82:13
    |
 LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    |             ^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:91:5
+  --> $DIR/others.rs:87:5
    |
 LL |     CELL.set(2); //~ ERROR interior mutability
    |     ^^^^
@@ -104,7 +104,7 @@ LL |     CELL.set(2); //~ ERROR interior mutability
    = help: assign this const to a local or static variable, and use the variable here
 
 error: a `const` item with interior mutability should not be borrowed
-  --> $DIR/others.rs:92:16
+  --> $DIR/others.rs:88:16
    |
 LL |     assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
    |                ^^^^
diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs
index c724ee21be3..d3ad26921bf 100644
--- a/tests/ui/bytecount.rs
+++ b/tests/ui/bytecount.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::needless_borrow)]
+
 #[deny(clippy::naive_bytecount)]
 fn main() {
     let x = vec![0_u8; 16];
diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr
index 1dc37fc8b25..68d838c1f82 100644
--- a/tests/ui/bytecount.stderr
+++ b/tests/ui/bytecount.stderr
@@ -1,23 +1,23 @@
 error: you appear to be counting bytes the naive way
-  --> $DIR/bytecount.rs:5:13
+  --> $DIR/bytecount.rs:7:13
    |
 LL |     let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count(x, 0)`
    |
 note: the lint level is defined here
-  --> $DIR/bytecount.rs:1:8
+  --> $DIR/bytecount.rs:3:8
    |
 LL | #[deny(clippy::naive_bytecount)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: you appear to be counting bytes the naive way
-  --> $DIR/bytecount.rs:7:13
+  --> $DIR/bytecount.rs:9:13
    |
 LL |     let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count((&x[..]), 0)`
 
 error: you appear to be counting bytes the naive way
-  --> $DIR/bytecount.rs:19:13
+  --> $DIR/bytecount.rs:21:13
    |
 LL |     let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count(x, b + 1)`
diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed
index 8d43f64768d..dc062762604 100644
--- a/tests/ui/clone_on_copy.fixed
+++ b/tests/ui/clone_on_copy.fixed
@@ -7,7 +7,8 @@
     clippy::no_effect,
     clippy::unnecessary_operation,
     clippy::vec_init_then_push,
-    clippy::toplevel_ref_arg
+    clippy::toplevel_ref_arg,
+    clippy::needless_borrow
 )]
 
 use std::cell::RefCell;
diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs
index f15501f7184..8c39d0d55dd 100644
--- a/tests/ui/clone_on_copy.rs
+++ b/tests/ui/clone_on_copy.rs
@@ -7,7 +7,8 @@
     clippy::no_effect,
     clippy::unnecessary_operation,
     clippy::vec_init_then_push,
-    clippy::toplevel_ref_arg
+    clippy::toplevel_ref_arg,
+    clippy::needless_borrow
 )]
 
 use std::cell::RefCell;
diff --git a/tests/ui/clone_on_copy.stderr b/tests/ui/clone_on_copy.stderr
index e7d28b4320b..861543d0aa9 100644
--- a/tests/ui/clone_on_copy.stderr
+++ b/tests/ui/clone_on_copy.stderr
@@ -1,5 +1,5 @@
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:24:5
+  --> $DIR/clone_on_copy.rs:25:5
    |
 LL |     42.clone();
    |     ^^^^^^^^^^ help: try removing the `clone` call: `42`
@@ -7,43 +7,43 @@ LL |     42.clone();
    = note: `-D clippy::clone-on-copy` implied by `-D warnings`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:28:5
+  --> $DIR/clone_on_copy.rs:29:5
    |
 LL |     (&42).clone();
    |     ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:31:5
+  --> $DIR/clone_on_copy.rs:32:5
    |
 LL |     rc.borrow().clone();
    |     ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
 
 error: using `clone` on type `u32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:34:5
+  --> $DIR/clone_on_copy.rs:35:5
    |
 LL |     x.clone().rotate_left(1);
    |     ^^^^^^^^^ help: try removing the `clone` call: `x`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:48:5
+  --> $DIR/clone_on_copy.rs:49:5
    |
 LL |     m!(42).clone();
    |     ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)`
 
 error: using `clone` on type `[u32; 2]` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:58:5
+  --> $DIR/clone_on_copy.rs:59:5
    |
 LL |     x.clone()[0];
    |     ^^^^^^^^^ help: try dereferencing it: `(*x)`
 
 error: using `clone` on type `char` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:68:14
+  --> $DIR/clone_on_copy.rs:69:14
    |
 LL |     is_ascii('z'.clone());
    |              ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
 
 error: using `clone` on type `i32` which implements the `Copy` trait
-  --> $DIR/clone_on_copy.rs:72:14
+  --> $DIR/clone_on_copy.rs:73:14
    |
 LL |     vec.push(42.clone());
    |              ^^^^^^^^^^ help: try removing the `clone` call: `42`
diff --git a/tests/ui/crashes/ice-8250.rs b/tests/ui/crashes/ice-8250.rs
new file mode 100644
index 00000000000..d9a5ee1162a
--- /dev/null
+++ b/tests/ui/crashes/ice-8250.rs
@@ -0,0 +1,6 @@
+fn _f(s: &str) -> Option<()> {
+    let _ = s[1..].splitn(2, '.').next()?;
+    Some(())
+}
+
+fn main() {}
diff --git a/tests/ui/crashes/ice-8250.stderr b/tests/ui/crashes/ice-8250.stderr
new file mode 100644
index 00000000000..04ea4456656
--- /dev/null
+++ b/tests/ui/crashes/ice-8250.stderr
@@ -0,0 +1,18 @@
+error: manual implementation of `split_once`
+  --> $DIR/ice-8250.rs:2:13
+   |
+LL |     let _ = s[1..].splitn(2, '.').next()?;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s[1..].split_once('.').map_or(s[1..], |x| x.0)`
+   |
+   = note: `-D clippy::manual-split-once` implied by `-D warnings`
+
+error: unnecessary use of `splitn`
+  --> $DIR/ice-8250.rs:2:13
+   |
+LL |     let _ = s[1..].splitn(2, '.').next()?;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s[1..].split('.')`
+   |
+   = note: `-D clippy::needless-splitn` implied by `-D warnings`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/default_union_representation.rs b/tests/ui/default_union_representation.rs
new file mode 100644
index 00000000000..93b2d33da2c
--- /dev/null
+++ b/tests/ui/default_union_representation.rs
@@ -0,0 +1,78 @@
+#![feature(transparent_unions)]
+#![warn(clippy::default_union_representation)]
+
+union NoAttribute {
+    a: i32,
+    b: u32,
+}
+
+#[repr(C)]
+union ReprC {
+    a: i32,
+    b: u32,
+}
+
+#[repr(packed)]
+union ReprPacked {
+    a: i32,
+    b: u32,
+}
+
+#[repr(C, packed)]
+union ReprCPacked {
+    a: i32,
+    b: u32,
+}
+
+#[repr(C, align(32))]
+union ReprCAlign {
+    a: i32,
+    b: u32,
+}
+
+#[repr(align(32))]
+union ReprAlign {
+    a: i32,
+    b: u32,
+}
+
+union SingleZST {
+    f0: (),
+}
+union ZSTsAndField1 {
+    f0: u32,
+    f1: (),
+    f2: (),
+    f3: (),
+}
+union ZSTsAndField2 {
+    f0: (),
+    f1: (),
+    f2: u32,
+    f3: (),
+}
+union ZSTAndTwoFields {
+    f0: u32,
+    f1: u64,
+    f2: (),
+}
+
+#[repr(C)]
+union CZSTAndTwoFields {
+    f0: u32,
+    f1: u64,
+    f2: (),
+}
+
+#[repr(transparent)]
+union ReprTransparent {
+    a: i32,
+}
+
+#[repr(transparent)]
+union ReprTransparentZST {
+    a: i32,
+    b: (),
+}
+
+fn main() {}
diff --git a/tests/ui/default_union_representation.stderr b/tests/ui/default_union_representation.stderr
new file mode 100644
index 00000000000..138884af868
--- /dev/null
+++ b/tests/ui/default_union_representation.stderr
@@ -0,0 +1,48 @@
+error: this union has the default representation
+  --> $DIR/default_union_representation.rs:4:1
+   |
+LL | / union NoAttribute {
+LL | |     a: i32,
+LL | |     b: u32,
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::default-union-representation` implied by `-D warnings`
+   = help: consider annotating `NoAttribute` with `#[repr(C)]` to explicitly specify memory layout
+
+error: this union has the default representation
+  --> $DIR/default_union_representation.rs:16:1
+   |
+LL | / union ReprPacked {
+LL | |     a: i32,
+LL | |     b: u32,
+LL | | }
+   | |_^
+   |
+   = help: consider annotating `ReprPacked` with `#[repr(C)]` to explicitly specify memory layout
+
+error: this union has the default representation
+  --> $DIR/default_union_representation.rs:34:1
+   |
+LL | / union ReprAlign {
+LL | |     a: i32,
+LL | |     b: u32,
+LL | | }
+   | |_^
+   |
+   = help: consider annotating `ReprAlign` with `#[repr(C)]` to explicitly specify memory layout
+
+error: this union has the default representation
+  --> $DIR/default_union_representation.rs:54:1
+   |
+LL | / union ZSTAndTwoFields {
+LL | |     f0: u32,
+LL | |     f1: u64,
+LL | |     f2: (),
+LL | | }
+   | |_^
+   |
+   = help: consider annotating `ZSTAndTwoFields` with `#[repr(C)]` to explicitly specify memory layout
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/duration_subsec.fixed b/tests/ui/duration_subsec.fixed
index ee5c7863eff..d92b8998e88 100644
--- a/tests/ui/duration_subsec.fixed
+++ b/tests/ui/duration_subsec.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(dead_code)]
+#![allow(dead_code, clippy::needless_borrow)]
 #![warn(clippy::duration_subsec)]
 
 use std::time::Duration;
diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs
index 3c9d2a28621..08da804996d 100644
--- a/tests/ui/duration_subsec.rs
+++ b/tests/ui/duration_subsec.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(dead_code)]
+#![allow(dead_code, clippy::needless_borrow)]
 #![warn(clippy::duration_subsec)]
 
 use std::time::Duration;
diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed
index f938f710688..618f80cdcf8 100644
--- a/tests/ui/eta.fixed
+++ b/tests/ui/eta.fixed
@@ -5,13 +5,10 @@
     clippy::no_effect,
     clippy::redundant_closure_call,
     clippy::needless_pass_by_value,
-    clippy::option_map_unit_fn
-)]
-#![warn(
-    clippy::redundant_closure,
-    clippy::redundant_closure_for_method_calls,
+    clippy::option_map_unit_fn,
     clippy::needless_borrow
 )]
+#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
 
 use std::path::{Path, PathBuf};
 
@@ -34,7 +31,7 @@ fn main() {
     Some(1).map(closure_mac!()); // don't lint closure in macro expansion
     let _: Option<Vec<u8>> = true.then(std::vec::Vec::new); // special case vec!
     let d = Some(1u8).map(|a| foo(foo2(a))); //is adjusted?
-    all(&[1, 2, 3], &2, below); //is adjusted
+    all(&[1, 2, 3], &&2, below); //is adjusted
     unsafe {
         Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn
     }
diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs
index 075bbc74922..a759e6eb514 100644
--- a/tests/ui/eta.rs
+++ b/tests/ui/eta.rs
@@ -5,13 +5,10 @@
     clippy::no_effect,
     clippy::redundant_closure_call,
     clippy::needless_pass_by_value,
-    clippy::option_map_unit_fn
-)]
-#![warn(
-    clippy::redundant_closure,
-    clippy::redundant_closure_for_method_calls,
+    clippy::option_map_unit_fn,
     clippy::needless_borrow
 )]
+#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
 
 use std::path::{Path, PathBuf};
 
diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr
index 8092f04c3fc..cda84982c9b 100644
--- a/tests/ui/eta.stderr
+++ b/tests/ui/eta.stderr
@@ -1,5 +1,5 @@
 error: redundant closure
-  --> $DIR/eta.rs:31:27
+  --> $DIR/eta.rs:28:27
    |
 LL |     let a = Some(1u8).map(|a| foo(a));
    |                           ^^^^^^^^^^ help: replace the closure with the function itself: `foo`
@@ -7,45 +7,37 @@ LL |     let a = Some(1u8).map(|a| foo(a));
    = note: `-D clippy::redundant-closure` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:35:40
+  --> $DIR/eta.rs:32:40
    |
 LL |     let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec!
    |                                        ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new`
 
 error: redundant closure
-  --> $DIR/eta.rs:36:35
+  --> $DIR/eta.rs:33:35
    |
 LL |     let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted?
    |                                   ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2`
 
-error: this expression borrows a reference (`&u8`) that is immediately dereferenced by the compiler
-  --> $DIR/eta.rs:37:21
-   |
-LL |     all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
-   |                     ^^^ help: change this to: `&2`
-   |
-   = note: `-D clippy::needless-borrow` implied by `-D warnings`
-
 error: redundant closure
-  --> $DIR/eta.rs:37:26
+  --> $DIR/eta.rs:34:26
    |
 LL |     all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
    |                          ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below`
 
 error: redundant closure
-  --> $DIR/eta.rs:43:27
+  --> $DIR/eta.rs:40:27
    |
 LL |     let e = Some(1u8).map(|a| divergent(a));
    |                           ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `divergent`
 
 error: redundant closure
-  --> $DIR/eta.rs:44:27
+  --> $DIR/eta.rs:41:27
    |
 LL |     let e = Some(1u8).map(|a| generic(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
 
 error: redundant closure
-  --> $DIR/eta.rs:90:51
+  --> $DIR/eta.rs:87:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    |                                                   ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@@ -53,82 +45,82 @@ LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:91:51
+  --> $DIR/eta.rs:88:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
    |                                                   ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo`
 
 error: redundant closure
-  --> $DIR/eta.rs:93:42
+  --> $DIR/eta.rs:90:42
    |
 LL |     let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
    |                                          ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear`
 
 error: redundant closure
-  --> $DIR/eta.rs:97:29
+  --> $DIR/eta.rs:94:29
    |
 LL |     let e = Some("str").map(|s| s.to_string());
    |                             ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string`
 
 error: redundant closure
-  --> $DIR/eta.rs:98:27
+  --> $DIR/eta.rs:95:27
    |
 LL |     let e = Some('a').map(|s| s.to_uppercase());
    |                           ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase`
 
 error: redundant closure
-  --> $DIR/eta.rs:100:65
+  --> $DIR/eta.rs:97:65
    |
 LL |     let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect();
    |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
 
 error: redundant closure
-  --> $DIR/eta.rs:163:22
+  --> $DIR/eta.rs:160:22
    |
 LL |     requires_fn_once(|| x());
    |                      ^^^^^^ help: replace the closure with the function itself: `x`
 
 error: redundant closure
-  --> $DIR/eta.rs:170:27
+  --> $DIR/eta.rs:167:27
    |
 LL |     let a = Some(1u8).map(|a| foo_ptr(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
 
 error: redundant closure
-  --> $DIR/eta.rs:175:27
+  --> $DIR/eta.rs:172:27
    |
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
 
 error: redundant closure
-  --> $DIR/eta.rs:207:28
+  --> $DIR/eta.rs:204:28
    |
 LL |     x.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> $DIR/eta.rs:208:28
+  --> $DIR/eta.rs:205:28
    |
 LL |     y.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> $DIR/eta.rs:209:28
+  --> $DIR/eta.rs:206:28
    |
 LL |     z.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
 
 error: redundant closure
-  --> $DIR/eta.rs:216:21
+  --> $DIR/eta.rs:213:21
    |
 LL |         Some(1).map(|n| closure(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
 
 error: redundant closure
-  --> $DIR/eta.rs:235:21
+  --> $DIR/eta.rs:232:21
    |
 LL |     map_str_to_path(|s| s.as_ref());
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::convert::AsRef::as_ref`
 
-error: aborting due to 21 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed
index 48e2aae75d0..3de2a51ffa5 100644
--- a/tests/ui/explicit_deref_methods.fixed
+++ b/tests/ui/explicit_deref_methods.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_variables, clippy::clone_double_ref)]
+#![allow(unused_variables, clippy::clone_double_ref, clippy::needless_borrow)]
 #![warn(clippy::explicit_deref_methods)]
 
 use std::ops::{Deref, DerefMut};
diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs
index d8c8c0c5ca3..a08d7596422 100644
--- a/tests/ui/explicit_deref_methods.rs
+++ b/tests/ui/explicit_deref_methods.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_variables, clippy::clone_double_ref)]
+#![allow(unused_variables, clippy::clone_double_ref, clippy::needless_borrow)]
 #![warn(clippy::explicit_deref_methods)]
 
 use std::ops::{Deref, DerefMut};
diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed
index f373e905d05..aa69781d15a 100644
--- a/tests/ui/for_loop_fixable.fixed
+++ b/tests/ui/for_loop_fixable.fixed
@@ -23,7 +23,12 @@ impl Unrelated {
     clippy::iter_next_loop,
     clippy::for_kv_map
 )]
-#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
+#[allow(
+    clippy::linkedlist,
+    clippy::unnecessary_mut_passed,
+    clippy::similar_names,
+    clippy::needless_borrow
+)]
 #[allow(unused_variables)]
 fn main() {
     let mut vec = vec![1, 2, 3, 4];
diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs
index 3814583bb6e..7c063d99511 100644
--- a/tests/ui/for_loop_fixable.rs
+++ b/tests/ui/for_loop_fixable.rs
@@ -23,7 +23,12 @@ impl Unrelated {
     clippy::iter_next_loop,
     clippy::for_kv_map
 )]
-#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
+#[allow(
+    clippy::linkedlist,
+    clippy::unnecessary_mut_passed,
+    clippy::similar_names,
+    clippy::needless_borrow
+)]
 #[allow(unused_variables)]
 fn main() {
     let mut vec = vec![1, 2, 3, 4];
diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr
index 009dbe1a0bf..ddfe66d675f 100644
--- a/tests/ui/for_loop_fixable.stderr
+++ b/tests/ui/for_loop_fixable.stderr
@@ -1,5 +1,5 @@
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:38:15
+  --> $DIR/for_loop_fixable.rs:43:15
    |
 LL |     for _v in vec.iter() {}
    |               ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
@@ -7,13 +7,13 @@ LL |     for _v in vec.iter() {}
    = note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:40:15
+  --> $DIR/for_loop_fixable.rs:45:15
    |
 LL |     for _v in vec.iter_mut() {}
    |               ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
 
 error: it is more concise to loop over containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:43:15
+  --> $DIR/for_loop_fixable.rs:48:15
    |
 LL |     for _v in out_vec.into_iter() {}
    |               ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec`
@@ -21,73 +21,73 @@ LL |     for _v in out_vec.into_iter() {}
    = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:48:15
+  --> $DIR/for_loop_fixable.rs:53:15
    |
 LL |     for _v in [1, 2, 3].iter() {}
    |               ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:52:15
+  --> $DIR/for_loop_fixable.rs:57:15
    |
 LL |     for _v in [0; 32].iter() {}
    |               ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:57:15
+  --> $DIR/for_loop_fixable.rs:62:15
    |
 LL |     for _v in ll.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&ll`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:60:15
+  --> $DIR/for_loop_fixable.rs:65:15
    |
 LL |     for _v in vd.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&vd`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:63:15
+  --> $DIR/for_loop_fixable.rs:68:15
    |
 LL |     for _v in bh.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&bh`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:66:15
+  --> $DIR/for_loop_fixable.rs:71:15
    |
 LL |     for _v in hm.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&hm`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:69:15
+  --> $DIR/for_loop_fixable.rs:74:15
    |
 LL |     for _v in bt.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&bt`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:72:15
+  --> $DIR/for_loop_fixable.rs:77:15
    |
 LL |     for _v in hs.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&hs`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:75:15
+  --> $DIR/for_loop_fixable.rs:80:15
    |
 LL |     for _v in bs.iter() {}
    |               ^^^^^^^^^ help: to write this more concisely, try: `&bs`
 
 error: it is more concise to loop over containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:250:18
+  --> $DIR/for_loop_fixable.rs:255:18
    |
 LL |         for i in iterator.into_iter() {
    |                  ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator`
 
 error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:270:18
+  --> $DIR/for_loop_fixable.rs:275:18
    |
 LL |         for _ in t.into_iter() {}
    |                  ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t`
 
 error: it is more concise to loop over containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:272:18
+  --> $DIR/for_loop_fixable.rs:277:18
    |
 LL |         for _ in r.into_iter() {}
    |                  ^^^^^^^^^^^^^ help: to write this more concisely, try: `r`
diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed
index 78d2bfd474e..d08f8f52495 100644
--- a/tests/ui/format.fixed
+++ b/tests/ui/format.fixed
@@ -1,6 +1,11 @@
 // run-rustfix
 
-#![allow(clippy::print_literal, clippy::redundant_clone, clippy::to_string_in_format_args)]
+#![allow(
+    clippy::print_literal,
+    clippy::redundant_clone,
+    clippy::to_string_in_format_args,
+    clippy::needless_borrow
+)]
 #![warn(clippy::useless_format)]
 
 struct Foo(pub String);
diff --git a/tests/ui/format.rs b/tests/ui/format.rs
index 009c1aa216f..4a10b580d26 100644
--- a/tests/ui/format.rs
+++ b/tests/ui/format.rs
@@ -1,6 +1,11 @@
 // run-rustfix
 
-#![allow(clippy::print_literal, clippy::redundant_clone, clippy::to_string_in_format_args)]
+#![allow(
+    clippy::print_literal,
+    clippy::redundant_clone,
+    clippy::to_string_in_format_args,
+    clippy::needless_borrow
+)]
 #![warn(clippy::useless_format)]
 
 struct Foo(pub String);
diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr
index 660be57585e..f25c7fb1ff1 100644
--- a/tests/ui/format.stderr
+++ b/tests/ui/format.stderr
@@ -1,5 +1,5 @@
 error: useless use of `format!`
-  --> $DIR/format.rs:13:5
+  --> $DIR/format.rs:18:5
    |
 LL |     format!("foo");
    |     ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
@@ -7,19 +7,19 @@ LL |     format!("foo");
    = note: `-D clippy::useless-format` implied by `-D warnings`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:14:5
+  --> $DIR/format.rs:19:5
    |
 LL |     format!("{{}}");
    |     ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:15:5
+  --> $DIR/format.rs:20:5
    |
 LL |     format!("{{}} abc {{}}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:16:5
+  --> $DIR/format.rs:21:5
    |
 LL | /     format!(
 LL | |         r##"foo {{}}
@@ -34,79 +34,79 @@ LL ~ " bar"##.to_string();
    |
 
 error: useless use of `format!`
-  --> $DIR/format.rs:21:13
+  --> $DIR/format.rs:26:13
    |
 LL |     let _ = format!("");
    |             ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:23:5
+  --> $DIR/format.rs:28:5
    |
 LL |     format!("{}", "foo");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:27:5
+  --> $DIR/format.rs:32:5
    |
 LL |     format!("{:+}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:28:5
+  --> $DIR/format.rs:33:5
    |
 LL |     format!("{:<}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:33:5
+  --> $DIR/format.rs:38:5
    |
 LL |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:37:5
+  --> $DIR/format.rs:42:5
    |
 LL |     format!("{:+}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:38:5
+  --> $DIR/format.rs:43:5
    |
 LL |     format!("{:<}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:65:5
+  --> $DIR/format.rs:70:5
    |
 LL |     format!("{}", 42.to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:67:5
+  --> $DIR/format.rs:72:5
    |
 LL |     format!("{}", x.display().to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:71:18
+  --> $DIR/format.rs:76:18
    |
 LL |     let _ = Some(format!("{}", a + "bar"));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:75:22
+  --> $DIR/format.rs:80:22
    |
 LL |     let _s: String = format!("{}", &*v.join("/n"));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:81:13
+  --> $DIR/format.rs:86:13
    |
 LL |     let _ = format!("{x}");
    |             ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:83:13
+  --> $DIR/format.rs:88:13
    |
 LL |     let _ = format!("{y}", y = x);
    |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index 9e37fb92559..b856f1375d3 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -45,6 +45,33 @@ fn main() {
         let b = &mut b;
         x(b);
     }
+
+    // Issue #8191
+    let mut x = 5;
+    let mut x = &mut x;
+
+    mut_ref(x);
+    mut_ref(x);
+    let y: &mut i32 = x;
+    let y: &mut i32 = x;
+
+    let y = match 0 {
+        // Don't lint. Removing the borrow would move 'x'
+        0 => &mut x,
+        _ => &mut *x,
+    };
+
+    *x = 5;
+
+    let s = String::new();
+    let _ = s.len();
+    let _ = s.capacity();
+    let _ = s.capacity();
+
+    let x = (1, 2);
+    let _ = x.0;
+    let x = &x as *const (i32, i32);
+    let _ = unsafe { (*x).0 };
 }
 
 #[allow(clippy::needless_borrowed_reference)]
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index 093277784be..0bfe222a3dc 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -45,6 +45,33 @@ fn main() {
         let b = &mut b;
         x(&b);
     }
+
+    // Issue #8191
+    let mut x = 5;
+    let mut x = &mut x;
+
+    mut_ref(&mut x);
+    mut_ref(&mut &mut x);
+    let y: &mut i32 = &mut x;
+    let y: &mut i32 = &mut &mut x;
+
+    let y = match 0 {
+        // Don't lint. Removing the borrow would move 'x'
+        0 => &mut x,
+        _ => &mut *x,
+    };
+
+    *x = 5;
+
+    let s = String::new();
+    let _ = (&s).len();
+    let _ = (&s).capacity();
+    let _ = (&&s).capacity();
+
+    let x = (1, 2);
+    let _ = (&x).0;
+    let x = &x as *const (i32, i32);
+    let _ = unsafe { (&*x).0 };
 }
 
 #[allow(clippy::needless_borrowed_reference)]
diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr
index 03a5b3d260e..b90e8448db0 100644
--- a/tests/ui/needless_borrow.stderr
+++ b/tests/ui/needless_borrow.stderr
@@ -1,4 +1,4 @@
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:9:15
    |
 LL |     let _ = x(&&a); // warn
@@ -6,59 +6,113 @@ LL |     let _ = x(&&a); // warn
    |
    = note: `-D clippy::needless-borrow` implied by `-D warnings`
 
-error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:13:13
    |
 LL |     mut_ref(&mut &mut b); // warn
    |             ^^^^^^^^^^^ help: change this to: `&mut b`
 
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:25:13
    |
 LL |             &&a
    |             ^^^ help: change this to: `&a`
 
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:27:15
    |
 LL |         46 => &&a,
    |               ^^^ help: change this to: `&a`
 
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:33:27
    |
 LL |                     break &ref_a;
    |                           ^^^^^^ help: change this to: `ref_a`
 
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:40:15
    |
 LL |     let _ = x(&&&a);
    |               ^^^^ help: change this to: `&a`
 
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:41:15
    |
 LL |     let _ = x(&mut &&a);
    |               ^^^^^^^^ help: change this to: `&a`
 
-error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:42:15
    |
 LL |     let _ = x(&&&mut b);
    |               ^^^^^^^^ help: change this to: `&mut b`
 
-error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:43:15
    |
 LL |     let _ = x(&&ref_a);
    |               ^^^^^^^ help: change this to: `ref_a`
 
-error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler
+error: this expression creates a reference which is immediately dereferenced by the compiler
   --> $DIR/needless_borrow.rs:46:11
    |
 LL |         x(&b);
    |           ^^ help: change this to: `b`
 
-error: aborting due to 10 previous errors
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> $DIR/needless_borrow.rs:53:13
+   |
+LL |     mut_ref(&mut x);
+   |             ^^^^^^ help: change this to: `x`
+
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> $DIR/needless_borrow.rs:54:13
+   |
+LL |     mut_ref(&mut &mut x);
+   |             ^^^^^^^^^^^ help: change this to: `x`
+
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> $DIR/needless_borrow.rs:55:23
+   |
+LL |     let y: &mut i32 = &mut x;
+   |                       ^^^^^^ help: change this to: `x`
+
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> $DIR/needless_borrow.rs:56:23
+   |
+LL |     let y: &mut i32 = &mut &mut x;
+   |                       ^^^^^^^^^^^ help: change this to: `x`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:67:13
+   |
+LL |     let _ = (&s).len();
+   |             ^^^^ help: change this to: `s`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:68:13
+   |
+LL |     let _ = (&s).capacity();
+   |             ^^^^ help: change this to: `s`
+
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> $DIR/needless_borrow.rs:69:13
+   |
+LL |     let _ = (&&s).capacity();
+   |             ^^^^^ help: change this to: `s`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:72:13
+   |
+LL |     let _ = (&x).0;
+   |             ^^^^ help: change this to: `x`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:74:22
+   |
+LL |     let _ = unsafe { (&*x).0 };
+   |                      ^^^^^ help: change this to: `(*x)`
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs
index b07c4a23810..f3eafe8e927 100644
--- a/tests/ui/needless_lifetimes.rs
+++ b/tests/ui/needless_lifetimes.rs
@@ -1,5 +1,11 @@
 #![warn(clippy::needless_lifetimes)]
-#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps, dyn_drop)]
+#![allow(
+    dead_code,
+    clippy::boxed_local,
+    clippy::needless_pass_by_value,
+    clippy::unnecessary_wraps,
+    dyn_drop
+)]
 
 fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
 
@@ -369,4 +375,47 @@ mod issue6159 {
     }
 }
 
+mod issue7296 {
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    struct Foo;
+    impl Foo {
+        fn implicit<'a>(&'a self) -> &'a () {
+            &()
+        }
+        fn implicit_mut<'a>(&'a mut self) -> &'a () {
+            &()
+        }
+
+        fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
+            &()
+        }
+        fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
+            &()
+        }
+
+        fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+            &()
+        }
+    }
+
+    trait Bar {
+        fn implicit<'a>(&'a self) -> &'a ();
+        fn implicit_provided<'a>(&'a self) -> &'a () {
+            &()
+        }
+
+        fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
+        fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
+            &()
+        }
+
+        fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
+        fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+            &()
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr
index 4114e6f1832..ffa152427a9 100644
--- a/tests/ui/needless_lifetimes.stderr
+++ b/tests/ui/needless_lifetimes.stderr
@@ -1,5 +1,5 @@
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:4:1
+  --> $DIR/needless_lifetimes.rs:10:1
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,148 +7,190 @@ LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:6:1
+  --> $DIR/needless_lifetimes.rs:12:1
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:16:1
+  --> $DIR/needless_lifetimes.rs:22:1
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:50:1
+  --> $DIR/needless_lifetimes.rs:56:1
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:55:1
+  --> $DIR/needless_lifetimes.rs:61:1
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:67:1
+  --> $DIR/needless_lifetimes.rs:73:1
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:91:1
+  --> $DIR/needless_lifetimes.rs:97:1
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:121:5
+  --> $DIR/needless_lifetimes.rs:127:5
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:130:5
+  --> $DIR/needless_lifetimes.rs:136:5
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:149:1
+  --> $DIR/needless_lifetimes.rs:155:1
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:179:1
+  --> $DIR/needless_lifetimes.rs:185:1
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:185:1
+  --> $DIR/needless_lifetimes.rs:191:1
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:204:1
+  --> $DIR/needless_lifetimes.rs:210:1
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:212:1
+  --> $DIR/needless_lifetimes.rs:218:1
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:248:1
+  --> $DIR/needless_lifetimes.rs:254:1
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:255:9
+  --> $DIR/needless_lifetimes.rs:261:9
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:259:9
+  --> $DIR/needless_lifetimes.rs:265:9
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:272:9
+  --> $DIR/needless_lifetimes.rs:278:9
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:301:5
+  --> $DIR/needless_lifetimes.rs:307:5
    |
 LL |     fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:304:5
+  --> $DIR/needless_lifetimes.rs:310:5
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:313:5
+  --> $DIR/needless_lifetimes.rs:319:5
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:325:5
+  --> $DIR/needless_lifetimes.rs:331:5
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:340:5
+  --> $DIR/needless_lifetimes.rs:346:5
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:353:5
+  --> $DIR/needless_lifetimes.rs:359:5
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
-  --> $DIR/needless_lifetimes.rs:356:5
+  --> $DIR/needless_lifetimes.rs:362:5
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 25 previous errors
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:384:9
+   |
+LL |         fn implicit<'a>(&'a self) -> &'a () {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:387:9
+   |
+LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:398:9
+   |
+LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:404:9
+   |
+LL |         fn implicit<'a>(&'a self) -> &'a ();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:405:9
+   |
+LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:414:9
+   |
+LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
+  --> $DIR/needless_lifetimes.rs:415:9
+   |
+LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 32 previous errors
 
diff --git a/tests/ui/needless_question_mark.fixed b/tests/ui/needless_question_mark.fixed
index f1fc81aa12b..ba9d15e59d0 100644
--- a/tests/ui/needless_question_mark.fixed
+++ b/tests/ui/needless_question_mark.fixed
@@ -125,3 +125,16 @@ pub fn test2() {
     let x = Some(3);
     let _x = some_and_qmark_in_macro!(x?);
 }
+
+async fn async_option_bad(to: TO) -> Option<usize> {
+    let _ = Some(3);
+    to.magic
+}
+
+async fn async_deref_ref(s: Option<&String>) -> Option<&str> {
+    Some(s?)
+}
+
+async fn async_result_bad(s: TR) -> Result<usize, bool> {
+    s.magic
+}
diff --git a/tests/ui/needless_question_mark.rs b/tests/ui/needless_question_mark.rs
index 44a0c5f61b5..3a6523e8fe8 100644
--- a/tests/ui/needless_question_mark.rs
+++ b/tests/ui/needless_question_mark.rs
@@ -125,3 +125,16 @@ pub fn test2() {
     let x = Some(3);
     let _x = some_and_qmark_in_macro!(x?);
 }
+
+async fn async_option_bad(to: TO) -> Option<usize> {
+    let _ = Some(3);
+    Some(to.magic?)
+}
+
+async fn async_deref_ref(s: Option<&String>) -> Option<&str> {
+    Some(s?)
+}
+
+async fn async_result_bad(s: TR) -> Result<usize, bool> {
+    Ok(s.magic?)
+}
diff --git a/tests/ui/needless_question_mark.stderr b/tests/ui/needless_question_mark.stderr
index 57c3d48c761..f8308e24e77 100644
--- a/tests/ui/needless_question_mark.stderr
+++ b/tests/ui/needless_question_mark.stderr
@@ -77,5 +77,17 @@ LL |     let _x = some_and_qmark_in_macro!(x?);
    |
    = note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 12 previous errors
+error: question mark operator is useless here
+  --> $DIR/needless_question_mark.rs:131:5
+   |
+LL |     Some(to.magic?)
+   |     ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
+
+error: question mark operator is useless here
+  --> $DIR/needless_question_mark.rs:139:5
+   |
+LL |     Ok(s.magic?)
+   |     ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `s.magic`
+
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs
index 67bfef06a05..00b99da2631 100644
--- a/tests/ui/ptr_arg.rs
+++ b/tests/ui/ptr_arg.rs
@@ -9,7 +9,6 @@ fn do_vec(x: &Vec<i64>) {
 }
 
 fn do_vec_mut(x: &mut Vec<i64>) {
-    // no error here
     //Nothing here
 }
 
@@ -18,7 +17,6 @@ fn do_str(x: &String) {
 }
 
 fn do_str_mut(x: &mut String) {
-    // no error here
     //Nothing here either
 }
 
@@ -27,7 +25,6 @@ fn do_path(x: &PathBuf) {
 }
 
 fn do_path_mut(x: &mut PathBuf) {
-    // no error here
     //Nothing here either
 }
 
@@ -52,7 +49,7 @@ fn cloned(x: &Vec<u8>) -> Vec<u8> {
     let e = x.clone();
     let f = e.clone(); // OK
     let g = x;
-    let h = g.clone(); // Alas, we cannot reliably detect this without following data.
+    let h = g.clone();
     let i = (e).clone();
     x.clone()
 }
@@ -156,6 +153,36 @@ mod issue6509 {
     }
 }
 
+fn mut_vec_slice_methods(v: &mut Vec<u32>) {
+    v.copy_within(1..5, 10);
+}
+
+fn mut_vec_vec_methods(v: &mut Vec<u32>) {
+    v.clear();
+}
+
+fn vec_contains(v: &Vec<u32>) -> bool {
+    [vec![], vec![0]].as_slice().contains(v)
+}
+
+fn fn_requires_vec(v: &Vec<u32>) -> bool {
+    vec_contains(v)
+}
+
+fn impl_fn_requires_vec(v: &Vec<u32>, f: impl Fn(&Vec<u32>)) {
+    f(v);
+}
+
+fn dyn_fn_requires_vec(v: &Vec<u32>, f: &dyn Fn(&Vec<u32>)) {
+    f(v);
+}
+
 // No error for types behind an alias (#7699)
 type A = Vec<u8>;
 fn aliased(a: &A) {}
+
+// Issue #8366
+pub trait Trait {
+    fn f(v: &mut Vec<i32>);
+    fn f2(v: &mut Vec<i32>) {}
+}
diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr
index 64594eb870c..a9613daadde 100644
--- a/tests/ui/ptr_arg.stderr
+++ b/tests/ui/ptr_arg.stderr
@@ -1,4 +1,4 @@
-error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
+error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
   --> $DIR/ptr_arg.rs:7:14
    |
 LL | fn do_vec(x: &Vec<i64>) {
@@ -6,170 +6,154 @@ LL | fn do_vec(x: &Vec<i64>) {
    |
    = note: `-D clippy::ptr-arg` implied by `-D warnings`
 
+error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:11:18
+   |
+LL | fn do_vec_mut(x: &mut Vec<i64>) {
+   |                  ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
+
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:16:14
+  --> $DIR/ptr_arg.rs:15:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
+error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:19:18
+   |
+LL | fn do_str_mut(x: &mut String) {
+   |                  ^^^^^^^^^^^ help: change this to: `&mut str`
+
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:25:15
+  --> $DIR/ptr_arg.rs:23:15
    |
 LL | fn do_path(x: &PathBuf) {
    |               ^^^^^^^^ help: change this to: `&Path`
 
-error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:38:18
+error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:27:19
+   |
+LL | fn do_path_mut(x: &mut PathBuf) {
+   |                   ^^^^^^^^^^^^ help: change this to: `&mut Path`
+
+error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:35:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
-error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:51:14
+error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:48:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
    |
 help: change this to
    |
-LL | fn cloned(x: &[u8]) -> Vec<u8> {
-   |              ~~~~~
-help: change `x.clone()` to
-   |
-LL |     let e = x.to_owned();
-   |             ~~~~~~~~~~~~
-help: change `x.clone()` to
-   |
-LL |     x.to_owned()
-   |
+LL ~ fn cloned(x: &[u8]) -> Vec<u8> {
+LL ~     let e = x.to_owned();
+LL |     let f = e.clone(); // OK
+LL |     let g = x;
+LL ~     let h = g.to_owned();
+LL |     let i = (e).clone();
+ ...
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:60:18
+  --> $DIR/ptr_arg.rs:57:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
    |
 help: change this to
    |
-LL | fn str_cloned(x: &str) -> String {
-   |                  ~~~~
-help: change `x.clone()` to
-   |
-LL |     let a = x.to_string();
-   |             ~~~~~~~~~~~~~
-help: change `x.clone()` to
-   |
-LL |     let b = x.to_string();
-   |             ~~~~~~~~~~~~~
-help: change `x.clone()` to
-   |
-LL |     x.to_string()
+LL ~ fn str_cloned(x: &str) -> String {
+LL ~     let a = x.to_owned();
+LL ~     let b = x.to_owned();
+LL |     let c = b.clone();
+LL |     let d = a.clone().clone().clone();
+LL ~     x.to_owned()
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:68:19
+  --> $DIR/ptr_arg.rs:65:19
    |
 LL | fn path_cloned(x: &PathBuf) -> PathBuf {
    |                   ^^^^^^^^
    |
 help: change this to
    |
-LL | fn path_cloned(x: &Path) -> PathBuf {
-   |                   ~~~~~
-help: change `x.clone()` to
-   |
-LL |     let a = x.to_path_buf();
-   |             ~~~~~~~~~~~~~~~
-help: change `x.clone()` to
-   |
-LL |     let b = x.to_path_buf();
-   |             ~~~~~~~~~~~~~~~
-help: change `x.clone()` to
-   |
-LL |     x.to_path_buf()
+LL ~ fn path_cloned(x: &Path) -> PathBuf {
+LL ~     let a = x.to_path_buf();
+LL ~     let b = x.to_path_buf();
+LL |     let c = b.clone();
+LL |     let d = a.clone().clone().clone();
+LL ~     x.to_path_buf()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:76:44
+  --> $DIR/ptr_arg.rs:73:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
    |
 help: change this to
    |
-LL | fn false_positive_capacity(x: &Vec<u8>, y: &str) {
-   |                                            ~~~~
-help: change `y.clone()` to
+LL ~ fn false_positive_capacity(x: &Vec<u8>, y: &str) {
+LL |     let a = x.capacity();
+LL ~     let b = y.to_owned();
+LL ~     let c = y;
    |
-LL |     let b = y.to_string();
-   |             ~~~~~~~~~~~~~
-help: change `y.as_str()` to
-   |
-LL |     let c = y;
-   |             ~
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:90:25
+  --> $DIR/ptr_arg.rs:87:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
-error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
-  --> $DIR/ptr_arg.rs:143:21
+error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:140:21
    |
 LL |     fn foo_vec(vec: &Vec<u8>) {
    |                     ^^^^^^^^
    |
 help: change this to
    |
-LL |     fn foo_vec(vec: &[u8]) {
-   |                     ~~~~~
-help: change `vec.clone()` to
-   |
-LL |         let _ = vec.to_owned().pop();
-   |                 ~~~~~~~~~~~~~~
-help: change `vec.clone()` to
+LL ~     fn foo_vec(vec: &[u8]) {
+LL ~         let _ = vec.to_owned().pop();
+LL ~         let _ = vec.to_owned().clone();
    |
-LL |         let _ = vec.to_owned().clone();
-   |                 ~~~~~~~~~~~~~~
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:148:23
+  --> $DIR/ptr_arg.rs:145:23
    |
 LL |     fn foo_path(path: &PathBuf) {
    |                       ^^^^^^^^
    |
 help: change this to
    |
-LL |     fn foo_path(path: &Path) {
-   |                       ~~~~~
-help: change `path.clone()` to
+LL ~     fn foo_path(path: &Path) {
+LL ~         let _ = path.to_path_buf().pop();
+LL ~         let _ = path.to_path_buf().clone();
    |
-LL |         let _ = path.to_path_buf().pop();
-   |                 ~~~~~~~~~~~~~~~~~~
-help: change `path.clone()` to
-   |
-LL |         let _ = path.to_path_buf().clone();
-   |                 ~~~~~~~~~~~~~~~~~~
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:153:21
+  --> $DIR/ptr_arg.rs:150:21
    |
 LL |     fn foo_str(str: &PathBuf) {
    |                     ^^^^^^^^
    |
 help: change this to
    |
-LL |     fn foo_str(str: &Path) {
-   |                     ~~~~~
-help: change `str.clone()` to
+LL ~     fn foo_str(str: &Path) {
+LL ~         let _ = str.to_path_buf().pop();
+LL ~         let _ = str.to_path_buf().clone();
    |
-LL |         let _ = str.to_path_buf().pop();
-   |                 ~~~~~~~~~~~~~~~~~
-help: change `str.clone()` to
+
+error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:156:29
    |
-LL |         let _ = str.to_path_buf().clone();
-   |                 ~~~~~~~~~~~~~~~~~
+LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) {
+   |                             ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
 
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed
index cc93859269c..a89845c1dd3 100644
--- a/tests/ui/redundant_pattern_matching_option.fixed
+++ b/tests/ui/redundant_pattern_matching_option.fixed
@@ -81,7 +81,7 @@ const fn issue6067() {
     None::<()>.is_none();
 }
 
-#[allow(clippy::deref_addrof, dead_code)]
+#[allow(clippy::deref_addrof, dead_code, clippy::needless_borrow)]
 fn issue7921() {
     if (&None::<()>).is_none() {}
     if (&None::<()>).is_none() {}
diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs
index 280dca40c01..d6f44403487 100644
--- a/tests/ui/redundant_pattern_matching_option.rs
+++ b/tests/ui/redundant_pattern_matching_option.rs
@@ -96,7 +96,7 @@ const fn issue6067() {
     };
 }
 
-#[allow(clippy::deref_addrof, dead_code)]
+#[allow(clippy::deref_addrof, dead_code, clippy::needless_borrow)]
 fn issue7921() {
     if let None = *(&None::<()>) {}
     if let None = *&None::<()> {}
diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed
index b9425733a8b..8bddec576ed 100644
--- a/tests/ui/rename.fixed
+++ b/tests/ui/rename.fixed
@@ -54,6 +54,7 @@
 #![warn(clippy::match_result_ok)]
 #![warn(clippy::disallowed_types)]
 #![warn(clippy::disallowed_methods)]
+#![warn(clippy::needless_borrow)]
 // uplifted lints
 #![warn(invalid_value)]
 #![warn(array_into_iter)]
diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs
index 341c003b9df..d2010d71d2c 100644
--- a/tests/ui/rename.rs
+++ b/tests/ui/rename.rs
@@ -54,6 +54,7 @@
 #![warn(clippy::if_let_some_result)]
 #![warn(clippy::disallowed_type)]
 #![warn(clippy::disallowed_method)]
+#![warn(clippy::ref_in_deref)]
 // uplifted lints
 #![warn(clippy::invalid_ref)]
 #![warn(clippy::into_iter_on_array)]
diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr
index cdec2808f1d..45cb8b786f5 100644
--- a/tests/ui/rename.stderr
+++ b/tests/ui/rename.stderr
@@ -138,59 +138,65 @@ error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
+error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
+  --> $DIR/rename.rs:57:9
+   |
+LL | #![warn(clippy::ref_in_deref)]
+   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
+
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
-error: aborting due to 32 previous errors
+error: aborting due to 33 previous errors
 
diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs
index 778f4f6fa25..767518ab0c0 100644
--- a/tests/ui/search_is_some_fixable_none.rs
+++ b/tests/ui/search_is_some_fixable_none.rs
@@ -189,7 +189,7 @@ mod issue7392 {
         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
     }
 
-    fn test_string_1(s: &String) -> bool {
+    fn test_string_1(s: &str) -> bool {
         s.is_empty()
     }
 
diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index 7c5e5eb589c..933ce5cf42d 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -251,14 +251,6 @@ error: called `is_none()` after searching an `Iterator` with `find`
 LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
 
-error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/search_is_some_fixable_none.rs:192:25
-   |
-LL |     fn test_string_1(s: &String) -> bool {
-   |                         ^^^^^^^ help: change this to: `&str`
-   |
-   = note: `-D clippy::ptr-arg` implied by `-D warnings`
-
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:208:17
    |
@@ -289,5 +281,5 @@ error: called `is_none()` after searching an `Iterator` with `find`
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
-error: aborting due to 44 previous errors
+error: aborting due to 43 previous errors
 
diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs
index 241641fceae..77fd52e4ce7 100644
--- a/tests/ui/search_is_some_fixable_some.rs
+++ b/tests/ui/search_is_some_fixable_some.rs
@@ -188,7 +188,7 @@ mod issue7392 {
         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
     }
 
-    fn test_string_1(s: &String) -> bool {
+    fn test_string_1(s: &str) -> bool {
         s.is_empty()
     }
 
diff --git a/tests/ui/search_is_some_fixable_some.stderr b/tests/ui/search_is_some_fixable_some.stderr
index 9212c6e71ff..8b424f18ef5 100644
--- a/tests/ui/search_is_some_fixable_some.stderr
+++ b/tests/ui/search_is_some_fixable_some.stderr
@@ -234,14 +234,6 @@ error: called `is_some()` after searching an `Iterator` with `find`
 LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
    |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|(&x, y)| x == *y)`
 
-error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/search_is_some_fixable_some.rs:191:25
-   |
-LL |     fn test_string_1(s: &String) -> bool {
-   |                         ^^^^^^^ help: change this to: `&str`
-   |
-   = note: `-D clippy::ptr-arg` implied by `-D warnings`
-
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:207:26
    |
@@ -272,5 +264,5 @@ error: called `is_some()` after searching an `Iterator` with `find`
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|fp| test_u32_2(*fp.field))`
 
-error: aborting due to 44 previous errors
+error: aborting due to 43 previous errors
 
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index b1819e08d53..bd371888046 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -145,6 +145,84 @@ fn if_suggestion() {
     };
 }
 
+// See: issue #8282
+fn ranges() {
+    enum E {
+        V,
+    }
+    let x = (Some(E::V), Some(42));
+
+    // Don't lint, because the `E` enum can be extended with additional fields later. Thus, the
+    // proposed replacement to `if let Some(E::V)` may hide non-exhaustive warnings that appeared
+    // because of `match` construction.
+    match x {
+        (Some(E::V), _) => {},
+        (None, _) => {},
+    }
+
+    // lint
+    match x {
+        (Some(_), _) => {},
+        (None, _) => {},
+    }
+
+    // lint
+    match x {
+        (Some(E::V), _) => todo!(),
+        (_, _) => {},
+    }
+
+    // lint
+    match (Some(42), Some(E::V), Some(42)) {
+        (.., Some(E::V), _) => {},
+        (..) => {},
+    }
+
+    // Don't lint, see above.
+    match (Some(E::V), Some(E::V), Some(E::V)) {
+        (.., Some(E::V), _) => {},
+        (.., None, _) => {},
+    }
+
+    // Don't lint, see above.
+    match (Some(E::V), Some(E::V), Some(E::V)) {
+        (Some(E::V), ..) => {},
+        (None, ..) => {},
+    }
+
+    // Don't lint, see above.
+    match (Some(E::V), Some(E::V), Some(E::V)) {
+        (_, Some(E::V), ..) => {},
+        (_, None, ..) => {},
+    }
+}
+
+fn skip_type_aliases() {
+    enum OptionEx {
+        Some(i32),
+        None,
+    }
+    enum ResultEx {
+        Err(i32),
+        Ok(i32),
+    }
+
+    use OptionEx::{None, Some};
+    use ResultEx::{Err, Ok};
+
+    // don't lint
+    match Err(42) {
+        Ok(_) => dummy(),
+        Err(_) => (),
+    };
+
+    // don't lint
+    match Some(1i32) {
+        Some(_) => dummy(),
+        None => (),
+    };
+}
+
 macro_rules! single_match {
     ($num:literal) => {
         match $num {
diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr
index c261b5111c8..318faf25717 100644
--- a/tests/ui/single_match.stderr
+++ b/tests/ui/single_match.stderr
@@ -39,15 +39,6 @@ LL | |     };
    | |_____^ help: try this: `if let (2..=3, 7..=9) = z { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:54:5
-   |
-LL | /     match x {
-LL | |         Some(y) => dummy(),
-LL | |         None => (),
-LL | |     };
-   | |_____^ help: try this: `if let Some(y) = x { dummy() }`
-
-error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
   --> $DIR/single_match.rs:59:5
    |
 LL | /     match y {
@@ -128,5 +119,32 @@ LL | |         _ => (),
 LL | |     };
    | |_____^ help: try this: `if let None = x { println!() }`
 
-error: aborting due to 13 previous errors
+error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
+  --> $DIR/single_match.rs:164:5
+   |
+LL | /     match x {
+LL | |         (Some(_), _) => {},
+LL | |         (None, _) => {},
+LL | |     }
+   | |_____^ help: try this: `if let (Some(_), _) = x {}`
+
+error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
+  --> $DIR/single_match.rs:170:5
+   |
+LL | /     match x {
+LL | |         (Some(E::V), _) => todo!(),
+LL | |         (_, _) => {},
+LL | |     }
+   | |_____^ help: try this: `if let (Some(E::V), _) = x { todo!() }`
+
+error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
+  --> $DIR/single_match.rs:176:5
+   |
+LL | /     match (Some(42), Some(E::V), Some(42)) {
+LL | |         (.., Some(E::V), _) => {},
+LL | |         (..) => {},
+LL | |     }
+   | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}`
+
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr
index c61d80a905c..21ea704b62a 100644
--- a/tests/ui/single_match_else.stderr
+++ b/tests/ui/single_match_else.stderr
@@ -19,45 +19,5 @@ LL +         None
 LL +     }
    |
 
-error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match_else.rs:70:5
-   |
-LL | /     match Some(1) {
-LL | |         Some(a) => println!("${:?}", a),
-LL | |         None => {
-LL | |             println!("else block");
-LL | |             return
-LL | |         },
-LL | |     }
-   | |_____^
-   |
-help: try this
-   |
-LL ~     if let Some(a) = Some(1) { println!("${:?}", a) } else {
-LL +         println!("else block");
-LL +         return
-LL +     }
-   |
-
-error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match_else.rs:79:5
-   |
-LL | /     match Some(1) {
-LL | |         Some(a) => println!("${:?}", a),
-LL | |         None => {
-LL | |             println!("else block");
-LL | |             return;
-LL | |         },
-LL | |     }
-   | |_____^
-   |
-help: try this
-   |
-LL ~     if let Some(a) = Some(1) { println!("${:?}", a) } else {
-LL +         println!("else block");
-LL +         return;
-LL +     }
-   |
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs
index c5ae3ff769b..7e3d357ae50 100644
--- a/tests/ui/slow_vector_initialization.rs
+++ b/tests/ui/slow_vector_initialization.rs
@@ -53,7 +53,7 @@ fn resize_vector() {
     vec1.resize(10, 0);
 }
 
-fn do_stuff(vec: &mut Vec<u8>) {}
+fn do_stuff(vec: &mut [u8]) {}
 
 fn extend_vector_with_manipulations_between() {
     let len = 300;
diff --git a/tests/ui/to_string_in_display.stderr b/tests/ui/to_string_in_display.stderr
index 5f26ef413e2..80189ca1f0a 100644
--- a/tests/ui/to_string_in_display.stderr
+++ b/tests/ui/to_string_in_display.stderr
@@ -6,5 +6,14 @@ LL |         write!(f, "{}", self.to_string())
    |
    = note: `-D clippy::to-string-in-display` implied by `-D warnings`
 
-error: aborting due to previous error
+error: unnecessary use of `to_string`
+  --> $DIR/to_string_in_display.rs:55:50
+   |
+LL |             Self::E(string) => write!(f, "E {}", string.to_string()),
+   |                                                  ^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::unnecessary-to-owned` implied by `-D warnings`
+   = note: this error originates in the macro `$crate::format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs
index 2edb202892a..21de19a2601 100644
--- a/tests/ui/trait_duplication_in_bounds.rs
+++ b/tests/ui/trait_duplication_in_bounds.rs
@@ -1,5 +1,6 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 
+use std::collections::BTreeMap;
 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
 
 fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
@@ -73,4 +74,25 @@ impl U for Life {
     fn f() {}
 }
 
+// should not warn
+trait Iter: Iterator {
+    fn into_group_btreemap<K, V>(self) -> BTreeMap<K, Vec<V>>
+    where
+        Self: Iterator<Item = (K, V)> + Sized,
+        K: Ord + Eq,
+    {
+        unimplemented!();
+    }
+}
+
+struct Foo {}
+
+trait FooIter: Iterator<Item = Foo> {
+    fn bar()
+    where
+        Self: Iterator<Item = Foo>,
+    {
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/trait_duplication_in_bounds.stderr b/tests/ui/trait_duplication_in_bounds.stderr
index e0c7a7ec618..6f8c8e47dfb 100644
--- a/tests/ui/trait_duplication_in_bounds.stderr
+++ b/tests/ui/trait_duplication_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:5:15
+  --> $DIR/trait_duplication_in_bounds.rs:6:15
    |
 LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
    |               ^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::trait_duplication_in_bounds)]
    = help: consider removing this trait bound
 
 error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:5:23
+  --> $DIR/trait_duplication_in_bounds.rs:6:23
    |
 LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
    |                       ^^^^^^^
@@ -20,7 +20,7 @@ LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
    = help: consider removing this trait bound
 
 error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:34:15
+  --> $DIR/trait_duplication_in_bounds.rs:35:15
    |
 LL |         Self: Default;
    |               ^^^^^^^
@@ -28,7 +28,7 @@ LL |         Self: Default;
    = help: consider removing this trait bound
 
 error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:48:15
+  --> $DIR/trait_duplication_in_bounds.rs:49:15
    |
 LL |         Self: Default + Clone;
    |               ^^^^^^^
@@ -36,7 +36,7 @@ LL |         Self: Default + Clone;
    = help: consider removing this trait bound
 
 error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:54:15
+  --> $DIR/trait_duplication_in_bounds.rs:55:15
    |
 LL |         Self: Default + Clone;
    |               ^^^^^^^
@@ -44,7 +44,7 @@ LL |         Self: Default + Clone;
    = help: consider removing this trait bound
 
 error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:54:25
+  --> $DIR/trait_duplication_in_bounds.rs:55:25
    |
 LL |         Self: Default + Clone;
    |                         ^^^^^
@@ -52,12 +52,20 @@ LL |         Self: Default + Clone;
    = help: consider removing this trait bound
 
 error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:57:15
+  --> $DIR/trait_duplication_in_bounds.rs:58:15
    |
 LL |         Self: Default;
    |               ^^^^^^^
    |
    = help: consider removing this trait bound
 
-error: aborting due to 7 previous errors
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds.rs:93:15
+   |
+LL |         Self: Iterator<Item = Foo>,
+   |               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs
index e8f2fb46665..b77c19f2ba5 100644
--- a/tests/ui/unnecessary_cast.rs
+++ b/tests/ui/unnecessary_cast.rs
@@ -1,6 +1,7 @@
 #![warn(clippy::unnecessary_cast)]
 #![allow(clippy::no_effect)]
 
+#[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
     1i32 as i32;
@@ -8,6 +9,12 @@ fn main() {
     false as bool;
     &1i32 as &i32;
 
+    -1_i32 as i32;
+    - 1_i32 as i32;
+    -1f32 as f32;
+    1_i32 as i32;
+    1_f32 as f32;
+
     // macro version
     macro_rules! foo {
         ($a:ident, $b:ident) => {
diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr
index 70aa448af68..a5a93c6110c 100644
--- a/tests/ui/unnecessary_cast.stderr
+++ b/tests/ui/unnecessary_cast.stderr
@@ -1,5 +1,5 @@
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:6:5
+  --> $DIR/unnecessary_cast.rs:7:5
    |
 LL |     1i32 as i32;
    |     ^^^^^^^^^^^ help: try: `1_i32`
@@ -7,16 +7,46 @@ LL |     1i32 as i32;
    = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:7:5
+  --> $DIR/unnecessary_cast.rs:8:5
    |
 LL |     1f32 as f32;
    |     ^^^^^^^^^^^ help: try: `1_f32`
 
 error: casting to the same type is unnecessary (`bool` -> `bool`)
-  --> $DIR/unnecessary_cast.rs:8:5
+  --> $DIR/unnecessary_cast.rs:9:5
    |
 LL |     false as bool;
    |     ^^^^^^^^^^^^^ help: try: `false`
 
-error: aborting due to 3 previous errors
+error: casting integer literal to `i32` is unnecessary
+  --> $DIR/unnecessary_cast.rs:12:5
+   |
+LL |     -1_i32 as i32;
+   |     ^^^^^^^^^^^^^ help: try: `-1_i32`
+
+error: casting integer literal to `i32` is unnecessary
+  --> $DIR/unnecessary_cast.rs:13:5
+   |
+LL |     - 1_i32 as i32;
+   |     ^^^^^^^^^^^^^^ help: try: `- 1_i32`
+
+error: casting float literal to `f32` is unnecessary
+  --> $DIR/unnecessary_cast.rs:14:5
+   |
+LL |     -1f32 as f32;
+   |     ^^^^^^^^^^^^ help: try: `-1_f32`
+
+error: casting integer literal to `i32` is unnecessary
+  --> $DIR/unnecessary_cast.rs:15:5
+   |
+LL |     1_i32 as i32;
+   |     ^^^^^^^^^^^^ help: try: `1_i32`
+
+error: casting float literal to `f32` is unnecessary
+  --> $DIR/unnecessary_cast.rs:16:5
+   |
+LL |     1_f32 as f32;
+   |     ^^^^^^^^^^^^ help: try: `1_f32`
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/unnecessary_ref.fixed b/tests/ui/unnecessary_ref.fixed
deleted file mode 100644
index d927bae976f..00000000000
--- a/tests/ui/unnecessary_ref.fixed
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-rustfix
-
-#![feature(stmt_expr_attributes)]
-#![allow(unused_variables, dead_code)]
-
-struct Outer {
-    inner: u32,
-}
-
-#[deny(clippy::ref_in_deref)]
-fn main() {
-    let outer = Outer { inner: 0 };
-    let inner = outer.inner;
-}
-
-struct Apple;
-impl Apple {
-    fn hello(&self) {}
-}
-struct Package(pub *const Apple);
-fn foobar(package: *const Package) {
-    unsafe { &*(*package).0 }.hello();
-}
diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs
deleted file mode 100644
index 86bfb76ec26..00000000000
--- a/tests/ui/unnecessary_ref.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-rustfix
-
-#![feature(stmt_expr_attributes)]
-#![allow(unused_variables, dead_code)]
-
-struct Outer {
-    inner: u32,
-}
-
-#[deny(clippy::ref_in_deref)]
-fn main() {
-    let outer = Outer { inner: 0 };
-    let inner = (&outer).inner;
-}
-
-struct Apple;
-impl Apple {
-    fn hello(&self) {}
-}
-struct Package(pub *const Apple);
-fn foobar(package: *const Package) {
-    unsafe { &*(&*package).0 }.hello();
-}
diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr
deleted file mode 100644
index 436f4bcf738..00000000000
--- a/tests/ui/unnecessary_ref.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: creating a reference that is immediately dereferenced
-  --> $DIR/unnecessary_ref.rs:13:17
-   |
-LL |     let inner = (&outer).inner;
-   |                 ^^^^^^^^ help: try this: `outer`
-   |
-note: the lint level is defined here
-  --> $DIR/unnecessary_ref.rs:10:8
-   |
-LL | #[deny(clippy::ref_in_deref)]
-   |        ^^^^^^^^^^^^^^^^^^^^
-
-error: creating a reference that is immediately dereferenced
-  --> $DIR/unnecessary_ref.rs:22:16
-   |
-LL |     unsafe { &*(&*package).0 }.hello();
-   |                ^^^^^^^^^^^ help: try this: `(*package)`
-   |
-   = note: `-D clippy::ref-in-deref` implied by `-D warnings`
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed
index e356f13d087..e431661d180 100644
--- a/tests/ui/useless_asref.fixed
+++ b/tests/ui/useless_asref.fixed
@@ -67,7 +67,7 @@ fn not_ok() {
         foo_rslice(mrrrrrslice);
         foo_rslice(mrrrrrslice);
     }
-    #[allow(unused_parens, clippy::double_parens)]
+    #[allow(unused_parens, clippy::double_parens, clippy::needless_borrow)]
     foo_rrrrmr((&&&&MoreRef));
 
     generic_not_ok(mrslice);
diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs
index 2a80291f5d8..6ae931d7aa4 100644
--- a/tests/ui/useless_asref.rs
+++ b/tests/ui/useless_asref.rs
@@ -67,7 +67,7 @@ fn not_ok() {
         foo_rslice(mrrrrrslice.as_ref());
         foo_rslice(mrrrrrslice);
     }
-    #[allow(unused_parens, clippy::double_parens)]
+    #[allow(unused_parens, clippy::double_parens, clippy::needless_borrow)]
     foo_rrrrmr((&&&&MoreRef).as_ref());
 
     generic_not_ok(mrslice);
diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs
index 0a127858def..44669174411 100644
--- a/tests/ui/write_literal.rs
+++ b/tests/ui/write_literal.rs
@@ -7,37 +7,37 @@ fn main() {
     let mut v = Vec::new();
 
     // these should be fine
-    write!(&mut v, "Hello");
-    writeln!(&mut v, "Hello");
+    write!(v, "Hello");
+    writeln!(v, "Hello");
     let world = "world";
-    writeln!(&mut v, "Hello {}", world);
-    writeln!(&mut v, "Hello {world}", world = world);
-    writeln!(&mut v, "3 in hex is {:X}", 3);
-    writeln!(&mut v, "2 + 1 = {:.4}", 3);
-    writeln!(&mut v, "2 + 1 = {:5.4}", 3);
-    writeln!(&mut v, "Debug test {:?}", "hello, world");
-    writeln!(&mut v, "{0:8} {1:>8}", "hello", "world");
-    writeln!(&mut v, "{1:8} {0:>8}", "hello", "world");
-    writeln!(&mut v, "{foo:8} {bar:>8}", foo = "hello", bar = "world");
-    writeln!(&mut v, "{bar:8} {foo:>8}", foo = "hello", bar = "world");
-    writeln!(&mut v, "{number:>width$}", number = 1, width = 6);
-    writeln!(&mut v, "{number:>0width$}", number = 1, width = 6);
-    writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2);
-    writeln!(&mut v, "10 / 4 is {}", 2.5);
-    writeln!(&mut v, "2 + 1 = {}", 3);
+    writeln!(v, "Hello {}", world);
+    writeln!(v, "Hello {world}", world = world);
+    writeln!(v, "3 in hex is {:X}", 3);
+    writeln!(v, "2 + 1 = {:.4}", 3);
+    writeln!(v, "2 + 1 = {:5.4}", 3);
+    writeln!(v, "Debug test {:?}", "hello, world");
+    writeln!(v, "{0:8} {1:>8}", "hello", "world");
+    writeln!(v, "{1:8} {0:>8}", "hello", "world");
+    writeln!(v, "{foo:8} {bar:>8}", foo = "hello", bar = "world");
+    writeln!(v, "{bar:8} {foo:>8}", foo = "hello", bar = "world");
+    writeln!(v, "{number:>width$}", number = 1, width = 6);
+    writeln!(v, "{number:>0width$}", number = 1, width = 6);
+    writeln!(v, "{} of {:b} people know binary, the other half doesn't", 1, 2);
+    writeln!(v, "10 / 4 is {}", 2.5);
+    writeln!(v, "2 + 1 = {}", 3);
 
     // these should throw warnings
-    write!(&mut v, "Hello {}", "world");
-    writeln!(&mut v, "Hello {} {}", world, "world");
-    writeln!(&mut v, "Hello {}", "world");
+    write!(v, "Hello {}", "world");
+    writeln!(v, "Hello {} {}", world, "world");
+    writeln!(v, "Hello {}", "world");
 
     // positional args don't change the fact
     // that we're using a literal -- this should
     // throw a warning
-    writeln!(&mut v, "{0} {1}", "hello", "world");
-    writeln!(&mut v, "{1} {0}", "hello", "world");
+    writeln!(v, "{0} {1}", "hello", "world");
+    writeln!(v, "{1} {0}", "hello", "world");
 
     // named args shouldn't change anything either
-    writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-    writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
+    writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+    writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
 }
diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr
index e0297c00231..593e9493ec5 100644
--- a/tests/ui/write_literal.stderr
+++ b/tests/ui/write_literal.stderr
@@ -1,134 +1,134 @@
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:30:32
+  --> $DIR/write_literal.rs:30:27
    |
-LL |     write!(&mut v, "Hello {}", "world");
-   |                                ^^^^^^^
+LL |     write!(v, "Hello {}", "world");
+   |                           ^^^^^^^
    |
    = note: `-D clippy::write-literal` implied by `-D warnings`
 help: try this
    |
-LL -     write!(&mut v, "Hello {}", "world");
-LL +     write!(&mut v, "Hello world");
+LL -     write!(v, "Hello {}", "world");
+LL +     write!(v, "Hello world");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:31:44
+  --> $DIR/write_literal.rs:31:39
    |
-LL |     writeln!(&mut v, "Hello {} {}", world, "world");
-   |                                            ^^^^^^^
+LL |     writeln!(v, "Hello {} {}", world, "world");
+   |                                       ^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "Hello {} {}", world, "world");
-LL +     writeln!(&mut v, "Hello {} world", world);
+LL -     writeln!(v, "Hello {} {}", world, "world");
+LL +     writeln!(v, "Hello {} world", world);
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:32:34
+  --> $DIR/write_literal.rs:32:29
    |
-LL |     writeln!(&mut v, "Hello {}", "world");
-   |                                  ^^^^^^^
+LL |     writeln!(v, "Hello {}", "world");
+   |                             ^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "Hello {}", "world");
-LL +     writeln!(&mut v, "Hello world");
+LL -     writeln!(v, "Hello {}", "world");
+LL +     writeln!(v, "Hello world");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:37:33
+  --> $DIR/write_literal.rs:37:28
    |
-LL |     writeln!(&mut v, "{0} {1}", "hello", "world");
-   |                                 ^^^^^^^
+LL |     writeln!(v, "{0} {1}", "hello", "world");
+   |                            ^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{0} {1}", "hello", "world");
-LL +     writeln!(&mut v, "hello {1}", "world");
+LL -     writeln!(v, "{0} {1}", "hello", "world");
+LL +     writeln!(v, "hello {1}", "world");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:37:42
+  --> $DIR/write_literal.rs:37:37
    |
-LL |     writeln!(&mut v, "{0} {1}", "hello", "world");
-   |                                          ^^^^^^^
+LL |     writeln!(v, "{0} {1}", "hello", "world");
+   |                                     ^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{0} {1}", "hello", "world");
-LL +     writeln!(&mut v, "{0} world", "hello");
+LL -     writeln!(v, "{0} {1}", "hello", "world");
+LL +     writeln!(v, "{0} world", "hello");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:38:33
+  --> $DIR/write_literal.rs:38:28
    |
-LL |     writeln!(&mut v, "{1} {0}", "hello", "world");
-   |                                 ^^^^^^^
+LL |     writeln!(v, "{1} {0}", "hello", "world");
+   |                            ^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{1} {0}", "hello", "world");
-LL +     writeln!(&mut v, "{1} hello", "world");
+LL -     writeln!(v, "{1} {0}", "hello", "world");
+LL +     writeln!(v, "{1} hello", "world");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:38:42
+  --> $DIR/write_literal.rs:38:37
    |
-LL |     writeln!(&mut v, "{1} {0}", "hello", "world");
-   |                                          ^^^^^^^
+LL |     writeln!(v, "{1} {0}", "hello", "world");
+   |                                     ^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{1} {0}", "hello", "world");
-LL +     writeln!(&mut v, "world {0}", "hello");
+LL -     writeln!(v, "{1} {0}", "hello", "world");
+LL +     writeln!(v, "world {0}", "hello");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:41:37
+  --> $DIR/write_literal.rs:41:32
    |
-LL |     writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-   |                                     ^^^^^^^^^^^^^
+LL |     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+   |                                ^^^^^^^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-LL +     writeln!(&mut v, "hello {bar}", bar = "world");
+LL -     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+LL +     writeln!(v, "hello {bar}", bar = "world");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:41:52
+  --> $DIR/write_literal.rs:41:47
    |
-LL |     writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-   |                                                    ^^^^^^^^^^^^^
+LL |     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+   |                                               ^^^^^^^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world");
-LL +     writeln!(&mut v, "{foo} world", foo = "hello");
+LL -     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+LL +     writeln!(v, "{foo} world", foo = "hello");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:42:37
+  --> $DIR/write_literal.rs:42:32
    |
-LL |     writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
-   |                                     ^^^^^^^^^^^^^
+LL |     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
+   |                                ^^^^^^^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
-LL +     writeln!(&mut v, "{bar} hello", bar = "world");
+LL -     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
+LL +     writeln!(v, "{bar} hello", bar = "world");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:42:52
+  --> $DIR/write_literal.rs:42:47
    |
-LL |     writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
-   |                                                    ^^^^^^^^^^^^^
+LL |     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
+   |                                               ^^^^^^^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world");
-LL +     writeln!(&mut v, "world {foo}", foo = "hello");
+LL -     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
+LL +     writeln!(v, "world {foo}", foo = "hello");
    | 
 
 error: aborting due to 11 previous errors
diff --git a/tests/ui/write_literal_2.rs b/tests/ui/write_literal_2.rs
index f341e8215e1..ba0d7be5eaa 100644
--- a/tests/ui/write_literal_2.rs
+++ b/tests/ui/write_literal_2.rs
@@ -6,20 +6,20 @@ use std::io::Write;
 fn main() {
     let mut v = Vec::new();
 
-    writeln!(&mut v, "{}", "{hello}");
-    writeln!(&mut v, r"{}", r"{hello}");
-    writeln!(&mut v, "{}", '\'');
-    writeln!(&mut v, "{}", '"');
-    writeln!(&mut v, r"{}", '"'); // don't lint
-    writeln!(&mut v, r"{}", '\'');
+    writeln!(v, "{}", "{hello}");
+    writeln!(v, r"{}", r"{hello}");
+    writeln!(v, "{}", '\'');
+    writeln!(v, "{}", '"');
+    writeln!(v, r"{}", '"'); // don't lint
+    writeln!(v, r"{}", '\'');
     writeln!(
-        &mut v,
+        v,
         "some {}",
         "hello \
         world!"
     );
     writeln!(
-        &mut v,
+        v,
         "some {}\
         {} \\ {}",
         "1", "2", "3",
diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr
index 73c6b885813..fc40fbfa9e2 100644
--- a/tests/ui/write_literal_2.stderr
+++ b/tests/ui/write_literal_2.stderr
@@ -1,62 +1,62 @@
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:9:28
+  --> $DIR/write_literal_2.rs:9:23
    |
-LL |     writeln!(&mut v, "{}", "{hello}");
-   |                            ^^^^^^^^^
+LL |     writeln!(v, "{}", "{hello}");
+   |                       ^^^^^^^^^
    |
    = note: `-D clippy::write-literal` implied by `-D warnings`
 help: try this
    |
-LL -     writeln!(&mut v, "{}", "{hello}");
-LL +     writeln!(&mut v, "{{hello}}");
+LL -     writeln!(v, "{}", "{hello}");
+LL +     writeln!(v, "{{hello}}");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:10:29
+  --> $DIR/write_literal_2.rs:10:24
    |
-LL |     writeln!(&mut v, r"{}", r"{hello}");
-   |                             ^^^^^^^^^^
+LL |     writeln!(v, r"{}", r"{hello}");
+   |                        ^^^^^^^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, r"{}", r"{hello}");
-LL +     writeln!(&mut v, r"{{hello}}");
+LL -     writeln!(v, r"{}", r"{hello}");
+LL +     writeln!(v, r"{{hello}}");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:11:28
+  --> $DIR/write_literal_2.rs:11:23
    |
-LL |     writeln!(&mut v, "{}", '/'');
-   |                            ^^^^
+LL |     writeln!(v, "{}", '/'');
+   |                       ^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{}", '/'');
-LL +     writeln!(&mut v, "'");
+LL -     writeln!(v, "{}", '/'');
+LL +     writeln!(v, "'");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:12:28
+  --> $DIR/write_literal_2.rs:12:23
    |
-LL |     writeln!(&mut v, "{}", '"');
-   |                            ^^^
+LL |     writeln!(v, "{}", '"');
+   |                       ^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, "{}", '"');
-LL +     writeln!(&mut v, "/"");
+LL -     writeln!(v, "{}", '"');
+LL +     writeln!(v, "/"");
    | 
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:14:29
+  --> $DIR/write_literal_2.rs:14:24
    |
-LL |     writeln!(&mut v, r"{}", '/'');
-   |                             ^^^^
+LL |     writeln!(v, r"{}", '/'');
+   |                        ^^^^
    |
 help: try this
    |
-LL -     writeln!(&mut v, r"{}", '/'');
-LL +     writeln!(&mut v, r"'");
+LL -     writeln!(v, r"{}", '/'');
+LL +     writeln!(v, r"'");
    | 
 
 error: literal with an empty format string
diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs
index 1c1b1b58402..446d6914d34 100644
--- a/tests/ui/write_with_newline.rs
+++ b/tests/ui/write_with_newline.rs
@@ -10,50 +10,50 @@ fn main() {
     let mut v = Vec::new();
 
     // These should fail
-    write!(&mut v, "Hello\n");
-    write!(&mut v, "Hello {}\n", "world");
-    write!(&mut v, "Hello {} {}\n", "world", "#2");
-    write!(&mut v, "{}\n", 1265);
-    write!(&mut v, "\n");
+    write!(v, "Hello\n");
+    write!(v, "Hello {}\n", "world");
+    write!(v, "Hello {} {}\n", "world", "#2");
+    write!(v, "{}\n", 1265);
+    write!(v, "\n");
 
     // These should be fine
-    write!(&mut v, "");
-    write!(&mut v, "Hello");
-    writeln!(&mut v, "Hello");
-    writeln!(&mut v, "Hello\n");
-    writeln!(&mut v, "Hello {}\n", "world");
-    write!(&mut v, "Issue\n{}", 1265);
-    write!(&mut v, "{}", 1265);
-    write!(&mut v, "\n{}", 1275);
-    write!(&mut v, "\n\n");
-    write!(&mut v, "like eof\n\n");
-    write!(&mut v, "Hello {} {}\n\n", "world", "#2");
-    writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
-    writeln!(&mut v, "\nbla\n\n"); // #3126
+    write!(v, "");
+    write!(v, "Hello");
+    writeln!(v, "Hello");
+    writeln!(v, "Hello\n");
+    writeln!(v, "Hello {}\n", "world");
+    write!(v, "Issue\n{}", 1265);
+    write!(v, "{}", 1265);
+    write!(v, "\n{}", 1275);
+    write!(v, "\n\n");
+    write!(v, "like eof\n\n");
+    write!(v, "Hello {} {}\n\n", "world", "#2");
+    writeln!(v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
+    writeln!(v, "\nbla\n\n"); // #3126
 
     // Escaping
-    write!(&mut v, "\\n"); // #3514
-    write!(&mut v, "\\\n"); // should fail
-    write!(&mut v, "\\\\n");
+    write!(v, "\\n"); // #3514
+    write!(v, "\\\n"); // should fail
+    write!(v, "\\\\n");
 
     // Raw strings
-    write!(&mut v, r"\n"); // #3778
+    write!(v, r"\n"); // #3778
 
     // Literal newlines should also fail
     write!(
-        &mut v,
+        v,
         "
 "
     );
     write!(
-        &mut v,
+        v,
         r"
 "
     );
 
     // Don't warn on CRLF (#4208)
-    write!(&mut v, "\r\n");
-    write!(&mut v, "foo\r\n");
-    write!(&mut v, "\\r\n"); //~ ERROR
-    write!(&mut v, "foo\rbar\n");
+    write!(v, "\r\n");
+    write!(v, "foo\r\n");
+    write!(v, "\\r\n"); //~ ERROR
+    write!(v, "foo\rbar\n");
 }
diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr
index 186459e50b6..3314a2a6e24 100644
--- a/tests/ui/write_with_newline.stderr
+++ b/tests/ui/write_with_newline.stderr
@@ -1,81 +1,81 @@
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:13:5
    |
-LL |     write!(&mut v, "Hello/n");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "Hello/n");
+   |     ^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::write-with-newline` implied by `-D warnings`
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "Hello/n");
-LL +     writeln!(&mut v, "Hello");
+LL -     write!(v, "Hello/n");
+LL +     writeln!(v, "Hello");
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:14:5
    |
-LL |     write!(&mut v, "Hello {}/n", "world");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "Hello {}/n", "world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "Hello {}/n", "world");
-LL +     writeln!(&mut v, "Hello {}", "world");
+LL -     write!(v, "Hello {}/n", "world");
+LL +     writeln!(v, "Hello {}", "world");
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:15:5
    |
-LL |     write!(&mut v, "Hello {} {}/n", "world", "#2");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "Hello {} {}/n", "world", "#2");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "Hello {} {}/n", "world", "#2");
-LL +     writeln!(&mut v, "Hello {} {}", "world", "#2");
+LL -     write!(v, "Hello {} {}/n", "world", "#2");
+LL +     writeln!(v, "Hello {} {}", "world", "#2");
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:16:5
    |
-LL |     write!(&mut v, "{}/n", 1265);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "{}/n", 1265);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "{}/n", 1265);
-LL +     writeln!(&mut v, "{}", 1265);
+LL -     write!(v, "{}/n", 1265);
+LL +     writeln!(v, "{}", 1265);
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:17:5
    |
-LL |     write!(&mut v, "/n");
-   |     ^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "/n");
+   |     ^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "/n");
-LL +     writeln!(&mut v);
+LL -     write!(v, "/n");
+LL +     writeln!(v);
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:36:5
    |
-LL |     write!(&mut v, "//n"); // should fail
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "//n"); // should fail
+   |     ^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "//n"); // should fail
-LL +     writeln!(&mut v, "/"); // should fail
+LL -     write!(v, "//n"); // should fail
+LL +     writeln!(v, "/"); // should fail
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:43:5
    |
 LL | /     write!(
-LL | |         &mut v,
+LL | |         v,
 LL | |         "
 LL | | "
 LL | |     );
@@ -84,7 +84,7 @@ LL | |     );
 help: use `writeln!()` instead
    |
 LL ~     writeln!(
-LL |         &mut v,
+LL |         v,
 LL ~         ""
    |
 
@@ -92,7 +92,7 @@ error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:48:5
    |
 LL | /     write!(
-LL | |         &mut v,
+LL | |         v,
 LL | |         r"
 LL | | "
 LL | |     );
@@ -101,32 +101,32 @@ LL | |     );
 help: use `writeln!()` instead
    |
 LL ~     writeln!(
-LL |         &mut v,
+LL |         v,
 LL ~         r""
    |
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:57:5
    |
-LL |     write!(&mut v, "/r/n"); //~ ERROR
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "/r/n"); //~ ERROR
+   |     ^^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "/r/n"); //~ ERROR
-LL +     writeln!(&mut v, "/r"); //~ ERROR
+LL -     write!(v, "/r/n"); //~ ERROR
+LL +     writeln!(v, "/r"); //~ ERROR
    | 
 
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:58:5
    |
-LL |     write!(&mut v, "foo/rbar/n");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     write!(v, "foo/rbar/n");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!()` instead
    |
-LL -     write!(&mut v, "foo/rbar/n");
-LL +     writeln!(&mut v, "foo/rbar");
+LL -     write!(v, "foo/rbar/n");
+LL +     writeln!(v, "foo/rbar");
    | 
 
 error: aborting due to 10 previous errors
diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed
index c3ac15b0375..e7d94acd130 100644
--- a/tests/ui/writeln_empty_string.fixed
+++ b/tests/ui/writeln_empty_string.fixed
@@ -8,13 +8,13 @@ fn main() {
     let mut v = Vec::new();
 
     // These should fail
-    writeln!(&mut v);
+    writeln!(v);
 
     let mut suggestion = Vec::new();
-    writeln!(&mut suggestion);
+    writeln!(suggestion);
 
     // These should be fine
-    writeln!(&mut v);
-    writeln!(&mut v, " ");
-    write!(&mut v, "");
+    writeln!(v);
+    writeln!(v, " ");
+    write!(v, "");
 }
diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs
index 9a8894b6c0d..662c62f0211 100644
--- a/tests/ui/writeln_empty_string.rs
+++ b/tests/ui/writeln_empty_string.rs
@@ -8,13 +8,13 @@ fn main() {
     let mut v = Vec::new();
 
     // These should fail
-    writeln!(&mut v, "");
+    writeln!(v, "");
 
     let mut suggestion = Vec::new();
-    writeln!(&mut suggestion, "");
+    writeln!(suggestion, "");
 
     // These should be fine
-    writeln!(&mut v);
-    writeln!(&mut v, " ");
-    write!(&mut v, "");
+    writeln!(v);
+    writeln!(v, " ");
+    write!(v, "");
 }
diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr
index 99635229b3e..ac65aadfc0e 100644
--- a/tests/ui/writeln_empty_string.stderr
+++ b/tests/ui/writeln_empty_string.stderr
@@ -1,16 +1,16 @@
-error: using `writeln!(&mut v, "")`
+error: using `writeln!(v, "")`
   --> $DIR/writeln_empty_string.rs:11:5
    |
-LL |     writeln!(&mut v, "");
-   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)`
+LL |     writeln!(v, "");
+   |     ^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)`
    |
    = note: `-D clippy::writeln-empty-string` implied by `-D warnings`
 
-error: using `writeln!(&mut suggestion, "")`
+error: using `writeln!(suggestion, "")`
   --> $DIR/writeln_empty_string.rs:14:5
    |
-LL |     writeln!(&mut suggestion, "");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)`
+LL |     writeln!(suggestion, "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(suggestion)`
 
 error: aborting due to 2 previous errors
 
diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html
index 5b7e61a349d..83a200ca3c4 100644
--- a/util/gh-pages/index.html
+++ b/util/gh-pages/index.html
@@ -522,6 +522,11 @@ Otherwise, have a great day =^.^=
                 }
 
                 scrollToLintByURL($scope);
+
+                setTimeout(function () {
+                    var el = document.getElementById('filter-input');
+                    if (el) { el.focus() }
+                }, 0);
             })
             .error(function (data) {
                 $scope.error = data;