summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock21
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs3
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl4
-rw-r--r--compiler/rustc_error_messages/locales/en-US/infer.ftl1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/mir_build.ftl61
-rw-r--r--compiler/rustc_error_messages/locales/en-US/trait_selection.ftl4
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs1134
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs (renamed from compiler/rustc_trait_selection/src/autoderef.rs)4
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs37
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/autoderef.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs73
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs101
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs35
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs25
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs8
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp11
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp14
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs24
-rw-r--r--compiler/rustc_macros/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/thir.rs7
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/error.rs14
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs18
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs2
-rw-r--r--compiler/rustc_mir_build/src/errors.rs226
-rw-r--r--compiler/rustc_mir_build/src/lib.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs191
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs188
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs30
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs42
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs14
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs14
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs11
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs13
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs61
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs197
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs3
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/num/int_macros.rs111
-rw-r--r--library/core/src/pin.rs10
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/std/src/thread/mod.rs22
-rw-r--r--src/bootstrap/bootstrap.py3
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile4
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-2068.rs2
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs2
-rw-r--r--src/tools/tidy/Cargo.toml1
-rw-r--r--src/tools/tidy/src/error_codes.rs6
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs4
-rw-r--r--src/tools/tidy/src/x_version.rs65
-rw-r--r--tests/rustdoc/const-intrinsic.rs25
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs2
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr32
-rw-r--r--tests/ui/associated-types/substs-ppaux.normal.stderr8
-rw-r--r--tests/ui/associated-types/substs-ppaux.verbose.stderr8
-rw-r--r--tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr6
-rw-r--r--tests/ui/c-variadic/issue-86053-1.rs2
-rw-r--r--tests/ui/c-variadic/issue-86053-1.stderr22
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-69654.stderr10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr43
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-72787.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-80742.stderr13
-rw-r--r--tests/ui/consts/const-match-check.eval1.stderr2
-rw-r--r--tests/ui/consts/const-match-check.eval2.stderr2
-rw-r--r--tests/ui/consts/const-match-check.matchck.stderr8
-rw-r--r--tests/ui/consts/const-pattern-irrefutable.rs18
-rw-r--r--tests/ui/consts/const-pattern-irrefutable.stderr19
-rw-r--r--tests/ui/consts/const_let_refutable.stderr2
-rw-r--r--tests/ui/consts/ct-var-in-collect_all_mismatches.rs20
-rw-r--r--tests/ui/consts/ct-var-in-collect_all_mismatches.stderr22
-rw-r--r--tests/ui/derives/derive-assoc-type-not-impl.stderr3
-rw-r--r--tests/ui/derives/issue-91492.stderr9
-rw-r--r--tests/ui/derives/issue-91550.stderr31
-rw-r--r--tests/ui/diagnostic-width/E0271.rs33
-rw-r--r--tests/ui/diagnostic-width/E0271.stderr23
-rw-r--r--tests/ui/dyn-star/dyn-star-to-dyn.rs9
-rw-r--r--tests/ui/dyn-star/dyn-star-to-dyn.stderr11
-rw-r--r--tests/ui/empty/empty-never-array.rs3
-rw-r--r--tests/ui/empty/empty-never-array.stderr14
-rw-r--r--tests/ui/error-codes/E0005.stderr13
-rw-r--r--tests/ui/error-codes/E0297.stderr7
-rw-r--r--tests/ui/error-codes/E0311.fixed13
-rw-r--r--tests/ui/error-codes/E0311.rs4
-rw-r--r--tests/ui/error-codes/E0311.stderr10
-rw-r--r--tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr13
-rw-r--r--tests/ui/for/for-loop-refutable-pattern-error-message.stderr2
-rw-r--r--tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs2
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr4
-rw-r--r--tests/ui/impl-trait/bound-normalization-fail.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102140.stderr12
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.stderr9
-rw-r--r--tests/ui/issues/issue-15381.rs3
-rw-r--r--tests/ui/issues/issue-15381.stderr2
-rw-r--r--tests/ui/issues/issue-35241.stderr8
-rw-r--r--tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs4
-rw-r--r--tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr24
-rw-r--r--tests/ui/kindck/kindck-copy.stderr12
-rw-r--r--tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed13
-rw-r--r--tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs4
-rw-r--r--tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr10
-rw-r--r--tests/ui/methods/method-not-found-generic-arg-elision.stderr13
-rw-r--r--tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr16
-rw-r--r--tests/ui/never_type/exhaustive_patterns.stderr8
-rw-r--r--tests/ui/not-panic/not-panic-safe-4.stderr10
-rw-r--r--tests/ui/not-panic/not-panic-safe.rs4
-rw-r--r--tests/ui/not-panic/not-panic-safe.stderr18
-rw-r--r--tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr2
-rw-r--r--tests/ui/pattern/usefulness/issue-31561.rs3
-rw-r--r--tests/ui/pattern/usefulness/issue-31561.stderr16
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs38
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr58
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-errors.rs6
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-errors.stderr6
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs3
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr2
-rw-r--r--tests/ui/pin-macro/cant_access_internals.rs1
-rw-r--r--tests/ui/pin-macro/cant_access_internals.stderr2
-rw-r--r--tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs1
-rw-r--r--tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr4
-rw-r--r--tests/ui/privacy/issue-75906.stderr4
-rw-r--r--tests/ui/privacy/issue-75907.rs2
-rw-r--r--tests/ui/privacy/issue-75907.stderr8
-rw-r--r--tests/ui/privacy/privacy5.stderr96
-rw-r--r--tests/ui/privacy/suggest-making-field-public.fixed15
-rw-r--r--tests/ui/privacy/suggest-making-field-public.rs15
-rw-r--r--tests/ui/privacy/suggest-making-field-public.stderr39
-rw-r--r--tests/ui/recursion/recursive-types-are-not-uninhabited.stderr13
-rw-r--r--tests/ui/resolve/issue-42944.rs2
-rw-r--r--tests/ui/resolve/issue-42944.stderr12
-rw-r--r--tests/ui/resolve/privacy-enum-ctor.stderr24
-rw-r--r--tests/ui/resolve/privacy-struct-ctor.stderr16
-rw-r--r--tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs5
-rw-r--r--tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr5
-rw-r--r--tests/ui/suggestions/derive-trait-for-method-call.stderr45
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr44
-rw-r--r--tests/ui/suggestions/lifetimes/issue-105544.fixed45
-rw-r--r--tests/ui/suggestions/lifetimes/issue-105544.rs45
-rw-r--r--tests/ui/suggestions/lifetimes/issue-105544.stderr110
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed29
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs3
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr10
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr14
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-1.stderr10
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-2.stderr10
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-3.stderr20
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.fixed5
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.rs5
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-4.stderr17
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.fixed8
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.rs8
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.stderr37
-rw-r--r--tests/ui/traits/ignore-err-impls.rs9
-rw-r--r--tests/ui/traits/ignore-err-impls.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.rs24
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.stderr31
-rw-r--r--tests/ui/typeck/issue-57404.stderr11
-rw-r--r--tests/ui/typeck/issue-87181/empty-tuple-method.rs2
-rw-r--r--tests/ui/typeck/issue-87181/empty-tuple-method.stderr2
-rw-r--r--tests/ui/typeck/issue-87181/enum-variant.rs2
-rw-r--r--tests/ui/typeck/issue-87181/enum-variant.stderr2
-rw-r--r--tests/ui/typeck/issue-87181/tuple-method.rs2
-rw-r--r--tests/ui/typeck/issue-87181/tuple-method.stderr2
-rw-r--r--tests/ui/typeck/issue-96738.stderr2
-rw-r--r--tests/ui/uninhabited/uninhabited-irrefutable.rs4
-rw-r--r--tests/ui/uninhabited/uninhabited-irrefutable.stderr14
-rw-r--r--tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr13
-rw-r--r--tests/ui/union/union-derive-clone.mirunsafeck.stderr3
-rw-r--r--tests/ui/union/union-derive-clone.thirunsafeck.stderr3
-rw-r--r--tests/ui/where-clauses/ignore-err-clauses.rs14
-rw-r--r--tests/ui/where-clauses/ignore-err-clauses.stderr9
198 files changed, 2930 insertions, 1837 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2a88152b519..4bea3af7f3b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5034,18 +5034,18 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
 
 [[package]]
 name = "semver"
-version = "1.0.14"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.152"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
 dependencies = [
  "serde_derive",
 ]
@@ -5062,9 +5062,9 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5082,9 +5082,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
 dependencies = [
  "indexmap",
  "itoa",
@@ -5400,9 +5400,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
-version = "1.0.107"
+version = "1.0.102"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5576,7 +5576,6 @@ dependencies = [
  "lazy_static",
  "miropt-test-tools",
  "regex",
- "semver",
  "termcolor",
  "walkdir",
 ]
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index d318c15d342..f7312f6fcda 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -153,9 +153,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         (
             &ty::Dynamic(ref data_a, _, src_dyn_kind),
             &ty::Dynamic(ref data_b, _, target_dyn_kind),
-        ) => {
-            assert_eq!(src_dyn_kind, target_dyn_kind);
-
+        ) if src_dyn_kind == target_dyn_kind => {
             let old_info =
                 old_info.expect("unsized_info: missing old info for trait upcasting coercion");
             if data_a.principal_def_id() == data_b.principal_def_id() {
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index da69fc8ecf7..739963fffd1 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -187,7 +187,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("bmi2", None),
     ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
     ("ermsb", Some(sym::ermsb_target_feature)),
-    ("f16c", Some(sym::f16c_target_feature)),
+    ("f16c", None),
     ("fma", None),
     ("fxsr", None),
     ("gfni", Some(sym::avx512_target_feature)),
@@ -396,7 +396,6 @@ pub fn from_target_feature(
                 Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
                 Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
                 Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
-                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
                 Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
                 Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
                 Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index a132a8146e9..24258974bb9 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -618,7 +618,7 @@ E0791: include_str!("./error_codes/E0791.md"),
 //  E0487, // unsafe use of destructor: destructor might be called while...
 //  E0488, // lifetime of variable does not enclose its declaration
 //  E0489, // type/lifetime parameter not in scope here
-    E0490, // a value of type `..` is borrowed for too long
+//  E0490, // removed: unreachable
     E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
 //  E0526, // shuffle indices are not constant
 //  E0540, // multiple rustc_deprecated attributes
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
index 26cdf8a58f3..41f458f6c17 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
@@ -120,3 +120,7 @@ hir_analysis_self_in_impl_self =
 
 hir_analysis_linkage_type =
     invalid type for variable with `#[linkage]` attribute
+
+hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+    .label = deref recursion limit reached
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl
index c1cb07cf0df..ae0091b0373 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl
@@ -101,7 +101,6 @@ infer_subtype_2 = ...so that {$requirement ->
 infer_reborrow = ...so that reference does not outlive borrowed content
 infer_reborrow_upvar = ...so that closure can access `{$name}`
 infer_relate_object_bound = ...so that it can be closed over into an object
-infer_data_borrowed = ...so that the type `{$name}` is not borrowed for too long
 infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
 infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
     [true] ...
diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl
index aacaafeede6..a082c0b61fa 100644
--- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl
@@ -303,3 +303,64 @@ mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once a
     .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
     .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
     .moved = also moved into `{$name_moved}` here
+
+mir_build_union_pattern = cannot use unions in constant patterns
+
+mir_build_type_not_structural =
+     to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+
+mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+
+mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
+
+mir_build_float_pattern = floating-point types cannot be used in patterns
+
+mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+
+mir_build_indirect_structural_match =
+    to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+
+mir_build_nontrivial_structural_match =
+    to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+
+mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
+    .range = ... with this range
+    .note = you likely meant to write mutually exclusive ranges
+
+mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
+    .help = ensure that all variants are matched explicitly by adding the suggested match arms
+    .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
+
+mir_build_uncovered = {$count ->
+        [1] pattern `{$witness_1}`
+        [2] patterns `{$witness_1}` and `{$witness_2}`
+        [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
+        *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
+    } not covered
+
+mir_build_pattern_not_covered = refutable pattern in {$origin}
+    .pattern_ty = the matched value is of type `{$pattern_ty}`
+
+mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+
+mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+
+mir_build_res_defined_here = {$res} defined here
+
+mir_build_adt_defined_here = `{$ty}` defined here
+
+mir_build_variant_defined_here = not covered
+
+mir_build_interpreted_as_const = introduce a variable instead
+
+mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as {$article} {$res} pattern, not a new variable
+
+mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
+        [one] variant that isn't
+        *[other] variants that aren't
+    } matched
+
+mir_build_suggest_let_else = you might want to use `let else` to handle the {$count ->
+        [one] variant that isn't
+        *[other] variants that aren't
+    } matched
diff --git a/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl b/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl
index 004e0ab1896..14eb4a5502d 100644
--- a/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl
@@ -2,10 +2,6 @@ trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entri
 
 trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
 
-trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
-    .label = deref recursion limit reached
-    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
-
 trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
     .label = empty on-clause here
 
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e2f30fb89b9..fcbc5bacfcc 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -161,6 +161,8 @@ declare_features! (
     (accepted, extern_crate_self, "1.34.0", Some(56409), None),
     /// Allows access to crate names passed via `--extern` through prelude.
     (accepted, extern_prelude, "1.30.0", Some(44660), None),
+    /// Allows using F16C intrinsics from `core::arch::{x86, x86_64}`.
+    (accepted, f16c_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
     /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
     (accepted, field_init_shorthand, "1.17.0", Some(37340), None),
     /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 691c0955cad..f0bc35d06bf 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -254,7 +254,6 @@ declare_features! (
     (active, bpf_target_feature, "1.54.0", Some(44839), None),
     (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
     (active, ermsb_target_feature, "1.49.0", Some(44839), None),
-    (active, f16c_target_feature, "1.36.0", Some(44839), None),
     (active, hexagon_target_feature, "1.27.0", Some(44839), None),
     (active, mips_target_feature, "1.27.0", Some(44839), None),
     (active, movbe_target_feature, "1.34.0", Some(44839), None),
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index f64d65cc6ad..ce3682a8f2d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -1,6 +1,6 @@
 use super::IsMethodCall;
 use crate::astconv::{
-    AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
+    CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
     GenericArgCountResult, GenericArgPosition,
 };
 use crate::errors::AssocTypeBindingNotAllowed;
@@ -18,642 +18,624 @@ use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
 use rustc_span::{symbol::kw, Span};
 use smallvec::SmallVec;
 
-impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
-    /// Report an error that a generic argument did not match the generic parameter that was
-    /// expected.
-    fn generic_arg_mismatch_err(
-        tcx: TyCtxt<'_>,
-        arg: &GenericArg<'_>,
-        param: &GenericParamDef,
-        possible_ordering_error: bool,
-        help: Option<&str>,
-    ) {
-        let sess = tcx.sess;
-        let mut err = struct_span_err!(
-            sess,
-            arg.span(),
-            E0747,
-            "{} provided when a {} was expected",
-            arg.descr(),
-            param.kind.descr(),
-        );
-
-        if let GenericParamDefKind::Const { .. } = param.kind {
-            if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
-                err.help("const arguments cannot yet be inferred with `_`");
-                if sess.is_nightly_build() {
-                    err.help(
-                        "add `#![feature(generic_arg_infer)]` to the crate attributes to enable",
-                    );
-                }
+/// Report an error that a generic argument did not match the generic parameter that was
+/// expected.
+fn generic_arg_mismatch_err(
+    tcx: TyCtxt<'_>,
+    arg: &GenericArg<'_>,
+    param: &GenericParamDef,
+    possible_ordering_error: bool,
+    help: Option<&str>,
+) {
+    let sess = tcx.sess;
+    let mut err = struct_span_err!(
+        sess,
+        arg.span(),
+        E0747,
+        "{} provided when a {} was expected",
+        arg.descr(),
+        param.kind.descr(),
+    );
+
+    if let GenericParamDefKind::Const { .. } = param.kind {
+        if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
+            err.help("const arguments cannot yet be inferred with `_`");
+            if sess.is_nightly_build() {
+                err.help("add `#![feature(generic_arg_infer)]` to the crate attributes to enable");
             }
         }
+    }
 
-        let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diagnostic| {
-            let suggestions = vec![
-                (arg.span().shrink_to_lo(), String::from("{ ")),
-                (arg.span().shrink_to_hi(), String::from(" }")),
-            ];
-            err.multipart_suggestion(
-                "if this generic argument was intended as a const parameter, \
+    let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diagnostic| {
+        let suggestions = vec![
+            (arg.span().shrink_to_lo(), String::from("{ ")),
+            (arg.span().shrink_to_hi(), String::from(" }")),
+        ];
+        err.multipart_suggestion(
+            "if this generic argument was intended as a const parameter, \
                  surround it with braces",
-                suggestions,
-                Applicability::MaybeIncorrect,
-            );
-        };
-
-        // Specific suggestion set for diagnostics
-        match (arg, &param.kind) {
-            (
-                GenericArg::Type(hir::Ty {
-                    kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
-                    ..
-                }),
-                GenericParamDefKind::Const { .. },
-            ) => match path.res {
-                Res::Err => {
-                    add_braces_suggestion(arg, &mut err);
-                    err.set_primary_message(
-                        "unresolved item provided when a constant was expected",
-                    )
+            suggestions,
+            Applicability::MaybeIncorrect,
+        );
+    };
+
+    // Specific suggestion set for diagnostics
+    match (arg, &param.kind) {
+        (
+            GenericArg::Type(hir::Ty {
+                kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
+                ..
+            }),
+            GenericParamDefKind::Const { .. },
+        ) => match path.res {
+            Res::Err => {
+                add_braces_suggestion(arg, &mut err);
+                err.set_primary_message("unresolved item provided when a constant was expected")
                     .emit();
-                    return;
-                }
-                Res::Def(DefKind::TyParam, src_def_id) => {
-                    if let Some(param_local_id) = param.def_id.as_local() {
-                        let param_name = tcx.hir().ty_param_name(param_local_id);
-                        let param_type = tcx.type_of(param.def_id);
-                        if param_type.is_suggestable(tcx, false) {
-                            err.span_suggestion(
-                                tcx.def_span(src_def_id),
-                                "consider changing this type parameter to be a `const` generic",
-                                format!("const {}: {}", param_name, param_type),
-                                Applicability::MaybeIncorrect,
-                            );
-                        };
-                    }
-                }
-                _ => add_braces_suggestion(arg, &mut err),
-            },
-            (
-                GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
-                GenericParamDefKind::Const { .. },
-            ) => add_braces_suggestion(arg, &mut err),
-            (
-                GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
-                GenericParamDefKind::Const { .. },
-            ) if tcx.type_of(param.def_id) == tcx.types.usize => {
-                let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
-                if let Ok(snippet) = snippet {
-                    err.span_suggestion(
-                        arg.span(),
-                        "array type provided where a `usize` was expected, try",
-                        format!("{{ {} }}", snippet),
-                        Applicability::MaybeIncorrect,
-                    );
+                return;
+            }
+            Res::Def(DefKind::TyParam, src_def_id) => {
+                if let Some(param_local_id) = param.def_id.as_local() {
+                    let param_name = tcx.hir().ty_param_name(param_local_id);
+                    let param_type = tcx.type_of(param.def_id);
+                    if param_type.is_suggestable(tcx, false) {
+                        err.span_suggestion(
+                            tcx.def_span(src_def_id),
+                            "consider changing this type parameter to be a `const` generic",
+                            format!("const {}: {}", param_name, param_type),
+                            Applicability::MaybeIncorrect,
+                        );
+                    };
                 }
             }
-            (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
-                let body = tcx.hir().body(cnst.value.body);
-                if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
-                    body.value.kind
-                {
-                    if let Res::Def(DefKind::Fn { .. }, id) = path.res {
-                        err.help(&format!(
-                            "`{}` is a function item, not a type",
-                            tcx.item_name(id)
-                        ));
-                        err.help("function item types cannot be named directly");
-                    }
+            _ => add_braces_suggestion(arg, &mut err),
+        },
+        (
+            GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
+            GenericParamDefKind::Const { .. },
+        ) => add_braces_suggestion(arg, &mut err),
+        (
+            GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
+            GenericParamDefKind::Const { .. },
+        ) if tcx.type_of(param.def_id) == tcx.types.usize => {
+            let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
+            if let Ok(snippet) = snippet {
+                err.span_suggestion(
+                    arg.span(),
+                    "array type provided where a `usize` was expected, try",
+                    format!("{{ {} }}", snippet),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+        (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
+            let body = tcx.hir().body(cnst.value.body);
+            if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
+            {
+                if let Res::Def(DefKind::Fn { .. }, id) = path.res {
+                    err.help(&format!("`{}` is a function item, not a type", tcx.item_name(id)));
+                    err.help("function item types cannot be named directly");
                 }
             }
-            _ => {}
         }
+        _ => {}
+    }
 
-        let kind_ord = param.kind.to_ord();
-        let arg_ord = arg.to_ord();
+    let kind_ord = param.kind.to_ord();
+    let arg_ord = arg.to_ord();
 
-        // This note is only true when generic parameters are strictly ordered by their kind.
-        if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
-            let (first, last) = if kind_ord < arg_ord {
-                (param.kind.descr(), arg.descr())
-            } else {
-                (arg.descr(), param.kind.descr())
-            };
-            err.note(&format!("{} arguments must be provided before {} arguments", first, last));
-            if let Some(help) = help {
-                err.help(help);
-            }
+    // This note is only true when generic parameters are strictly ordered by their kind.
+    if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
+        let (first, last) = if kind_ord < arg_ord {
+            (param.kind.descr(), arg.descr())
+        } else {
+            (arg.descr(), param.kind.descr())
+        };
+        err.note(&format!("{} arguments must be provided before {} arguments", first, last));
+        if let Some(help) = help {
+            err.help(help);
         }
+    }
+
+    err.emit();
+}
 
-        err.emit();
+/// Creates the relevant generic argument substitutions
+/// corresponding to a set of generic parameters. This is a
+/// rather complex function. Let us try to explain the role
+/// of each of its parameters:
+///
+/// To start, we are given the `def_id` of the thing we are
+/// creating the substitutions for, and a partial set of
+/// substitutions `parent_substs`. In general, the substitutions
+/// for an item begin with substitutions for all the "parents" of
+/// that item -- e.g., for a method it might include the
+/// parameters from the impl.
+///
+/// Therefore, the method begins by walking down these parents,
+/// starting with the outermost parent and proceed inwards until
+/// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
+/// first to see if the parent's substitutions are listed in there. If so,
+/// we can append those and move on. Otherwise, it invokes the
+/// three callback functions:
+///
+/// - `args_for_def_id`: given the `DefId` `P`, supplies back the
+///   generic arguments that were given to that parent from within
+///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
+///   might refer to the trait `Foo`, and the arguments might be
+///   `[T]`. The boolean value indicates whether to infer values
+///   for arguments whose values were not explicitly provided.
+/// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
+///   instantiate a `GenericArg`.
+/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
+///   creates a suitable inference variable.
+pub fn create_substs_for_generic_args<'tcx, 'a>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    parent_substs: &[subst::GenericArg<'tcx>],
+    has_self: bool,
+    self_ty: Option<Ty<'tcx>>,
+    arg_count: &GenericArgCountResult,
+    ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
+) -> SubstsRef<'tcx> {
+    // Collect the segments of the path; we need to substitute arguments
+    // for parameters throughout the entire path (wherever there are
+    // generic parameters).
+    let mut parent_defs = tcx.generics_of(def_id);
+    let count = parent_defs.count();
+    let mut stack = vec![(def_id, parent_defs)];
+    while let Some(def_id) = parent_defs.parent {
+        parent_defs = tcx.generics_of(def_id);
+        stack.push((def_id, parent_defs));
     }
 
-    /// Creates the relevant generic argument substitutions
-    /// corresponding to a set of generic parameters. This is a
-    /// rather complex function. Let us try to explain the role
-    /// of each of its parameters:
-    ///
-    /// To start, we are given the `def_id` of the thing we are
-    /// creating the substitutions for, and a partial set of
-    /// substitutions `parent_substs`. In general, the substitutions
-    /// for an item begin with substitutions for all the "parents" of
-    /// that item -- e.g., for a method it might include the
-    /// parameters from the impl.
-    ///
-    /// Therefore, the method begins by walking down these parents,
-    /// starting with the outermost parent and proceed inwards until
-    /// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
-    /// first to see if the parent's substitutions are listed in there. If so,
-    /// we can append those and move on. Otherwise, it invokes the
-    /// three callback functions:
-    ///
-    /// - `args_for_def_id`: given the `DefId` `P`, supplies back the
-    ///   generic arguments that were given to that parent from within
-    ///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
-    ///   might refer to the trait `Foo`, and the arguments might be
-    ///   `[T]`. The boolean value indicates whether to infer values
-    ///   for arguments whose values were not explicitly provided.
-    /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
-    ///   instantiate a `GenericArg`.
-    /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
-    ///   creates a suitable inference variable.
-    pub fn create_substs_for_generic_args<'a>(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        parent_substs: &[subst::GenericArg<'tcx>],
-        has_self: bool,
-        self_ty: Option<Ty<'tcx>>,
-        arg_count: &GenericArgCountResult,
-        ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
-    ) -> SubstsRef<'tcx> {
-        // Collect the segments of the path; we need to substitute arguments
-        // for parameters throughout the entire path (wherever there are
-        // generic parameters).
-        let mut parent_defs = tcx.generics_of(def_id);
-        let count = parent_defs.count();
-        let mut stack = vec![(def_id, parent_defs)];
-        while let Some(def_id) = parent_defs.parent {
-            parent_defs = tcx.generics_of(def_id);
-            stack.push((def_id, parent_defs));
+    // We manually build up the substitution, rather than using convenience
+    // methods in `subst.rs`, so that we can iterate over the arguments and
+    // parameters in lock-step linearly, instead of trying to match each pair.
+    let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
+    // Iterate over each segment of the path.
+    while let Some((def_id, defs)) = stack.pop() {
+        let mut params = defs.params.iter().peekable();
+
+        // If we have already computed substitutions for parents, we can use those directly.
+        while let Some(&param) = params.peek() {
+            if let Some(&kind) = parent_substs.get(param.index as usize) {
+                substs.push(kind);
+                params.next();
+            } else {
+                break;
+            }
         }
 
-        // We manually build up the substitution, rather than using convenience
-        // methods in `subst.rs`, so that we can iterate over the arguments and
-        // parameters in lock-step linearly, instead of trying to match each pair.
-        let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
-        // Iterate over each segment of the path.
-        while let Some((def_id, defs)) = stack.pop() {
-            let mut params = defs.params.iter().peekable();
-
-            // If we have already computed substitutions for parents, we can use those directly.
-            while let Some(&param) = params.peek() {
-                if let Some(&kind) = parent_substs.get(param.index as usize) {
-                    substs.push(kind);
-                    params.next();
-                } else {
-                    break;
+        // `Self` is handled first, unless it's been handled in `parent_substs`.
+        if has_self {
+            if let Some(&param) = params.peek() {
+                if param.index == 0 {
+                    if let GenericParamDefKind::Type { .. } = param.kind {
+                        substs.push(
+                            self_ty
+                                .map(|ty| ty.into())
+                                .unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
+                        );
+                        params.next();
+                    }
                 }
             }
+        }
 
-            // `Self` is handled first, unless it's been handled in `parent_substs`.
-            if has_self {
-                if let Some(&param) = params.peek() {
-                    if param.index == 0 {
-                        if let GenericParamDefKind::Type { .. } = param.kind {
-                            substs.push(
-                                self_ty
-                                    .map(|ty| ty.into())
-                                    .unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
-                            );
+        // Check whether this segment takes generic arguments and the user has provided any.
+        let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
+
+        let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter());
+        let mut args = args_iter.clone().peekable();
+
+        // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
+        // If we later encounter a lifetime, we know that the arguments were provided in the
+        // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
+        // inferred, so we can use it for diagnostics later.
+        let mut force_infer_lt = None;
+
+        loop {
+            // We're going to iterate through the generic arguments that the user
+            // provided, matching them with the generic parameters we expect.
+            // Mismatches can occur as a result of elided lifetimes, or for malformed
+            // input. We try to handle both sensibly.
+            match (args.peek(), params.peek()) {
+                (Some(&arg), Some(&param)) => {
+                    match (arg, &param.kind, arg_count.explicit_late_bound) {
+                        (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
+                        | (
+                            GenericArg::Type(_) | GenericArg::Infer(_),
+                            GenericParamDefKind::Type { .. },
+                            _,
+                        )
+                        | (
+                            GenericArg::Const(_) | GenericArg::Infer(_),
+                            GenericParamDefKind::Const { .. },
+                            _,
+                        ) => {
+                            substs.push(ctx.provided_kind(param, arg));
+                            args.next();
                             params.next();
                         }
-                    }
-                }
-            }
-
-            // Check whether this segment takes generic arguments and the user has provided any.
-            let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
-
-            let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter());
-            let mut args = args_iter.clone().peekable();
-
-            // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
-            // If we later encounter a lifetime, we know that the arguments were provided in the
-            // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
-            // inferred, so we can use it for diagnostics later.
-            let mut force_infer_lt = None;
-
-            loop {
-                // We're going to iterate through the generic arguments that the user
-                // provided, matching them with the generic parameters we expect.
-                // Mismatches can occur as a result of elided lifetimes, or for malformed
-                // input. We try to handle both sensibly.
-                match (args.peek(), params.peek()) {
-                    (Some(&arg), Some(&param)) => {
-                        match (arg, &param.kind, arg_count.explicit_late_bound) {
-                            (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
-                            | (
-                                GenericArg::Type(_) | GenericArg::Infer(_),
-                                GenericParamDefKind::Type { .. },
-                                _,
-                            )
-                            | (
-                                GenericArg::Const(_) | GenericArg::Infer(_),
-                                GenericParamDefKind::Const { .. },
-                                _,
-                            ) => {
-                                substs.push(ctx.provided_kind(param, arg));
-                                args.next();
-                                params.next();
-                            }
-                            (
-                                GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
-                                GenericParamDefKind::Lifetime,
-                                _,
-                            ) => {
-                                // We expected a lifetime argument, but got a type or const
-                                // argument. That means we're inferring the lifetimes.
-                                substs.push(ctx.inferred_kind(None, param, infer_args));
-                                force_infer_lt = Some((arg, param));
-                                params.next();
-                            }
-                            (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
-                                // We've come across a lifetime when we expected something else in
-                                // the presence of explicit late bounds. This is most likely
-                                // due to the presence of the explicit bound so we're just going to
-                                // ignore it.
-                                args.next();
-                            }
-                            (_, _, _) => {
-                                // We expected one kind of parameter, but the user provided
-                                // another. This is an error. However, if we already know that
-                                // the arguments don't match up with the parameters, we won't issue
-                                // an additional error, as the user already knows what's wrong.
-                                if arg_count.correct.is_ok() {
-                                    // We're going to iterate over the parameters to sort them out, and
-                                    // show that order to the user as a possible order for the parameters
-                                    let mut param_types_present = defs
-                                        .params
-                                        .iter()
-                                        .map(|param| (param.kind.to_ord(), param.clone()))
-                                        .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
-                                    param_types_present.sort_by_key(|(ord, _)| *ord);
-                                    let (mut param_types_present, ordered_params): (
-                                        Vec<ParamKindOrd>,
-                                        Vec<GenericParamDef>,
-                                    ) = param_types_present.into_iter().unzip();
-                                    param_types_present.dedup();
-
-                                    Self::generic_arg_mismatch_err(
-                                        tcx,
-                                        arg,
-                                        param,
-                                        !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
-                                        Some(&format!(
-                                            "reorder the arguments: {}: `<{}>`",
-                                            param_types_present
-                                                .into_iter()
-                                                .map(|ord| format!("{}s", ord))
-                                                .collect::<Vec<String>>()
-                                                .join(", then "),
-                                            ordered_params
-                                                .into_iter()
-                                                .filter_map(|param| {
-                                                    if param.name == kw::SelfUpper {
-                                                        None
-                                                    } else {
-                                                        Some(param.name.to_string())
-                                                    }
-                                                })
-                                                .collect::<Vec<String>>()
-                                                .join(", ")
-                                        )),
-                                    );
-                                }
-
-                                // We've reported the error, but we want to make sure that this
-                                // problem doesn't bubble down and create additional, irrelevant
-                                // errors. In this case, we're simply going to ignore the argument
-                                // and any following arguments. The rest of the parameters will be
-                                // inferred.
-                                while args.next().is_some() {}
-                            }
+                        (
+                            GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
+                            GenericParamDefKind::Lifetime,
+                            _,
+                        ) => {
+                            // We expected a lifetime argument, but got a type or const
+                            // argument. That means we're inferring the lifetimes.
+                            substs.push(ctx.inferred_kind(None, param, infer_args));
+                            force_infer_lt = Some((arg, param));
+                            params.next();
                         }
-                    }
-
-                    (Some(&arg), None) => {
-                        // We should never be able to reach this point with well-formed input.
-                        // There are three situations in which we can encounter this issue.
-                        //
-                        //  1.  The number of arguments is incorrect. In this case, an error
-                        //      will already have been emitted, and we can ignore it.
-                        //  2.  There are late-bound lifetime parameters present, yet the
-                        //      lifetime arguments have also been explicitly specified by the
-                        //      user.
-                        //  3.  We've inferred some lifetimes, which have been provided later (i.e.
-                        //      after a type or const). We want to throw an error in this case.
-
-                        if arg_count.correct.is_ok()
-                            && arg_count.explicit_late_bound == ExplicitLateBound::No
-                        {
-                            let kind = arg.descr();
-                            assert_eq!(kind, "lifetime");
-                            let (provided_arg, param) =
-                                force_infer_lt.expect("lifetimes ought to have been inferred");
-                            Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None);
+                        (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
+                            // We've come across a lifetime when we expected something else in
+                            // the presence of explicit late bounds. This is most likely
+                            // due to the presence of the explicit bound so we're just going to
+                            // ignore it.
+                            args.next();
                         }
+                        (_, _, _) => {
+                            // We expected one kind of parameter, but the user provided
+                            // another. This is an error. However, if we already know that
+                            // the arguments don't match up with the parameters, we won't issue
+                            // an additional error, as the user already knows what's wrong.
+                            if arg_count.correct.is_ok() {
+                                // We're going to iterate over the parameters to sort them out, and
+                                // show that order to the user as a possible order for the parameters
+                                let mut param_types_present = defs
+                                    .params
+                                    .iter()
+                                    .map(|param| (param.kind.to_ord(), param.clone()))
+                                    .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
+                                param_types_present.sort_by_key(|(ord, _)| *ord);
+                                let (mut param_types_present, ordered_params): (
+                                    Vec<ParamKindOrd>,
+                                    Vec<GenericParamDef>,
+                                ) = param_types_present.into_iter().unzip();
+                                param_types_present.dedup();
+
+                                generic_arg_mismatch_err(
+                                    tcx,
+                                    arg,
+                                    param,
+                                    !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
+                                    Some(&format!(
+                                        "reorder the arguments: {}: `<{}>`",
+                                        param_types_present
+                                            .into_iter()
+                                            .map(|ord| format!("{}s", ord))
+                                            .collect::<Vec<String>>()
+                                            .join(", then "),
+                                        ordered_params
+                                            .into_iter()
+                                            .filter_map(|param| {
+                                                if param.name == kw::SelfUpper {
+                                                    None
+                                                } else {
+                                                    Some(param.name.to_string())
+                                                }
+                                            })
+                                            .collect::<Vec<String>>()
+                                            .join(", ")
+                                    )),
+                                );
+                            }
 
-                        break;
+                            // We've reported the error, but we want to make sure that this
+                            // problem doesn't bubble down and create additional, irrelevant
+                            // errors. In this case, we're simply going to ignore the argument
+                            // and any following arguments. The rest of the parameters will be
+                            // inferred.
+                            while args.next().is_some() {}
+                        }
                     }
+                }
 
-                    (None, Some(&param)) => {
-                        // If there are fewer arguments than parameters, it means
-                        // we're inferring the remaining arguments.
-                        substs.push(ctx.inferred_kind(Some(&substs), param, infer_args));
-                        params.next();
+                (Some(&arg), None) => {
+                    // We should never be able to reach this point with well-formed input.
+                    // There are three situations in which we can encounter this issue.
+                    //
+                    //  1.  The number of arguments is incorrect. In this case, an error
+                    //      will already have been emitted, and we can ignore it.
+                    //  2.  There are late-bound lifetime parameters present, yet the
+                    //      lifetime arguments have also been explicitly specified by the
+                    //      user.
+                    //  3.  We've inferred some lifetimes, which have been provided later (i.e.
+                    //      after a type or const). We want to throw an error in this case.
+
+                    if arg_count.correct.is_ok()
+                        && arg_count.explicit_late_bound == ExplicitLateBound::No
+                    {
+                        let kind = arg.descr();
+                        assert_eq!(kind, "lifetime");
+                        let (provided_arg, param) =
+                            force_infer_lt.expect("lifetimes ought to have been inferred");
+                        generic_arg_mismatch_err(tcx, provided_arg, param, false, None);
                     }
 
-                    (None, None) => break,
+                    break;
+                }
+
+                (None, Some(&param)) => {
+                    // If there are fewer arguments than parameters, it means
+                    // we're inferring the remaining arguments.
+                    substs.push(ctx.inferred_kind(Some(&substs), param, infer_args));
+                    params.next();
                 }
+
+                (None, None) => break,
             }
         }
-
-        tcx.intern_substs(&substs)
     }
 
-    /// Checks that the correct number of generic arguments have been provided.
-    /// Used specifically for function calls.
-    pub fn check_generic_arg_count_for_call(
-        tcx: TyCtxt<'_>,
-        span: Span,
-        def_id: DefId,
-        generics: &ty::Generics,
-        seg: &hir::PathSegment<'_>,
-        is_method_call: IsMethodCall,
-    ) -> GenericArgCountResult {
-        let empty_args = hir::GenericArgs::none();
-        let gen_args = seg.args.unwrap_or(&empty_args);
-        let gen_pos = if is_method_call == IsMethodCall::Yes {
-            GenericArgPosition::MethodCall
+    tcx.intern_substs(&substs)
+}
+
+/// Checks that the correct number of generic arguments have been provided.
+/// Used specifically for function calls.
+pub fn check_generic_arg_count_for_call(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    def_id: DefId,
+    generics: &ty::Generics,
+    seg: &hir::PathSegment<'_>,
+    is_method_call: IsMethodCall,
+) -> GenericArgCountResult {
+    let empty_args = hir::GenericArgs::none();
+    let gen_args = seg.args.unwrap_or(&empty_args);
+    let gen_pos = if is_method_call == IsMethodCall::Yes {
+        GenericArgPosition::MethodCall
+    } else {
+        GenericArgPosition::Value
+    };
+    let has_self = generics.parent.is_none() && generics.has_self;
+
+    check_generic_arg_count(
+        tcx,
+        span,
+        def_id,
+        seg,
+        generics,
+        gen_args,
+        gen_pos,
+        has_self,
+        seg.infer_args,
+    )
+}
+
+/// Checks that the correct number of generic arguments have been provided.
+/// This is used both for datatypes and function calls.
+#[instrument(skip(tcx, gen_pos), level = "debug")]
+pub(crate) fn check_generic_arg_count(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    def_id: DefId,
+    seg: &hir::PathSegment<'_>,
+    gen_params: &ty::Generics,
+    gen_args: &hir::GenericArgs<'_>,
+    gen_pos: GenericArgPosition,
+    has_self: bool,
+    infer_args: bool,
+) -> GenericArgCountResult {
+    let default_counts = gen_params.own_defaults();
+    let param_counts = gen_params.own_counts();
+
+    // Subtracting from param count to ensure type params synthesized from `impl Trait`
+    // cannot be explicitly specified.
+    let synth_type_param_count = gen_params
+        .params
+        .iter()
+        .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
+        .count();
+    let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
+    let infer_lifetimes =
+        (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
+
+    if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
+            prohibit_assoc_ty_binding(tcx, b.span);
+        }
+
+    let explicit_late_bound =
+        prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos);
+
+    let mut invalid_args = vec![];
+
+    let mut check_lifetime_args = |min_expected_args: usize,
+                                   max_expected_args: usize,
+                                   provided_args: usize,
+                                   late_bounds_ignore: bool| {
+        if (min_expected_args..=max_expected_args).contains(&provided_args) {
+            return Ok(());
+        }
+
+        if late_bounds_ignore {
+            return Ok(());
+        }
+
+        if provided_args > max_expected_args {
+            invalid_args.extend(
+                gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()),
+            );
+        };
+
+        let gen_args_info = if provided_args > min_expected_args {
+            invalid_args.extend(
+                gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()),
+            );
+            let num_redundant_args = provided_args - min_expected_args;
+            GenericArgsInfo::ExcessLifetimes { num_redundant_args }
         } else {
-            GenericArgPosition::Value
+            let num_missing_args = min_expected_args - provided_args;
+            GenericArgsInfo::MissingLifetimes { num_missing_args }
         };
-        let has_self = generics.parent.is_none() && generics.has_self;
 
-        Self::check_generic_arg_count(
+        let reported = WrongNumberOfGenericArgs::new(
             tcx,
-            span,
-            def_id,
+            gen_args_info,
             seg,
-            generics,
+            gen_params,
+            has_self as usize,
             gen_args,
-            gen_pos,
-            has_self,
-            seg.infer_args,
+            def_id,
         )
-    }
-
-    /// Checks that the correct number of generic arguments have been provided.
-    /// This is used both for datatypes and function calls.
-    #[instrument(skip(tcx, gen_pos), level = "debug")]
-    pub(crate) fn check_generic_arg_count(
-        tcx: TyCtxt<'_>,
-        span: Span,
-        def_id: DefId,
-        seg: &hir::PathSegment<'_>,
-        gen_params: &ty::Generics,
-        gen_args: &hir::GenericArgs<'_>,
-        gen_pos: GenericArgPosition,
-        has_self: bool,
-        infer_args: bool,
-    ) -> GenericArgCountResult {
-        let default_counts = gen_params.own_defaults();
-        let param_counts = gen_params.own_counts();
-
-        // Subtracting from param count to ensure type params synthesized from `impl Trait`
-        // cannot be explicitly specified.
-        let synth_type_param_count = gen_params
-            .params
-            .iter()
-            .filter(|param| {
-                matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
-            })
-            .count();
-        let named_type_param_count =
-            param_counts.types - has_self as usize - synth_type_param_count;
-        let infer_lifetimes =
-            (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
-
-        if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
-            Self::prohibit_assoc_ty_binding(tcx, b.span);
+        .diagnostic()
+        .emit();
+
+        Err(reported)
+    };
+
+    let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
+    let max_expected_lifetime_args = param_counts.lifetimes;
+    let num_provided_lifetime_args = gen_args.num_lifetime_params();
+
+    let lifetimes_correct = check_lifetime_args(
+        min_expected_lifetime_args,
+        max_expected_lifetime_args,
+        num_provided_lifetime_args,
+        explicit_late_bound == ExplicitLateBound::Yes,
+    );
+
+    let mut check_types_and_consts = |expected_min,
+                                      expected_max,
+                                      expected_max_with_synth,
+                                      provided,
+                                      params_offset,
+                                      args_offset| {
+        debug!(
+            ?expected_min,
+            ?expected_max,
+            ?provided,
+            ?params_offset,
+            ?args_offset,
+            "check_types_and_consts"
+        );
+        if (expected_min..=expected_max).contains(&provided) {
+            return Ok(());
         }
 
-        let explicit_late_bound =
-            Self::prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos);
-
-        let mut invalid_args = vec![];
+        let num_default_params = expected_max - expected_min;
 
-        let mut check_lifetime_args =
-            |min_expected_args: usize,
-             max_expected_args: usize,
-             provided_args: usize,
-             late_bounds_ignore: bool| {
-                if (min_expected_args..=max_expected_args).contains(&provided_args) {
-                    return Ok(());
-                }
-
-                if late_bounds_ignore {
-                    return Ok(());
-                }
+        let gen_args_info = if provided > expected_max {
+            invalid_args.extend(
+                gen_args.args[args_offset + expected_max..args_offset + provided]
+                    .iter()
+                    .map(|arg| arg.span()),
+            );
+            let num_redundant_args = provided - expected_max;
 
-                if provided_args > max_expected_args {
-                    invalid_args.extend(
-                        gen_args.args[max_expected_args..provided_args]
-                            .iter()
-                            .map(|arg| arg.span()),
-                    );
-                };
-
-                let gen_args_info = if provided_args > min_expected_args {
-                    invalid_args.extend(
-                        gen_args.args[min_expected_args..provided_args]
-                            .iter()
-                            .map(|arg| arg.span()),
-                    );
-                    let num_redundant_args = provided_args - min_expected_args;
-                    GenericArgsInfo::ExcessLifetimes { num_redundant_args }
-                } else {
-                    let num_missing_args = min_expected_args - provided_args;
-                    GenericArgsInfo::MissingLifetimes { num_missing_args }
-                };
-
-                let reported = WrongNumberOfGenericArgs::new(
-                    tcx,
-                    gen_args_info,
-                    seg,
-                    gen_params,
-                    has_self as usize,
-                    gen_args,
-                    def_id,
-                )
-                .diagnostic()
-                .emit();
-
-                Err(reported)
-            };
-
-        let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
-        let max_expected_lifetime_args = param_counts.lifetimes;
-        let num_provided_lifetime_args = gen_args.num_lifetime_params();
-
-        let lifetimes_correct = check_lifetime_args(
-            min_expected_lifetime_args,
-            max_expected_lifetime_args,
-            num_provided_lifetime_args,
-            explicit_late_bound == ExplicitLateBound::Yes,
-        );
+            // Provide extra note if synthetic arguments like `impl Trait` are specified.
+            let synth_provided = provided <= expected_max_with_synth;
 
-        let mut check_types_and_consts = |expected_min,
-                                          expected_max,
-                                          expected_max_with_synth,
-                                          provided,
-                                          params_offset,
-                                          args_offset| {
-            debug!(
-                ?expected_min,
-                ?expected_max,
-                ?provided,
-                ?params_offset,
-                ?args_offset,
-                "check_types_and_consts"
-            );
-            if (expected_min..=expected_max).contains(&provided) {
-                return Ok(());
+            GenericArgsInfo::ExcessTypesOrConsts {
+                num_redundant_args,
+                num_default_params,
+                args_offset,
+                synth_provided,
             }
+        } else {
+            let num_missing_args = expected_max - provided;
 
-            let num_default_params = expected_max - expected_min;
-
-            let gen_args_info = if provided > expected_max {
-                invalid_args.extend(
-                    gen_args.args[args_offset + expected_max..args_offset + provided]
-                        .iter()
-                        .map(|arg| arg.span()),
-                );
-                let num_redundant_args = provided - expected_max;
+            GenericArgsInfo::MissingTypesOrConsts {
+                num_missing_args,
+                num_default_params,
+                args_offset,
+            }
+        };
 
-                // Provide extra note if synthetic arguments like `impl Trait` are specified.
-                let synth_provided = provided <= expected_max_with_synth;
+        debug!(?gen_args_info);
 
-                GenericArgsInfo::ExcessTypesOrConsts {
-                    num_redundant_args,
-                    num_default_params,
-                    args_offset,
-                    synth_provided,
-                }
-            } else {
-                let num_missing_args = expected_max - provided;
+        let reported = WrongNumberOfGenericArgs::new(
+            tcx,
+            gen_args_info,
+            seg,
+            gen_params,
+            params_offset,
+            gen_args,
+            def_id,
+        )
+        .diagnostic()
+        .emit_unless(gen_args.has_err());
 
-                GenericArgsInfo::MissingTypesOrConsts {
-                    num_missing_args,
-                    num_default_params,
-                    args_offset,
-                }
-            };
-
-            debug!(?gen_args_info);
-
-            let reported = WrongNumberOfGenericArgs::new(
-                tcx,
-                gen_args_info,
-                seg,
-                gen_params,
-                params_offset,
-                gen_args,
-                def_id,
-            )
-            .diagnostic()
-            .emit_unless(gen_args.has_err());
-
-            Err(reported)
-        };
+        Err(reported)
+    };
 
-        let args_correct = {
-            let expected_min = if infer_args {
-                0
-            } else {
-                param_counts.consts + named_type_param_count
-                    - default_counts.types
-                    - default_counts.consts
-            };
-            debug!(?expected_min);
-            debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params());
-
-            check_types_and_consts(
-                expected_min,
-                param_counts.consts + named_type_param_count,
-                param_counts.consts + named_type_param_count + synth_type_param_count,
-                gen_args.num_generic_params(),
-                param_counts.lifetimes + has_self as usize,
-                gen_args.num_lifetime_params(),
-            )
+    let args_correct = {
+        let expected_min = if infer_args {
+            0
+        } else {
+            param_counts.consts + named_type_param_count
+                - default_counts.types
+                - default_counts.consts
         };
+        debug!(?expected_min);
+        debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params());
+
+        check_types_and_consts(
+            expected_min,
+            param_counts.consts + named_type_param_count,
+            param_counts.consts + named_type_param_count + synth_type_param_count,
+            gen_args.num_generic_params(),
+            param_counts.lifetimes + has_self as usize,
+            gen_args.num_lifetime_params(),
+        )
+    };
 
-        GenericArgCountResult {
-            explicit_late_bound,
-            correct: lifetimes_correct.and(args_correct).map_err(|reported| {
-                GenericArgCountMismatch { reported: Some(reported), invalid_args }
-            }),
-        }
+    GenericArgCountResult {
+        explicit_late_bound,
+        correct: lifetimes_correct
+            .and(args_correct)
+            .map_err(|reported| GenericArgCountMismatch { reported: Some(reported), invalid_args }),
     }
+}
 
-    /// Emits an error regarding forbidden type binding associations
-    pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
-        tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
-    }
+/// Emits an error regarding forbidden type binding associations
+pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
+    tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
+}
 
-    /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
-    /// are present. This is used both for datatypes and function calls.
-    pub(crate) fn prohibit_explicit_late_bound_lifetimes(
-        tcx: TyCtxt<'_>,
-        def: &ty::Generics,
-        args: &hir::GenericArgs<'_>,
-        position: GenericArgPosition,
-    ) -> ExplicitLateBound {
-        let param_counts = def.own_counts();
-        let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params();
-
-        if infer_lifetimes {
-            return ExplicitLateBound::No;
-        }
+/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
+/// are present. This is used both for datatypes and function calls.
+pub(crate) fn prohibit_explicit_late_bound_lifetimes(
+    tcx: TyCtxt<'_>,
+    def: &ty::Generics,
+    args: &hir::GenericArgs<'_>,
+    position: GenericArgPosition,
+) -> ExplicitLateBound {
+    let param_counts = def.own_counts();
+    let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params();
+
+    if infer_lifetimes {
+        return ExplicitLateBound::No;
+    }
 
-        if let Some(span_late) = def.has_late_bound_regions {
-            let msg = "cannot specify lifetime arguments explicitly \
+    if let Some(span_late) = def.has_late_bound_regions {
+        let msg = "cannot specify lifetime arguments explicitly \
                        if late bound lifetime parameters are present";
-            let note = "the late bound lifetime parameter is introduced here";
-            let span = args.args[0].span();
-
-            if position == GenericArgPosition::Value
-                && args.num_lifetime_params() != param_counts.lifetimes
-            {
-                let mut err = tcx.sess.struct_span_err(span, msg);
-                err.span_note(span_late, note);
-                err.emit();
-            } else {
-                let mut multispan = MultiSpan::from_span(span);
-                multispan.push_span_label(span_late, note);
-                tcx.struct_span_lint_hir(
-                    LATE_BOUND_LIFETIME_ARGUMENTS,
-                    args.args[0].hir_id(),
-                    multispan,
-                    msg,
-                    |lint| lint,
-                );
-            }
-
-            ExplicitLateBound::Yes
+        let note = "the late bound lifetime parameter is introduced here";
+        let span = args.args[0].span();
+
+        if position == GenericArgPosition::Value
+            && args.num_lifetime_params() != param_counts.lifetimes
+        {
+            let mut err = tcx.sess.struct_span_err(span, msg);
+            err.span_note(span_late, note);
+            err.emit();
         } else {
-            ExplicitLateBound::No
+            let mut multispan = MultiSpan::from_span(span);
+            multispan.push_span_label(span_late, note);
+            tcx.struct_span_lint_hir(
+                LATE_BOUND_LIFETIME_ARGUMENTS,
+                args.args[0].hir_id(),
+                multispan,
+                msg,
+                |lint| lint,
+            );
         }
+
+        ExplicitLateBound::Yes
+    } else {
+        ExplicitLateBound::No
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 5a7957be318..9fa0e6e8eaa 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -3,8 +3,11 @@
 //! instance of `AstConv`.
 
 mod errors;
-mod generics;
+pub mod generics;
 
+use crate::astconv::generics::{
+    check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
+};
 use crate::bounds::Bounds;
 use crate::collect::HirPlaceholderCollector;
 use crate::errors::{
@@ -120,6 +123,13 @@ pub trait AstConv<'tcx> {
     fn set_tainted_by_errors(&self, e: ErrorGuaranteed);
 
     fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
+
+    fn astconv(&self) -> &dyn AstConv<'tcx>
+    where
+        Self: Sized,
+    {
+        self
+    }
 }
 
 #[derive(Debug)]
@@ -279,7 +289,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
-            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+            prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
 
         substs
@@ -349,7 +359,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             assert!(self_ty.is_none());
         }
 
-        let arg_count = Self::check_generic_arg_count(
+        let arg_count = check_generic_arg_count(
             tcx,
             span,
             def_id,
@@ -524,7 +534,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             inferred_params: vec![],
             infer_args,
         };
-        let substs = Self::create_substs_for_generic_args(
+        let substs = create_substs_for_generic_args(
             tcx,
             def_id,
             parent_substs,
@@ -610,7 +620,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         );
 
         if let Some(b) = item_segment.args().bindings.first() {
-            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+            prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
 
         args
@@ -804,7 +814,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             constness,
         );
         if let Some(b) = trait_segment.args().bindings.first() {
-            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+            prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
         self.tcx().mk_trait_ref(trait_def_id, substs)
     }
@@ -2301,7 +2311,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         for segment in segments {
             // Only emit the first error to avoid overloading the user with error messages.
             if let Some(b) = segment.args().bindings.first() {
-                Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+                prohibit_assoc_ty_binding(self.tcx(), b.span);
                 return true;
             }
         }
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index e988c77a064..730560cc686 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -178,6 +178,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         self.state.obligations
     }
 
+    pub fn current_obligations(&self) -> Vec<traits::PredicateObligation<'tcx>> {
+        self.state.obligations.clone()
+    }
+
     pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
         &self.state.steps
     }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index e9baab59453..d1f4dbc8d84 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,4 +1,6 @@
+use crate::autoderef::Autoderef;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
+
 use hir::def::DefKind;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@@ -22,7 +24,6 @@ use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index b7f259668a1..cd745ee8cab 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -351,7 +351,7 @@ impl<'tcx> ItemCtxt<'tcx> {
     }
 
     pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
-        <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_ty)
+        self.astconv().ast_ty_to_ty(ast_ty)
     }
 
     pub fn hir_id(&self) -> hir::HirId {
@@ -413,8 +413,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
         if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
-            let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
-                self,
+            let item_substs = self.astconv().create_substs_for_associated_item(
                 span,
                 item_def_id,
                 item_segment,
@@ -1112,8 +1111,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                 tcx.hir().get_parent(hir_id)
                 && i.of_trait.is_some()
             {
-                <dyn AstConv<'_>>::ty_of_fn(
-                    &icx,
+                icx.astconv().ty_of_fn(
                     hir_id,
                     sig.header.unsafety,
                     sig.header.abi,
@@ -1130,15 +1128,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
             generics,
             ..
-        }) => <dyn AstConv<'_>>::ty_of_fn(
-            &icx,
-            hir_id,
-            header.unsafety,
-            header.abi,
-            decl,
-            Some(generics),
-            None,
-        ),
+        }) => {
+            icx.astconv().ty_of_fn(hir_id, header.unsafety, header.abi, decl, Some(generics), None)
+        }
 
         ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
             let abi = tcx.hir().get_foreign_abi(hir_id);
@@ -1244,8 +1236,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
 
             ty::Binder::dummy(fn_sig)
         }
-        None => <dyn AstConv<'_>>::ty_of_fn(
-            icx,
+        None => icx.astconv().ty_of_fn(
             hir_id,
             sig.header.unsafety,
             sig.header.abi,
@@ -1354,8 +1345,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     match item.kind {
         hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
             let selfty = tcx.type_of(def_id);
-            <dyn AstConv<'_>>::instantiate_mono_trait_ref(
-                &icx,
+            icx.astconv().instantiate_mono_trait_ref(
                 ast_trait_ref,
                 selfty,
                 check_impl_constness(tcx, impl_.constness, ast_trait_ref),
@@ -1485,15 +1475,8 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
         hir::Unsafety::Unsafe
     };
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let fty = <dyn AstConv<'_>>::ty_of_fn(
-        &ItemCtxt::new(tcx, def_id),
-        hir_id,
-        unsafety,
-        abi,
-        decl,
-        None,
-        None,
-    );
+    let fty =
+        ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
 
     // Feature gate SIMD types in FFI, since I am not sure that the
     // ABIs are handled at all correctly. -huonw
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 093e9560ccd..62eef710ba4 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -26,9 +26,9 @@ fn associated_type_bounds<'tcx>(
     );
 
     let icx = ItemCtxt::new(tcx, assoc_item_def_id);
-    let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
+    let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
     // Associated types are implicitly sized unless a `?Sized` bound is found
-    <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span);
+    icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
 
     let trait_def_id = tcx.parent(assoc_item_def_id);
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
@@ -70,9 +70,9 @@ fn opaque_type_bounds<'tcx>(
         };
 
         let icx = ItemCtxt::new(tcx, opaque_def_id);
-        let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
+        let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
         // Opaque types are implicitly sized unless a `?Sized` bound is found
-        <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span);
+        icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
         debug!(?bounds);
 
         tcx.arena.alloc_from_iter(bounds.predicates())
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 18fc43ce15c..23425355684 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -162,8 +162,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
                 let mut bounds = Bounds::default();
                 // Params are implicitly sized unless a `?Sized` bound is found
-                <dyn AstConv<'_>>::add_implicitly_sized(
-                    &icx,
+                icx.astconv().add_implicitly_sized(
                     &mut bounds,
                     param_ty,
                     &[],
@@ -211,22 +210,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 }
 
                 let mut bounds = Bounds::default();
-                <dyn AstConv<'_>>::add_bounds(
-                    &icx,
-                    ty,
-                    bound_pred.bounds.iter(),
-                    &mut bounds,
-                    bound_vars,
-                );
+                icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
                 predicates.extend(bounds.predicates());
             }
 
             hir::WherePredicate::RegionPredicate(region_pred) => {
-                let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, &region_pred.lifetime, None);
+                let r1 = icx.astconv().ast_region_to_region(&region_pred.lifetime, None);
                 predicates.extend(region_pred.bounds.iter().map(|bound| {
                     let (r2, span) = match bound {
                         hir::GenericBound::Outlives(lt) => {
-                            (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span)
+                            (icx.astconv().ast_region_to_region(lt, None), lt.ident.span)
                         }
                         _ => bug!(),
                     };
@@ -279,7 +272,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
         debug!(?lifetimes);
         for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
             let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
-            let orig_region = <dyn AstConv<'_>>::ast_region_to_region(&icx, &arg, None);
+            let orig_region = icx.astconv().ast_region_to_region(&arg, None);
             if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
                 // Only early-bound regions can point to the original generic parameter.
                 continue;
@@ -527,14 +520,9 @@ pub(super) fn super_predicates_that_define_assoc_type(
         // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
         let self_param_ty = tcx.types.self_param;
         let superbounds1 = if let Some(assoc_name) = assoc_name {
-            <dyn AstConv<'_>>::compute_bounds_that_match_assoc_type(
-                &icx,
-                self_param_ty,
-                bounds,
-                assoc_name,
-            )
+            icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
         } else {
-            <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
+            icx.astconv().compute_bounds(self_param_ty, bounds)
         };
 
         let superbounds1 = superbounds1.predicates();
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index d383fcacb3a..04f5f3f6276 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[help]
+#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
+pub struct AutoDerefReachedRecursionLimit<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub ty: Ty<'a>,
+    pub suggested_limit: rustc_session::Limit,
+    pub crate_name: Symbol,
+}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 2058832d5fd..ddc5b766881 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -84,6 +84,7 @@ extern crate rustc_middle;
 pub mod check;
 
 pub mod astconv;
+pub mod autoderef;
 mod bounds;
 mod check_unused;
 mod coherence;
@@ -544,7 +545,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
     // scope.  This is derived from the enclosing item-like thing.
     let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
-    <dyn AstConv<'_>>::ast_ty_to_ty(&item_cx, hir_ty)
+    item_cx.astconv().ast_ty_to_ty(hir_ty)
 }
 
 pub fn hir_trait_to_predicates<'tcx>(
@@ -558,8 +559,7 @@ pub fn hir_trait_to_predicates<'tcx>(
     let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
     let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
     let mut bounds = Bounds::default();
-    let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
-        &item_cx,
+    let _ = &item_cx.astconv().instantiate_poly_trait_ref(
         hir_trait,
         DUMMY_SP,
         ty::BoundConstness::NotConst,
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 41b52a4c4a9..7873257c4e3 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -2,11 +2,11 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, PlaceOp};
 
+use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
-use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
 
 use std::iter;
 
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 3b664363d23..8d417290407 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -8,6 +8,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed,
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir_analysis::autoderef::Autoderef;
 use rustc_infer::{
     infer,
     traits::{self, Obligation},
@@ -25,7 +26,6 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_target::spec::abi;
-use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::DefIdOrName;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index a0e086bc261..7e1c0faa453 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1807,7 +1807,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
             // Get the return type.
             && let hir::TyKind::OpaqueDef(..) = ty.kind
         {
-            let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
+            let ty = fcx.astconv().ast_ty_to_ty( ty);
             // Get the `impl Trait`'s `DefId`.
             if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
                 // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
@@ -1866,7 +1866,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
     fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
         if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
             && let hir::FnRetTy::Return(ty) = fn_decl.output
-            && let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty)
+            && let ty = fcx.astconv().ast_ty_to_ty( ty)
             && let ty::Dynamic(..) = ty.kind()
         {
             return true;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 47c4b7d7431..8570715b41e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -10,6 +10,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, GenericArg, Node, QPath};
+use rustc_hir_analysis::astconv::generics::{
+    check_generic_arg_count_for_call, create_substs_for_generic_args,
+};
 use rustc_hir_analysis::astconv::{
     AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
     GenericArgCountResult, IsMethodCall, PathSeg,
@@ -374,7 +377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
-        let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
+        let t = self.astconv().ast_ty_to_ty(ast_t);
         self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
         self.handle_raw_ty(ast_t.span, t)
     }
@@ -777,7 +780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // to be object-safe.
                 // We manually call `register_wf_obligation` in the success path
                 // below.
-                let ty = <dyn AstConv<'_>>::ast_ty_to_ty_in_path(self, qself);
+                let ty = self.astconv().ast_ty_to_ty_in_path(qself);
                 (self.handle_raw_ty(span, ty), qself, segment)
             }
             QPath::LangItem(..) => {
@@ -975,8 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let path_segs = match res {
             Res::Local(_) | Res::SelfCtor(_) => vec![],
-            Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
-                self,
+            Res::Def(kind, def_id) => self.astconv().def_ids_for_value_path_segments(
                 segments,
                 self_ty.map(|ty| ty.raw),
                 kind,
@@ -1027,8 +1029,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // errors if type parameters are provided in an inappropriate place.
 
         let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect();
-        let generics_has_err = <dyn AstConv<'_>>::prohibit_generics(
-            self,
+        let generics_has_err = self.astconv().prohibit_generics(
             segments.iter().enumerate().filter_map(|(index, seg)| {
                 if !generic_segs.contains(&index) || is_alias_variant_ctor {
                     Some(seg)
@@ -1069,7 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // parameter internally, but we don't allow users to specify the
             // parameter's value explicitly, so we have to do some error-
             // checking here.
-            let arg_count = <dyn AstConv<'_>>::check_generic_arg_count_for_call(
+            let arg_count = check_generic_arg_count_for_call(
                 tcx,
                 span,
                 def_id,
@@ -1177,7 +1178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                        <dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
+                        self.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
                         self.fcx.to_ty(ty).raw.into()
@@ -1235,7 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let substs_raw = self_ctor_substs.unwrap_or_else(|| {
-            <dyn AstConv<'_>>::create_substs_for_generic_args(
+            create_substs_for_generic_args(
                 tcx,
                 def_id,
                 &[],
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 5075d9b893b..b9e13fd2009 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1664,15 +1664,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match *qpath {
             QPath::Resolved(ref maybe_qself, ref path) => {
                 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
-                let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
+                let ty = self.astconv().res_to_ty(self_ty, path, true);
                 (path.res, self.handle_raw_ty(path_span, ty))
             }
             QPath::TypeRelative(ref qself, ref segment) => {
                 let ty = self.to_ty(qself);
 
-                let result = <dyn AstConv<'_>>::associated_path_to_ty(
-                    self, hir_id, path_span, ty.raw, qself, segment, true,
-                );
+                let result = self
+                    .astconv()
+                    .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
                 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
                 let ty = self.handle_raw_ty(path_span, ty);
                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 6347b9a69a0..428fde642bc 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
-use rustc_span::{self, Span};
+use rustc_span::{self, Span, DUMMY_SP};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
 
 use std::cell::{Cell, RefCell};
@@ -175,6 +175,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     fn_sig
                 })
             }),
+            autoderef_steps: Box::new(|ty| {
+                let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
+                let mut steps = vec![];
+                while let Some((ty, _)) = autoderef.next() {
+                    steps.push((ty, autoderef.current_obligations()));
+                }
+                steps
+            }),
         }
     }
 
@@ -286,8 +294,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
             poly_trait_ref,
         );
 
-        let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
-            self,
+        let item_substs = self.astconv().create_substs_for_associated_item(
             span,
             item_def_id,
             item_segment,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 91498265259..005bd164065 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -5,7 +5,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
 use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
 use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
     Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
@@ -417,10 +417,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
             return true;
         } else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
-            && let ty::FnDef(def_id, ..) = &found.kind()
-            && let Some(sp) = self.tcx.hir().span_if_local(*def_id)
+            && let ty::FnDef(def_id, ..) = *found.kind()
+            && let Some(sp) = self.tcx.hir().span_if_local(def_id)
         {
-            err.span_label(sp, format!("{found} defined here"));
+            let name = self.tcx.item_name(def_id);
+            let kind = self.tcx.def_kind(def_id);
+            if let DefKind::Ctor(of, CtorKind::Fn) = kind {
+                err.span_label(sp, format!("`{name}` defines {} constructor here, which should be called", match of {
+                    CtorOf::Struct => "a struct",
+                    CtorOf::Variant => "an enum variant",
+                }));
+            } else {
+                let descr = kind.descr(def_id);
+                err.span_label(sp, format!("{descr} `{name}` defined here"));
+            }
             return true;
         } else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
             return true;
@@ -783,7 +793,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // are not, the expectation must have been caused by something else.
                 debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
                 let span = ty.span;
-                let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
+                let ty = self.astconv().ast_ty_to_ty(ty);
                 debug!("suggest_missing_return_type: return type {:?}", ty);
                 debug!("suggest_missing_return_type: expected type {:?}", ty);
                 let bound_vars = self.tcx.late_bound_vars(fn_id);
@@ -854,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ..
                 }) => {
                     // FIXME: Maybe these calls to `ast_ty_to_ty` can be removed (and the ones below)
-                    let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, bounded_ty);
+                    let ty = self.astconv().ast_ty_to_ty(bounded_ty);
                     Some((ty, bounds))
                 }
                 _ => None,
@@ -892,7 +902,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let all_bounds_str = all_matching_bounds_strs.join(" + ");
 
         let ty_param_used_in_fn_params = fn_parameters.iter().any(|param| {
-                let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, param);
+                let ty = self.astconv().ast_ty_to_ty( param);
                 matches!(ty.kind(), ty::Param(fn_param_ty_param) if expected_ty_as_param == fn_param_ty_param)
             });
 
@@ -946,7 +956,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if let hir::FnRetTy::Return(ty) = fn_decl.output {
-            let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
+            let ty = self.astconv().ast_ty_to_ty(ty);
             let bound_vars = self.tcx.late_bound_vars(fn_id);
             let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
             let ty = match self.tcx.asyncness(fn_id.owner) {
@@ -1339,7 +1349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 hir::Path { segments: [segment], .. },
             ))
             | hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
-                let self_ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
+                let self_ty = self.astconv().ast_ty_to_ty(ty);
                 if let Ok(pick) = self.probe_for_name(
                     Mode::Path,
                     Ident::new(capitalized_name, segment.ident.span),
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 69929589541..7ddf9eaa4d8 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -205,7 +205,7 @@ fn typeck_with_fallback<'tcx>(
 
         if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
             let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
-                <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
+                fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
             } else {
                 tcx.fn_sig(def_id)
             };
@@ -220,7 +220,7 @@ fn typeck_with_fallback<'tcx>(
         } else {
             let expected_type = body_ty
                 .and_then(|ty| match ty.kind {
-                    hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
+                    hir::TyKind::Infer => Some(fcx.astconv().ast_ty_to_ty(ty)),
                     _ => None,
                 })
                 .unwrap_or_else(|| match tcx.hir().get(id) {
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 7d2ba1fd09d..4a33a791e1b 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -4,6 +4,9 @@ use crate::{callee, FnCtxt};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
+use rustc_hir_analysis::astconv::generics::{
+    check_generic_arg_count_for_call, create_substs_for_generic_args,
+};
 use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
 use rustc_infer::infer::{self, InferOk};
 use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
@@ -331,7 +334,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // variables.
         let generics = self.tcx.generics_of(pick.item.def_id);
 
-        let arg_count_correct = <dyn AstConv<'_>>::check_generic_arg_count_for_call(
+        let arg_count_correct = check_generic_arg_count_for_call(
             self.tcx,
             self.span,
             pick.item.def_id,
@@ -369,8 +372,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             ) -> subst::GenericArg<'tcx> {
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                        <dyn AstConv<'_>>::ast_region_to_region(self.cfcx.fcx, lt, Some(param))
-                            .into()
+                        self.cfcx.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
                         self.cfcx.to_ty(ty).raw.into()
@@ -399,7 +401,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             }
         }
 
-        let substs = <dyn AstConv<'_>>::create_substs_for_generic_args(
+        let substs = create_substs_for_generic_args(
             self.tcx,
             pick.item.def_id,
             parent_substs,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 5d8383170f0..dd827777df9 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
+use rustc_hir_analysis::autoderef::{self, Autoderef};
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -29,7 +30,6 @@ use rustc_span::lev_distance::{
 };
 use rustc_span::symbol::sym;
 use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
-use rustc_trait_selection::autoderef::{self, Autoderef};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
 use rustc_trait_selection::traits::query::method_autoderef::{
@@ -1556,7 +1556,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
                     // Convert the bounds into obligations.
                     let impl_obligations = traits::predicates_for_generics(
-                        |_, _| cause.clone(),
+                        |_idx, span| {
+                            let misc = traits::ObligationCause::misc(span, self.body_id);
+                            let parent_trait_pred = ty::Binder::dummy(ty::TraitPredicate {
+                                trait_ref: ty::TraitRef::from_method(self.tcx, impl_def_id, substs),
+                                constness: ty::BoundConstness::NotConst,
+                                polarity: ty::ImplPolarity::Positive,
+                            });
+                            misc.derived_cause(parent_trait_pred, |derived| {
+                                traits::ImplDerivedObligation(Box::new(
+                                    traits::ImplDerivedObligationCause {
+                                        derived,
+                                        impl_def_id,
+                                        span,
+                                    },
+                                ))
+                            })
+                        },
                         self.param_env,
                         impl_bounds,
                     );
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 62e80659486..8166eb82990 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -101,6 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
     }
 
+    #[instrument(level = "debug", skip(self))]
     pub fn report_method_error(
         &self,
         span: Span,
@@ -586,22 +587,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // Find all the requirements that come from a local `impl` block.
             let mut skip_list: FxHashSet<_> = Default::default();
-            let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
-            for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
+            let mut spanned_predicates = FxHashMap::default();
+            for (p, parent_p, impl_def_id, cause) in unsatisfied_predicates
                 .iter()
                 .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
                 .filter_map(|(p, parent, c)| match c.code() {
-                    ObligationCauseCode::ImplDerivedObligation(data) => {
-                        Some((&data.derived, p, parent, data.impl_def_id, data))
+                    ObligationCauseCode::ImplDerivedObligation(data)
+                        if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
+                    {
+                        Some((p, parent, data.impl_def_id, data))
                     }
                     _ => None,
                 })
             {
-                let parent_trait_ref = data.parent_trait_pred;
-                let path = parent_trait_ref.print_modifiers_and_trait_path();
-                let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
-                let unsatisfied_msg = "unsatisfied trait bound introduced here";
-                let derive_msg = "unsatisfied trait bound introduced in this `derive` macro";
                 match self.tcx.hir().get_if_local(impl_def_id) {
                     // Unmet obligation comes from a `derive` macro, point at it once to
                     // avoid multiple span labels pointing at the same place.
@@ -617,10 +615,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ) =>
                     {
                         let span = self_ty.span.ctxt().outer_expn_data().call_site;
-                        let mut spans: MultiSpan = span.into();
-                        spans.push_span_label(span, derive_msg);
-                        let entry = spanned_predicates.entry(spans);
-                        entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                        let entry = spanned_predicates.entry(span);
+                        let entry = entry.or_insert_with(|| {
+                            (FxHashSet::default(), FxHashSet::default(), Vec::new())
+                        });
+                        entry.0.insert(span);
+                        entry.1.insert((
+                            span,
+                            "unsatisfied trait bound introduced in this `derive` macro",
+                        ));
+                        entry.2.push(p);
+                        skip_list.insert(p);
                     }
 
                     // Unmet obligation coming from an `impl`.
@@ -647,8 +652,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 };
                                 err.span_suggestion_verbose(
                                     sp,
-                                    "consider relaxing the type parameter's implicit \
-                                     `Sized` bound",
+                                    "consider relaxing the type parameter's implicit `Sized` bound",
                                     sugg,
                                     Applicability::MachineApplicable,
                                 );
@@ -659,25 +663,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             let _ = format_pred(*pred);
                         }
                         skip_list.insert(p);
-                        let mut spans = if cause.span != *item_span {
-                            let mut spans: MultiSpan = cause.span.into();
-                            spans.push_span_label(cause.span, unsatisfied_msg);
-                            spans
+                        let entry = spanned_predicates.entry(self_ty.span);
+                        let entry = entry.or_insert_with(|| {
+                            (FxHashSet::default(), FxHashSet::default(), Vec::new())
+                        });
+                        entry.2.push(p);
+                        if cause.span != *item_span {
+                            entry.0.insert(cause.span);
+                            entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
                         } else {
-                            let mut spans = Vec::with_capacity(2);
                             if let Some(trait_ref) = of_trait {
-                                spans.push(trait_ref.path.span);
+                                entry.0.insert(trait_ref.path.span);
                             }
-                            spans.push(self_ty.span);
-                            spans.into()
+                            entry.0.insert(self_ty.span);
                         };
                         if let Some(trait_ref) = of_trait {
-                            spans.push_span_label(trait_ref.path.span, "");
+                            entry.1.insert((trait_ref.path.span, ""));
                         }
-                        spans.push_span_label(self_ty.span, "");
-
-                        let entry = spanned_predicates.entry(spans);
-                        entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                        entry.1.insert((self_ty.span, ""));
                     }
                     Some(Node::Item(hir::Item {
                         kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
@@ -694,11 +697,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
-            spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
-            for (span, (_path, _self_ty, preds)) in spanned_predicates {
-                let mut preds: Vec<_> = preds
-                    .into_iter()
-                    .filter_map(|pred| format_pred(*pred))
+            spanned_predicates.sort_by_key(|(span, _)| *span);
+            for (_, (primary_spans, span_labels, predicates)) in spanned_predicates {
+                let mut preds: Vec<_> = predicates
+                    .iter()
+                    .filter_map(|pred| format_pred(**pred))
                     .map(|(p, _)| format!("`{}`", p))
                     .collect();
                 preds.sort();
@@ -708,6 +711,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
                 };
+                let mut span: MultiSpan = primary_spans.into_iter().collect::<Vec<_>>().into();
+                for (sp, label) in span_labels {
+                    span.push_span_label(sp, label);
+                }
                 err.span_note(span, &msg);
                 unsatisfied_bounds = true;
             }
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index a0f048fc09b..ae0df5aa8f1 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -3,6 +3,7 @@ use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp};
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir_analysis::autoderef::Autoderef;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast};
@@ -10,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
-use rustc_trait_selection::autoderef::Autoderef;
 use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 66db1a2f928..080ae6b9466 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -55,6 +55,7 @@ use crate::infer::ExpectedFound;
 use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
+    PredicateObligation,
 };
 
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -91,8 +92,12 @@ pub mod nice_region_error;
 pub struct TypeErrCtxt<'a, 'tcx> {
     pub infcx: &'a InferCtxt<'tcx>,
     pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
-    pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
     pub fallback_has_occurred: bool,
+
+    pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
+
+    pub autoderef_steps:
+        Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
 }
 
 impl TypeErrCtxt<'_, '_> {
@@ -2144,18 +2149,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         // suggest adding an explicit lifetime bound to it.
         let generics = self.tcx.generics_of(generic_param_scope);
         // type_param_span is (span, has_bounds)
+        let mut is_synthetic = false;
+        let mut ast_generics = None;
         let type_param_span = match bound_kind {
             GenericKind::Param(ref param) => {
                 // Account for the case where `param` corresponds to `Self`,
                 // which doesn't have the expected type argument.
                 if !(generics.has_self && param.index == 0) {
                     let type_param = generics.type_param(param, self.tcx);
+                    is_synthetic = type_param.kind.is_synthetic();
                     type_param.def_id.as_local().map(|def_id| {
                         // Get the `hir::Param` to verify whether it already has any bounds.
                         // We do this to avoid suggesting code that ends up as `T: 'a'b`,
                         // instead we suggest `T: 'a + 'b` in that case.
                         let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
-                        let ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id);
+                        ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id);
                         let bounds =
                             ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id));
                         // `sp` only covers `T`, change it so that it covers
@@ -2187,11 +2195,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 .unwrap_or("'lt".to_string())
         };
 
-        let add_lt_sugg = generics
-            .params
-            .first()
-            .and_then(|param| param.def_id.as_local())
-            .map(|def_id| (self.tcx.def_span(def_id).shrink_to_lo(), format!("{}, ", new_lt)));
+        let mut add_lt_suggs: Vec<Option<_>> = vec![];
+        if is_synthetic {
+            if let Some(ast_generics) = ast_generics {
+                let named_lifetime_param_exist = ast_generics.params.iter().any(|p| {
+                    matches!(
+                        p.kind,
+                        hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
+                    )
+                });
+                if named_lifetime_param_exist && let [param, ..] = ast_generics.params
+                {
+                    add_lt_suggs.push(Some((
+                        self.tcx.def_span(param.def_id).shrink_to_lo(),
+                        format!("{new_lt}, "),
+                    )));
+                } else {
+                    add_lt_suggs
+                        .push(Some((ast_generics.span.shrink_to_hi(), format!("<{new_lt}>"))));
+                }
+            }
+        } else {
+            if let [param, ..] = &generics.params[..] && let Some(def_id) = param.def_id.as_local()
+            {
+                add_lt_suggs
+                    .push(Some((self.tcx.def_span(def_id).shrink_to_lo(), format!("{new_lt}, "))));
+            }
+        }
+
+        if let Some(ast_generics) = ast_generics {
+            for p in ast_generics.params {
+                if p.is_elided_lifetime() {
+                    if self
+                        .tcx
+                        .sess
+                        .source_map()
+                        .span_to_prev_source(p.span.shrink_to_hi())
+                        .ok()
+                        .map_or(false, |s| *s.as_bytes().last().unwrap() == b'&')
+                    {
+                        add_lt_suggs
+                            .push(Some(
+                                (
+                                    p.span.shrink_to_hi(),
+                                    if let Ok(snip) = self.tcx.sess.source_map().span_to_next_source(p.span)
+                                        && snip.starts_with(' ')
+                                    {
+                                        format!("{new_lt}")
+                                    } else {
+                                        format!("{new_lt} ")
+                                    }
+                                )
+                            ));
+                    } else {
+                        add_lt_suggs.push(Some((p.span.shrink_to_hi(), format!("<{new_lt}>"))));
+                    }
+                }
+            }
+        }
 
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
@@ -2215,20 +2276,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             );
         }
 
-        fn binding_suggestion<S: fmt::Display>(
+        fn binding_suggestion<'tcx, S: fmt::Display>(
             err: &mut Diagnostic,
             type_param_span: Option<(Span, bool)>,
-            bound_kind: GenericKind<'_>,
+            bound_kind: GenericKind<'tcx>,
             sub: S,
-            add_lt_sugg: Option<(Span, String)>,
+            add_lt_suggs: Vec<Option<(Span, String)>>,
         ) {
             let msg = "consider adding an explicit lifetime bound";
             if let Some((sp, has_lifetimes)) = type_param_span {
                 let suggestion =
                     if has_lifetimes { format!(" + {}", sub) } else { format!(": {}", sub) };
                 let mut suggestions = vec![(sp, suggestion)];
-                if let Some(add_lt_sugg) = add_lt_sugg {
-                    suggestions.push(add_lt_sugg);
+                for add_lt_sugg in add_lt_suggs {
+                    if let Some(add_lt_sugg) = add_lt_sugg {
+                        suggestions.push(add_lt_sugg);
+                    }
                 }
                 err.multipart_suggestion_verbose(
                     format!("{msg}..."),
@@ -2252,9 +2315,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     };
                     let mut sugg =
                         vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {}", new_lt))];
-                    if let Some(lt) = add_lt_sugg.clone() {
-                        sugg.push(lt);
-                        sugg.rotate_right(1);
+                    for add_lt_sugg in add_lt_suggs.clone() {
+                        if let Some(lt) = add_lt_sugg {
+                            sugg.push(lt);
+                            sugg.rotate_right(1);
+                        }
                     }
                     // `MaybeIncorrect` due to issue #41966.
                     err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
@@ -2358,7 +2423,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 // for the bound is not suitable for suggestions when `-Zverbose` is set because it
                 // uses `Debug` output, so we handle it specially here so that suggestions are
                 // always correct.
-                binding_suggestion(&mut err, type_param_span, bound_kind, name, None);
+                binding_suggestion(&mut err, type_param_span, bound_kind, name, vec![]);
                 err
             }
 
@@ -2371,7 +2436,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     "{} may not live long enough",
                     labeled_user_string
                 );
-                binding_suggestion(&mut err, type_param_span, bound_kind, "'static", None);
+                binding_suggestion(&mut err, type_param_span, bound_kind, "'static", vec![]);
                 err
             }
 
@@ -2410,7 +2475,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 type_param_span,
                                 bound_kind,
                                 new_lt,
-                                add_lt_sugg,
+                                add_lt_suggs,
                             );
                         }
                     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 7bb79d7bda8..7504ed094a3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -29,15 +29,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
                     .add_to_diagnostic(err);
             }
-            infer::DataBorrowed(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_data_borrowed,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
             infer::ReferenceOutlivesReferent(ty, span) => {
                 RegionOriginNote::WithName {
                     span,
@@ -227,32 +218,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 );
                 err
             }
-            infer::DataBorrowed(ty, span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0490,
-                    "a value of type `{}` is borrowed for too long",
-                    self.ty_to_string(ty)
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "the type is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but the borrow lasts for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
             infer::ReferenceOutlivesReferent(ty, span) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index da2c6fbc05f..897545046c3 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -702,26 +702,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     // Obtain the spans for all the places that can
                     // influence the constraints on this value for
                     // richer diagnostics in `static_impl_trait`.
-                    let influences: Vec<Span> = self
-                        .data
-                        .constraints
-                        .iter()
-                        .filter_map(|(constraint, origin)| match (constraint, origin) {
-                            (
-                                Constraint::VarSubVar(_, sup),
-                                SubregionOrigin::DataBorrowed(_, sp),
-                            ) if sup == &node_vid => Some(*sp),
-                            _ => None,
-                        })
-                        .collect();
-
-                    self.collect_error_for_expanding_node(
-                        graph,
-                        &mut dup_vec,
-                        node_vid,
-                        errors,
-                        influences,
-                    );
+
+                    self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
                 }
             }
         }
@@ -775,7 +757,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
         node_idx: RegionVid,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
-        influences: Vec<Span>,
     ) {
         // Errors in expanding nodes result from a lower-bound that is
         // not contained by an upper-bound.
@@ -830,7 +811,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                         lower_bound.region,
                         upper_bound.origin.clone(),
                         upper_bound.region,
-                        influences,
+                        vec![],
                     ));
                     return;
                 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 6bef3f000a5..4acd0d0edfe 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -410,9 +410,6 @@ pub enum SubregionOrigin<'tcx> {
     /// Creating a pointer `b` to contents of another reference
     Reborrow(Span),
 
-    /// Data with type `Ty<'tcx>` was borrowed
-    DataBorrowed(Ty<'tcx>, Span),
-
     /// (&'a &'b T) where a >= b
     ReferenceOutlivesReferent(Ty<'tcx>, Span),
 
@@ -688,6 +685,10 @@ impl<'tcx> InferCtxt<'tcx> {
             typeck_results: None,
             fallback_has_occurred: false,
             normalize_fn_sig: Box::new(|fn_sig| fn_sig),
+            autoderef_steps: Box::new(|ty| {
+                debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
+                vec![(ty, vec![])]
+            }),
         }
     }
 
@@ -1974,7 +1975,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
             RelateParamBound(a, ..) => a,
             RelateRegionParamBound(a) => a,
             Reborrow(a) => a,
-            DataBorrowed(_, a) => a,
             ReferenceOutlivesReferent(_, a) => a,
             CompareImplItemObligation { span, .. } => span,
             AscribeUserTypeProvePredicate(span) => span,
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index 7da6ab71309..03e6d2149e9 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -28,8 +28,8 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
   for (size_t i = 0; i < FilenamesLen; i++) {
     FilenameRefs.push_back(std::string(Filenames[i]));
   }
-  auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter(
-    makeArrayRef(FilenameRefs));
+  auto FilenamesWriter =
+      coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs));
   RawRustStringOstream OS(BufferOut);
   FilenamesWriter.write(OS);
 }
@@ -45,15 +45,16 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   // Convert from FFI representation to LLVM representation.
   SmallVector<coverage::CounterMappingRegion, 0> MappingRegions;
   MappingRegions.reserve(NumMappingRegions);
-  for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) {
+  for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>(
+           RustMappingRegions, NumMappingRegions)) {
     MappingRegions.emplace_back(
         Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID,
         Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
         Region.Kind);
   }
   auto CoverageMappingWriter = coverage::CoverageMappingWriter(
-      makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
-      makeArrayRef(Expressions, NumExpressions),
+      ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
+      ArrayRef<coverage::CounterExpression>(Expressions, NumExpressions),
       MappingRegions);
   RawRustStringOstream OS(BufferOut);
   CoverageMappingWriter.write(OS);
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 279b6991854..8f94e8a4ab2 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -257,7 +257,7 @@ template<typename T> static inline void AddAttributes(T *t, unsigned Index,
   PALNew = PAL.addAttributes(t->getContext(), Index, B);
 #else
   AttrBuilder B(t->getContext());
-  for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
+  for (LLVMAttributeRef Attr : ArrayRef<LLVMAttributeRef>(Attrs, AttrsLen))
     B.addAttribute(unwrap(Attr));
   PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
 #endif
@@ -1064,7 +1064,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
     LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
     const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) {
   return wrap(Builder->createEnumerator(StringRef(Name, NameLen),
-      APSInt(APInt(SizeInBits, makeArrayRef(Value, 2)), IsUnsigned)));
+      APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
@@ -1477,7 +1477,7 @@ extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
                                                            LLVMValueRef *Inputs,
                                                            unsigned NumInputs) {
-  return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
+  return new OperandBundleDef(Name, ArrayRef<Value*>(unwrap(Inputs), NumInputs));
 }
 
 extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
@@ -1491,8 +1491,8 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVM
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
   return wrap(unwrap(B)->CreateCall(
-      FTy, Callee, makeArrayRef(unwrap(Args), NumArgs),
-      makeArrayRef(*OpBundles, NumOpBundles)));
+      FTy, Callee, ArrayRef<Value*>(unwrap(Args), NumArgs),
+      ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles)));
 }
 
 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
@@ -1537,8 +1537,8 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
   return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
-                                      makeArrayRef(unwrap(Args), NumArgs),
-                                      makeArrayRef(*OpBundles, NumOpBundles),
+                                      ArrayRef<Value*>(unwrap(Args), NumArgs),
+                                      ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles),
                                       Name));
 }
 
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 82f6812026a..e405462bbb8 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -382,10 +382,26 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                     return Ok(quote! { #diag.subdiagnostic(#binding); });
                 }
             }
-            (Meta::List(_), "subdiagnostic") => {
-                throw_invalid_attr!(attr, &meta, |diag| {
-                    diag.help("`subdiagnostic` does not support nested attributes")
-                })
+            (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
+                if nested.len() == 1
+                    && let Some(NestedMeta::Meta(Meta::Path(path))) = nested.first()
+                    && path.is_ident("eager") {
+                        let handler = match &self.parent.kind {
+                            DiagnosticDeriveKind::Diagnostic { handler } => handler,
+                            DiagnosticDeriveKind::LintDiagnostic => {
+                                throw_invalid_attr!(attr, &meta, |diag| {
+                                    diag.help("eager subdiagnostics are not supported on lints")
+                                })
+                            }
+                        };
+                        return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+                } else {
+                    throw_invalid_attr!(attr, &meta, |diag| {
+                        diag.help(
+                            "`eager` is the only supported nested attribute for `subdiagnostic`",
+                        )
+                    })
+                }
             }
             _ => (),
         }
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index ac916bb6068..bb3722fe156 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -1,5 +1,6 @@
 #![feature(allow_internal_unstable)]
 #![feature(if_let_guard)]
+#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index ac903010c8d..5f320708c84 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -9,6 +9,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::RangeEnd;
@@ -575,6 +576,12 @@ impl<'tcx> Pat<'tcx> {
     }
 }
 
+impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        format!("{}", self).into_diagnostic_arg()
+    }
+}
+
 #[derive(Clone, Debug, HashStable)]
 pub struct Ascription<'tcx> {
     pub annotation: CanonicalUserTypeAnnotation<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index cd147d7e558..b9c5a4e0d0d 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -89,7 +89,9 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
                 Err(TypeError::Sorts(relate::expected_found(self, a, b)))
             }
 
-            (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(self.tcx().ty_error()),
+            (&ty::Error(guar), _) | (_, &ty::Error(guar)) => {
+                Ok(self.tcx().ty_error_with_guaranteed(guar))
+            }
 
             _ => relate::super_relate_tys(self, a, b),
         }
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 50554cf9a82..5d394f71f0d 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -2,10 +2,10 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::diagnostics::suggest_constraining_type_param;
 use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
-use hir::def::DefKind;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, Diagnostic, MultiSpan};
 use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind};
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{BytePos, Span};
@@ -319,7 +319,11 @@ impl<'tcx> Ty<'tcx> {
                     .into()
                 }
             }
-            ty::FnDef(..) => "fn item".into(),
+            ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
+                DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
+                DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
+                _ => "fn item".into(),
+            },
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
                 format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
@@ -366,7 +370,11 @@ impl<'tcx> Ty<'tcx> {
                 _ => "reference",
             }
             .into(),
-            ty::FnDef(..) => "fn item".into(),
+            ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
+                DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
+                DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
+                _ => "fn item".into(),
+            },
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(..) => "trait object".into(),
             ty::Closure(..) => "closure".into(),
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index c49e75d68ad..a91e8de5f21 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -283,6 +283,8 @@ pub trait PrettyPrinter<'tcx>:
     /// This is typically the case for all non-`'_` regions.
     fn should_print_region(&self, region: ty::Region<'tcx>) -> bool;
 
+    fn reset_type_limit(&mut self) {}
+
     // Defaults (should not be overridden):
 
     /// If possible, this returns a global path resolving to `def_id` that is visible
@@ -1981,6 +1983,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
     }
 
+    fn reset_type_limit(&mut self) {
+        self.printed_type_count = 0;
+    }
+
     fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<Symbol> {
         self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
     }
@@ -2722,11 +2728,15 @@ define_print_and_forward_display! {
     }
 
     ty::SubtypePredicate<'tcx> {
-        p!(print(self.a), " <: ", print(self.b))
+        p!(print(self.a), " <: ");
+        cx.reset_type_limit();
+        p!(print(self.b))
     }
 
     ty::CoercePredicate<'tcx> {
-        p!(print(self.a), " -> ", print(self.b))
+        p!(print(self.a), " -> ");
+        cx.reset_type_limit();
+        p!(print(self.b))
     }
 
     ty::TraitPredicate<'tcx> {
@@ -2738,7 +2748,9 @@ define_print_and_forward_display! {
     }
 
     ty::ProjectionPredicate<'tcx> {
-        p!(print(self.projection_ty), " == ", print(self.term))
+        p!(print(self.projection_ty), " == ");
+        cx.reset_type_limit();
+        p!(print(self.term))
     }
 
     ty::Term<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 4d34ca3d66b..65fd8d9753d 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -414,7 +414,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             bug!("bound types encountered in super_relate_tys")
         }
 
-        (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(tcx.ty_error()),
+        (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)),
 
         (&ty::Never, _)
         | (&ty::Char, _)
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 233eecbd5b4..06523b0a1de 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,9 +1,13 @@
+use crate::thir::pattern::deconstruct_pat::DeconstructedPat;
 use crate::thir::pattern::MatchCheckCtxt;
 use rustc_errors::Handler;
 use rustc_errors::{
-    error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
+    error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+    IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
 };
+use rustc_hir::def::Res;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_middle::thir::Pat;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::{symbol::Ident, Span};
 
@@ -624,3 +628,223 @@ pub enum MultipleMutBorrowOccurence {
         name_moved: Ident,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(mir_build_union_pattern)]
+pub struct UnionPattern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_type_not_structural)]
+pub struct TypeNotStructural<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub non_sm_ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_invalid_pattern)]
+pub struct InvalidPattern<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub non_sm_ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_unsized_pattern)]
+pub struct UnsizedPattern<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub non_sm_ty: Ty<'tcx>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_float_pattern)]
+pub struct FloatPattern;
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_pointer_pattern)]
+pub struct PointerPattern;
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_indirect_structural_match)]
+pub struct IndirectStructuralMatch<'tcx> {
+    pub non_sm_ty: Ty<'tcx>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_nontrivial_structural_match)]
+pub struct NontrivialStructuralMatch<'tcx> {
+    pub non_sm_ty: Ty<'tcx>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_overlapping_range_endpoints)]
+#[note]
+pub struct OverlappingRangeEndpoints<'tcx> {
+    #[label(range)]
+    pub range: Span,
+    #[subdiagnostic]
+    pub overlap: Vec<Overlap<'tcx>>,
+}
+
+pub struct Overlap<'tcx> {
+    pub span: Span,
+    pub range: Pat<'tcx>,
+}
+
+impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        let Overlap { span, range } = self;
+
+        // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
+        // does not support `#[subdiagnostic(eager)]`...
+        let message = format!("this range overlaps on `{range}`...");
+        diag.span_label(span, message);
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_non_exhaustive_omitted_pattern)]
+#[help]
+#[note]
+pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
+    pub scrut_ty: Ty<'tcx>,
+    #[subdiagnostic]
+    pub uncovered: Uncovered<'tcx>,
+}
+
+#[derive(Subdiagnostic)]
+#[label(mir_build_uncovered)]
+pub(crate) struct Uncovered<'tcx> {
+    #[primary_span]
+    span: Span,
+    count: usize,
+    witness_1: Pat<'tcx>,
+    witness_2: Pat<'tcx>,
+    witness_3: Pat<'tcx>,
+    remainder: usize,
+}
+
+impl<'tcx> Uncovered<'tcx> {
+    pub fn new<'p>(
+        span: Span,
+        cx: &MatchCheckCtxt<'p, 'tcx>,
+        witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
+    ) -> Self {
+        let witness_1 = witnesses.get(0).unwrap().to_pat(cx);
+        Self {
+            span,
+            count: witnesses.len(),
+            // Substitute dummy values if witnesses is smaller than 3. These will never be read.
+            witness_2: witnesses.get(1).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
+            witness_3: witnesses.get(2).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
+            witness_1,
+            remainder: witnesses.len().saturating_sub(3),
+        }
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_pattern_not_covered, code = "E0005")]
+pub(crate) struct PatternNotCovered<'s, 'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub origin: &'s str,
+    #[subdiagnostic]
+    pub uncovered: Uncovered<'tcx>,
+    #[subdiagnostic]
+    pub inform: Option<Inform>,
+    #[subdiagnostic]
+    pub interpreted_as_const: Option<InterpretedAsConst>,
+    #[subdiagnostic]
+    pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
+    #[note(pattern_ty)]
+    pub _p: (),
+    pub pattern_ty: Ty<'tcx>,
+    #[subdiagnostic]
+    pub let_suggestion: Option<SuggestLet>,
+    #[subdiagnostic]
+    pub res_defined_here: Option<ResDefinedHere>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(mir_build_inform_irrefutable)]
+#[note(mir_build_more_information)]
+pub struct Inform;
+
+pub struct AdtDefinedHere<'tcx> {
+    pub adt_def_span: Span,
+    pub ty: Ty<'tcx>,
+    pub variants: Vec<Variant>,
+}
+
+pub struct Variant {
+    pub span: Span,
+}
+
+impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        diag.set_arg("ty", self.ty);
+        let mut spans = MultiSpan::from(self.adt_def_span);
+
+        for Variant { span } in self.variants {
+            spans.push_span_label(span, rustc_errors::fluent::mir_build_variant_defined_here);
+        }
+
+        diag.span_note(spans, rustc_errors::fluent::mir_build_adt_defined_here);
+    }
+}
+
+#[derive(Subdiagnostic)]
+#[label(mir_build_res_defined_here)]
+pub struct ResDefinedHere {
+    #[primary_span]
+    pub def_span: Span,
+    pub res: Res,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    mir_build_interpreted_as_const,
+    code = "{variable}_var",
+    applicability = "maybe-incorrect"
+)]
+#[label(mir_build_confused)]
+pub struct InterpretedAsConst {
+    #[primary_span]
+    pub span: Span,
+    pub article: &'static str,
+    pub variable: String,
+    pub res: Res,
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestLet {
+    #[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
+    If {
+        #[suggestion_part(code = "if ")]
+        start_span: Span,
+        #[suggestion_part(code = " {{ todo!() }}")]
+        semi_span: Span,
+        count: usize,
+    },
+    #[suggestion(
+        mir_build_suggest_let_else,
+        code = " else {{ todo!() }}",
+        applicability = "has-placeholders"
+    )]
+    Else {
+        #[primary_span]
+        end_span: Span,
+        count: usize,
+    },
+}
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 2b05e92fdcf..fb7ae6f1d24 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -10,6 +10,7 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(once_cell)]
+#![feature(try_blocks)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index e7ee0d9e908..e13c0662ef8 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -9,8 +9,7 @@ use crate::errors::*;
 use rustc_arena::TypedArena;
 use rustc_ast::Mutability;
 use rustc_errors::{
-    pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan,
+    struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::*;
@@ -378,8 +377,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
 
         let pattern = self.lower_pattern(&mut cx, pat, &mut false);
         let pattern_ty = pattern.ty();
-        let arms = vec![MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false }];
-        let report = compute_match_usefulness(&cx, &arms, pat.hir_id, pattern_ty);
+        let arm = MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false };
+        let report = compute_match_usefulness(&cx, &[arm], pat.hir_id, pattern_ty);
 
         // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
         // only care about exhaustiveness here.
@@ -390,145 +389,73 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             return;
         }
 
-        let joined_patterns = joined_uncovered_patterns(&cx, &witnesses);
-
-        let mut bindings = vec![];
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            pat.span,
-            E0005,
-            "refutable pattern in {}: {} not covered",
-            origin,
-            joined_patterns
-        );
-        let suggest_if_let = match &pat.kind {
-            hir::PatKind::Path(hir::QPath::Resolved(None, path))
-                if path.segments.len() == 1 && path.segments[0].args.is_none() =>
+        let (inform, interpreted_as_const, res_defined_here,let_suggestion) =
+            if let hir::PatKind::Path(hir::QPath::Resolved(
+                None,
+                hir::Path {
+                    segments: &[hir::PathSegment { args: None, res, ident, .. }],
+                    ..
+                },
+            )) = &pat.kind
             {
-                const_not_var(&mut err, cx.tcx, pat, path);
-                false
-            }
-            _ => {
-                pat.walk(&mut |pat: &hir::Pat<'_>| {
-                    match pat.kind {
-                        hir::PatKind::Binding(_, _, ident, _) => {
-                            bindings.push(ident);
+                (
+                    None,
+                    Some(InterpretedAsConst {
+                        span: pat.span,
+                        article: res.article(),
+                        variable: ident.to_string().to_lowercase(),
+                        res,
+                    }),
+                    try {
+                        ResDefinedHere {
+                            def_span: cx.tcx.hir().res_span(res)?,
+                            res,
                         }
-                        _ => {}
+                    },
+                    None,
+                )
+            } else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) {
+                let mut bindings = vec![];
+                pat.walk_always(&mut |pat: &hir::Pat<'_>| {
+                    if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
+                        bindings.push(ident);
                     }
-                    true
                 });
-
-                err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns));
-                true
-            }
-        };
-
-        if let (Some(span), true) = (sp, suggest_if_let) {
-            err.note(
-                "`let` bindings require an \"irrefutable pattern\", like a `struct` or \
-                 an `enum` with only one variant",
-            );
-            if self.tcx.sess.source_map().is_span_accessible(span) {
                 let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
                 let start_span = span.shrink_to_lo();
                 let end_span = semi_span.shrink_to_lo();
-                err.multipart_suggestion(
-                    &format!(
-                        "you might want to use `if let` to ignore the variant{} that {} matched",
-                        pluralize!(witnesses.len()),
-                        match witnesses.len() {
-                            1 => "isn't",
-                            _ => "aren't",
-                        },
-                    ),
-                    vec![
-                        match &bindings[..] {
-                            [] => (start_span, "if ".to_string()),
-                            [binding] => (start_span, format!("let {} = if ", binding)),
-                            bindings => (
-                                start_span,
-                                format!(
-                                    "let ({}) = if ",
-                                    bindings
-                                        .iter()
-                                        .map(|ident| ident.to_string())
-                                        .collect::<Vec<_>>()
-                                        .join(", ")
-                                ),
-                            ),
-                        },
-                        match &bindings[..] {
-                            [] => (semi_span, " { todo!() }".to_string()),
-                            [binding] => {
-                                (end_span, format!(" {{ {} }} else {{ todo!() }}", binding))
-                            }
-                            bindings => (
-                                end_span,
-                                format!(
-                                    " {{ ({}) }} else {{ todo!() }}",
-                                    bindings
-                                        .iter()
-                                        .map(|ident| ident.to_string())
-                                        .collect::<Vec<_>>()
-                                        .join(", ")
-                                ),
-                            ),
-                        },
-                    ],
-                    Applicability::HasPlaceholders,
-                );
-                if !bindings.is_empty() {
-                    err.span_suggestion_verbose(
-                        semi_span.shrink_to_lo(),
-                        &format!(
-                            "alternatively, you might want to use \
-                             let else to handle the variant{} that {} matched",
-                            pluralize!(witnesses.len()),
-                            match witnesses.len() {
-                                1 => "isn't",
-                                _ => "aren't",
-                            },
-                        ),
-                        " else { todo!() }",
-                        Applicability::HasPlaceholders,
-                    );
-                }
-            }
-            err.note(
-                "for more information, visit \
-                 https://doc.rust-lang.org/book/ch18-02-refutability.html",
-            );
-        }
+                let count = witnesses.len();
 
-        adt_defined_here(&cx, &mut err, pattern_ty, &witnesses);
-        err.note(&format!("the matched value is of type `{}`", pattern_ty));
-        err.emit();
-    }
-}
+                let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
+                (sp.map(|_|Inform), None, None, Some(let_suggestion))
+            } else{
+                (sp.map(|_|Inform), None, None,  None)
+            };
 
-/// A path pattern was interpreted as a constant, not a new variable.
-/// This caused an irrefutable match failure in e.g. `let`.
-fn const_not_var(err: &mut Diagnostic, tcx: TyCtxt<'_>, pat: &Pat<'_>, path: &hir::Path<'_>) {
-    let descr = path.res.descr();
-    err.span_label(
-        pat.span,
-        format!("interpreted as {} {} pattern, not a new variable", path.res.article(), descr,),
-    );
+        let adt_defined_here = try {
+            let ty = pattern_ty.peel_refs();
+            let ty::Adt(def, _) = ty.kind() else { None? };
+            let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span;
+            let mut variants = vec![];
 
-    err.span_suggestion(
-        pat.span,
-        "introduce a variable instead",
-        format!("{}_var", path.segments[0].ident).to_lowercase(),
-        // Cannot use `MachineApplicable` as it's not really *always* correct
-        // because there may be such an identifier in scope or the user maybe
-        // really wanted to match against the constant. This is quite unlikely however.
-        Applicability::MaybeIncorrect,
-    );
+            for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) {
+                variants.push(Variant { span });
+            }
+            AdtDefinedHere { adt_def_span, ty, variants }
+        };
 
-    if let Some(span) = tcx.hir().res_span(path.res) {
-        err.span_label(span, format!("{} defined here", descr));
+        self.tcx.sess.emit_err(PatternNotCovered {
+            span: pat.span,
+            origin,
+            uncovered: Uncovered::new(pat.span, &cx, witnesses),
+            inform,
+            interpreted_as_const,
+            _p: (),
+            pattern_ty,
+            let_suggestion,
+            res_defined_here,
+            adt_defined_here,
+        });
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 6470efab2e9..7f3519945c3 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -1,11 +1,9 @@
-use rustc_errors::DelayDm;
 use rustc_hir as hir;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::mir::{self, Field};
 use rustc_middle::thir::{FieldPat, Pat, PatKind};
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::Span;
 use rustc_trait_selection::traits::predicate_for_trait_def;
@@ -15,6 +13,10 @@ use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
 use std::cell::Cell;
 
 use super::PatCtxt;
+use crate::errors::{
+    FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
+    PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
+};
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// Converts an evaluated constant to a pattern (if possible).
@@ -105,47 +107,6 @@ impl<'tcx> ConstToPat<'tcx> {
         self.infcx.tcx
     }
 
-    fn adt_derive_msg(&self, adt_def: AdtDef<'tcx>) -> String {
-        let path = self.tcx().def_path_str(adt_def.did());
-        format!(
-            "to use a constant of type `{}` in a pattern, \
-            `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-            path, path,
-        )
-    }
-
-    fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
-        traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
-            with_no_trimmed_paths!(match non_sm_ty.kind() {
-                ty::Adt(adt, _) => self.adt_derive_msg(*adt),
-                ty::Dynamic(..) => {
-                    "trait objects cannot be used in patterns".to_string()
-                }
-                ty::Alias(ty::Opaque, ..) => {
-                    "opaque types cannot be used in patterns".to_string()
-                }
-                ty::Closure(..) => {
-                    "closures cannot be used in patterns".to_string()
-                }
-                ty::Generator(..) | ty::GeneratorWitness(..) => {
-                    "generators cannot be used in patterns".to_string()
-                }
-                ty::Float(..) => {
-                    "floating-point numbers cannot be used in patterns".to_string()
-                }
-                ty::FnPtr(..) => {
-                    "function pointers cannot be used in patterns".to_string()
-                }
-                ty::RawPtr(..) => {
-                    "raw pointers cannot be used in patterns".to_string()
-                }
-                _ => {
-                    bug!("use of a value of `{non_sm_ty}` inside a pattern")
-                }
-            })
-        })
-    }
-
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
         ty.is_structural_eq_shallow(self.infcx.tcx)
     }
@@ -176,7 +137,8 @@ impl<'tcx> ConstToPat<'tcx> {
             // If we were able to successfully convert the const to some pat,
             // double-check that all types in the const implement `Structural`.
 
-            let structural = self.search_for_structural_match_violation(cv.ty());
+            let structural =
+                traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty());
             debug!(
                 "search_for_structural_match_violation cv.ty: {:?} returned: {:?}",
                 cv.ty(),
@@ -194,17 +156,18 @@ impl<'tcx> ConstToPat<'tcx> {
                 return inlined_const_as_pat;
             }
 
-            if let Some(msg) = structural {
+            if let Some(non_sm_ty) = structural {
                 if !self.type_may_have_partial_eq_impl(cv.ty()) {
-                    // span_fatal avoids ICE from resolution of non-existent method (rare case).
-                    self.tcx().sess.span_fatal(self.span, &msg);
+                    // fatal avoids ICE from resolution of non-existent method (rare case).
+                    self.tcx()
+                        .sess
+                        .emit_fatal(TypeNotStructural { span: self.span, non_sm_ty: non_sm_ty });
                 } else if mir_structural_match_violation && !self.saw_const_match_lint.get() {
-                    self.tcx().struct_span_lint_hir(
+                    self.tcx().emit_spanned_lint(
                         lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                         self.id,
                         self.span,
-                        msg,
-                        |lint| lint,
+                        IndirectStructuralMatch { non_sm_ty },
                     );
                 } else {
                     debug!(
@@ -278,12 +241,11 @@ impl<'tcx> ConstToPat<'tcx> {
         let kind = match cv.ty().kind() {
             ty::Float(_) => {
                 if self.include_lint_checks {
-                    tcx.struct_span_lint_hir(
+                    tcx.emit_spanned_lint(
                         lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                         id,
                         span,
-                        "floating-point types cannot be used in patterns",
-                        |lint| lint,
+                        FloatPattern,
                     );
                 }
                 PatKind::Constant { value: cv }
@@ -291,29 +253,22 @@ impl<'tcx> ConstToPat<'tcx> {
             ty::Adt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
                 self.saw_const_match_error.set(true);
-                let msg = "cannot use unions in constant patterns";
-                if self.include_lint_checks {
-                    tcx.sess.span_err(span, msg);
-                } else {
-                    tcx.sess.delay_span_bug(span, msg);
-                }
+                let err = UnionPattern { span };
+                tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
                 PatKind::Wild
             }
             ty::Adt(..)
                 if !self.type_may_have_partial_eq_impl(cv.ty())
                     // FIXME(#73448): Find a way to bring const qualification into parity with
                     // `search_for_structural_match_violation` and then remove this condition.
-                    && self.search_for_structural_match_violation(cv.ty()).is_some() =>
+
+                    // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
+                    // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
+                    && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty()) =>
             {
-                // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
-                // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
-                let msg = self.search_for_structural_match_violation(cv.ty()).unwrap();
                 self.saw_const_match_error.set(true);
-                if self.include_lint_checks {
-                    tcx.sess.span_err(self.span, &msg);
-                } else {
-                    tcx.sess.delay_span_bug(self.span, &msg);
-                }
+                let err = TypeNotStructural { span, non_sm_ty };
+                tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
                 PatKind::Wild
             }
             // If the type is not structurally comparable, just emit the constant directly,
@@ -331,19 +286,11 @@ impl<'tcx> ConstToPat<'tcx> {
                     && !self.saw_const_match_lint.get()
                 {
                     self.saw_const_match_lint.set(true);
-                    tcx.struct_span_lint_hir(
+                    tcx.emit_spanned_lint(
                         lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                         id,
                         span,
-                        DelayDm(|| {
-                            format!(
-                                "to use a constant of type `{}` in a pattern, \
-                                 `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                                cv.ty(),
-                                cv.ty(),
-                            )
-                        }),
-                        |lint| lint,
+                        IndirectStructuralMatch { non_sm_ty: cv.ty() },
                     );
                 }
                 // Since we are behind a reference, we can just bubble the error up so we get a
@@ -357,18 +304,9 @@ impl<'tcx> ConstToPat<'tcx> {
                     adt_def,
                     cv.ty()
                 );
-                let path = tcx.def_path_str(adt_def.did());
-                let msg = format!(
-                    "to use a constant of type `{}` in a pattern, \
-                     `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                    path, path,
-                );
                 self.saw_const_match_error.set(true);
-                if self.include_lint_checks {
-                    tcx.sess.span_err(span, &msg);
-                } else {
-                    tcx.sess.delay_span_bug(span, &msg);
-                }
+                let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
+                tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
                 PatKind::Wild
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
@@ -401,12 +339,8 @@ impl<'tcx> ConstToPat<'tcx> {
                 // These are not allowed and will error elsewhere anyway.
                 ty::Dynamic(..) => {
                     self.saw_const_match_error.set(true);
-                    let msg = format!("`{}` cannot be used in patterns", cv.ty());
-                    if self.include_lint_checks {
-                        tcx.sess.span_err(span, &msg);
-                    } else {
-                        tcx.sess.delay_span_bug(span, &msg);
-                    }
+                    let err = InvalidPattern { span, non_sm_ty: cv.ty() };
+                    tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
                     PatKind::Wild
                 }
                 // `&str` is represented as `ConstValue::Slice`, let's keep using this
@@ -471,32 +405,26 @@ impl<'tcx> ConstToPat<'tcx> {
                 // this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
                 // reference. This makes the rest of the matching logic simpler as it doesn't have
                 // to figure out how to get a reference again.
-                ty::Adt(adt_def, _) if !self.type_marked_structural(*pointee_ty) => {
+                ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
                     if self.behind_reference.get() {
                         if self.include_lint_checks
                             && !self.saw_const_match_error.get()
                             && !self.saw_const_match_lint.get()
                         {
-                            self.saw_const_match_lint.set(true);
-                            let msg = self.adt_derive_msg(adt_def);
-                            self.tcx().struct_span_lint_hir(
+                           self.saw_const_match_lint.set(true);
+                           tcx.emit_spanned_lint(
                                 lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                                 self.id,
-                                self.span,
-                                msg,
-                                |lint| lint,
+                                span,
+                                IndirectStructuralMatch { non_sm_ty: *pointee_ty },
                             );
                         }
                         PatKind::Constant { value: cv }
                     } else {
                         if !self.saw_const_match_error.get() {
                             self.saw_const_match_error.set(true);
-                            let msg = self.adt_derive_msg(adt_def);
-                            if self.include_lint_checks {
-                                tcx.sess.span_err(span, &msg);
-                            } else {
-                                tcx.sess.delay_span_bug(span, &msg);
-                            }
+                            let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
+                            tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
                         }
                         PatKind::Wild
                     }
@@ -508,12 +436,10 @@ impl<'tcx> ConstToPat<'tcx> {
                     if !pointee_ty.is_sized(tcx, param_env) {
                         // `tcx.deref_mir_constant()` below will ICE with an unsized type
                         // (except slices, which are handled in a separate arm above).
-                        let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
-                        if self.include_lint_checks {
-                            tcx.sess.span_err(span, &msg);
-                        } else {
-                            tcx.sess.delay_span_bug(span, &msg);
-                        }
+
+                        let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
+                        tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+
                         PatKind::Wild
                     } else {
                         let old = self.behind_reference.replace(true);
@@ -545,27 +471,19 @@ impl<'tcx> ConstToPat<'tcx> {
                     && !self.saw_const_match_lint.get()
                 {
                     self.saw_const_match_lint.set(true);
-                    let msg = "function pointers and unsized pointers in patterns behave \
-                        unpredictably and should not be relied upon. \
-                        See https://github.com/rust-lang/rust/issues/70861 for details.";
-                    tcx.struct_span_lint_hir(
+                    tcx.emit_spanned_lint(
                         lint::builtin::POINTER_STRUCTURAL_MATCH,
                         id,
                         span,
-                        msg,
-                        |lint| lint,
+                        PointerPattern
                     );
                 }
                 PatKind::Constant { value: cv }
             }
             _ => {
                 self.saw_const_match_error.set(true);
-                let msg = format!("`{}` cannot be used in patterns", cv.ty());
-                if self.include_lint_checks {
-                    tcx.sess.span_err(span, &msg);
-                } else {
-                    tcx.sess.delay_span_bug(span, &msg);
-                }
+                let err = InvalidPattern { span, non_sm_ty: cv.ty() };
+                    tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
                 PatKind::Wild
             }
         };
@@ -576,21 +494,17 @@ impl<'tcx> ConstToPat<'tcx> {
             && mir_structural_match_violation
             // FIXME(#73448): Find a way to bring const qualification into parity with
             // `search_for_structural_match_violation` and then remove this condition.
-            && self.search_for_structural_match_violation(cv.ty()).is_some()
-        {
-            self.saw_const_match_lint.set(true);
+
             // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
             // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
-            let msg = self.search_for_structural_match_violation(cv.ty()).unwrap().replace(
-                "in a pattern,",
-                "in a pattern, the constant's initializer must be trivial or",
-            );
-            tcx.struct_span_lint_hir(
+            && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty())
+        {
+            self.saw_const_match_lint.set(true);
+            tcx.emit_spanned_lint(
                 lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
                 id,
                 span,
-                msg,
-                |lint| lint,
+                NontrivialStructuralMatch {non_sm_ty}
             );
         }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index a95349d7670..17b3c475f83 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -67,6 +67,7 @@ use self::SliceKind::*;
 
 use super::compare_const_vals;
 use super::usefulness::{MatchCheckCtxt, PatCtxt};
+use crate::errors::{Overlap, OverlappingRangeEndpoints};
 
 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
 fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
@@ -96,7 +97,7 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
 /// `IntRange` is never used to encode an empty range or a "range" that wraps
 /// around the (offset) space: i.e., `range.lo <= range.hi`.
 #[derive(Clone, PartialEq, Eq)]
-pub(super) struct IntRange {
+pub(crate) struct IntRange {
     range: RangeInclusive<u128>,
     /// Keeps the bias used for encoding the range. It depends on the type of the range and
     /// possibly the pointer size of the current architecture. The algorithm ensures we never
@@ -284,32 +285,21 @@ impl IntRange {
             return;
         }
 
-        let overlaps: Vec<_> = pats
+        let overlap: Vec<_> = pats
             .filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span())))
             .filter(|(range, _)| self.suspicious_intersection(range))
-            .map(|(range, span)| (self.intersection(&range).unwrap(), span))
+            .map(|(range, span)| Overlap {
+                range: self.intersection(&range).unwrap().to_pat(pcx.cx.tcx, pcx.ty),
+                span,
+            })
             .collect();
 
-        if !overlaps.is_empty() {
-            pcx.cx.tcx.struct_span_lint_hir(
+        if !overlap.is_empty() {
+            pcx.cx.tcx.emit_spanned_lint(
                 lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
                 hir_id,
                 pcx.span,
-                "multiple patterns overlap on their endpoints",
-                |lint| {
-                    for (int_range, span) in overlaps {
-                        lint.span_label(
-                            span,
-                            &format!(
-                                "this range overlaps on `{}`...",
-                                int_range.to_pat(pcx.cx.tcx, pcx.ty)
-                            ),
-                        );
-                    }
-                    lint.span_label(pcx.span, "... with this range");
-                    lint.note("you likely meant to write mutually exclusive ranges");
-                    lint
-                },
+                OverlappingRangeEndpoints { overlap, range: pcx.span },
             );
         }
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 7d4353c5292..3a6ef87c9c6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -2,7 +2,7 @@
 
 mod check_match;
 mod const_to_pat;
-mod deconstruct_pat;
+pub(crate) mod deconstruct_pat;
 mod usefulness;
 
 pub(crate) use self::check_match::check_match;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 8f80cb95e58..be66d0d4765 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -291,9 +291,8 @@
 
 use self::ArmType::*;
 use self::Usefulness::*;
-
-use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
 use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard};
+use crate::errors::{NonExhaustiveOmittedPattern, Uncovered};
 
 use rustc_data_structures::captures::Captures;
 
@@ -743,31 +742,6 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
     }
 }
 
-/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
-/// is not exhaustive enough.
-///
-/// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
-fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
-    cx: &MatchCheckCtxt<'p, 'tcx>,
-    scrut_ty: Ty<'tcx>,
-    sp: Span,
-    hir_id: HirId,
-    witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
-) {
-    cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, "some variants are not matched explicitly", |lint| {
-        let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
-        lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
-        lint.help(
-            "ensure that all variants are matched explicitly by adding the suggested match arms",
-        );
-        lint.note(&format!(
-            "the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
-            scrut_ty,
-        ));
-        lint
-    });
-}
-
 /// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
 /// The algorithm from the paper has been modified to correctly handle empty
 /// types. The changes are:
@@ -913,7 +887,19 @@ fn is_useful<'p, 'tcx>(
                         .collect::<Vec<_>>()
                 };
 
-                lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns);
+                // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
+                // is not exhaustive enough.
+                //
+                // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
+                cx.tcx.emit_spanned_lint(
+                    NON_EXHAUSTIVE_OMITTED_PATTERNS,
+                    hir_id,
+                    pcx.span,
+                    NonExhaustiveOmittedPattern {
+                        scrut_ty: pcx.ty,
+                        uncovered: Uncovered::new(pcx.span, pcx.cx, patterns),
+                    },
+                );
             }
 
             ret.extend(usefulness);
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 58f6fd2b006..b1b04c92a75 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -334,6 +334,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         self.r.field_names.insert(def_id, field_names);
     }
 
+    fn insert_field_visibilities_local(&mut self, def_id: DefId, vdata: &ast::VariantData) {
+        let field_vis = vdata
+            .fields()
+            .iter()
+            .map(|field| field.vis.span.until(field.ident.map_or(field.ty.span, |i| i.span)))
+            .collect();
+        self.r.field_visibility_spans.insert(def_id, field_vis);
+    }
+
     fn insert_field_names_extern(&mut self, def_id: DefId) {
         let field_names =
             self.r.cstore().struct_field_names_untracked(def_id, self.r.session).collect();
@@ -737,6 +746,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
 
                 // Record field names for error reporting.
                 self.insert_field_names_local(def_id, vdata);
+                self.insert_field_visibilities_local(def_id, vdata);
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
@@ -770,6 +780,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                         Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id.to_def_id());
                     self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
                     self.r.visibilities.insert(ctor_def_id, ctor_vis);
+                    // We need the field visibility spans also for the constructor for E0603.
+                    self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata);
 
                     self.r
                         .struct_constructors
@@ -783,6 +795,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
 
                 // Record field names for error reporting.
                 self.insert_field_names_local(def_id, vdata);
+                self.insert_field_visibilities_local(def_id, vdata);
             }
 
             ItemKind::Trait(..) => {
@@ -1510,6 +1523,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
 
         // Record field names for error reporting.
         self.insert_field_names_local(def_id.to_def_id(), &variant.data);
+        self.insert_field_visibilities_local(def_id.to_def_id(), &variant.data);
 
         visit::walk_variant(self, variant);
     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 7d62d67d64f..1a852de8eed 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -6,7 +6,9 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+    pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
+};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
@@ -1604,6 +1606,16 @@ impl<'a> Resolver<'a> {
         err.span_label(ident.span, &format!("private {}", descr));
         if let Some(span) = ctor_fields_span {
             err.span_label(span, "a constructor is private if any of the fields is private");
+            if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
+                err.multipart_suggestion_verbose(
+                    &format!(
+                        "consider making the field{} publicly accessible",
+                        pluralize!(fields.len())
+                    ),
+                    fields.iter().map(|span| (*span, "pub ".to_string())).collect(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
         }
 
         // Print the whole import chain to make it easier to see what happens.
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 74522f18542..d92f5a7c05e 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1451,6 +1451,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         .collect();
 
                     if non_visible_spans.len() > 0 {
+                        if let Some(fields) = self.r.field_visibility_spans.get(&def_id) {
+                            err.multipart_suggestion_verbose(
+                                &format!(
+                                    "consider making the field{} publicly accessible",
+                                    pluralize!(fields.len())
+                                ),
+                                fields.iter().map(|span| (*span, "pub ".to_string())).collect(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+
                         let mut m: MultiSpan = non_visible_spans.clone().into();
                         non_visible_spans
                             .into_iter()
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 2182b736937..84d9794ccf2 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -881,6 +881,10 @@ pub struct Resolver<'a> {
     /// Used for hints during error reporting.
     field_names: FxHashMap<DefId, Vec<Spanned<Symbol>>>,
 
+    /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
+    /// Used for hints during error reporting.
+    field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
+
     /// All imports known to succeed or fail.
     determined_imports: Vec<&'a Import<'a>>,
 
@@ -1268,6 +1272,7 @@ impl<'a> Resolver<'a> {
 
             has_self: FxHashSet::default(),
             field_names: FxHashMap::default(),
+            field_visibility_spans: FxHashMap::default(),
 
             determined_imports: Vec::new(),
             indeterminate_imports: Vec::new(),
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 19f404cb5b7..4405537c645 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,7 +1,6 @@
 use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
 use rustc_macros::Diagnostic;
 use rustc_middle::ty::{self, PolyTraitRef, Ty};
-use rustc_session::Limit;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
@@ -22,18 +21,6 @@ pub struct UnableToConstructConstantValue<'a> {
 }
 
 #[derive(Diagnostic)]
-#[help]
-#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
-pub struct AutoDerefReachedRecursionLimit<'a> {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    pub ty: Ty<'a>,
-    pub suggested_limit: Limit,
-    pub crate_name: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
 pub struct EmptyOnClauseInOnUnimplemented {
     #[primary_span]
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index a30d1df4ede..081ac966c69 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -35,7 +35,6 @@ extern crate rustc_middle;
 #[macro_use]
 extern crate smallvec;
 
-pub mod autoderef;
 pub mod errors;
 pub mod infer;
 pub mod solve;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
index 27c207528c7..ba9ee57d409 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -55,7 +55,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
 
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         self.infcx.probe(|_| {
-            if a.is_ty_infer() || b.is_ty_infer() {
+            if a.is_ty_var() || b.is_ty_var() {
                 Ok(a)
             } else {
                 self.infcx.super_combine_tys(self, a, b).or_else(|e| {
@@ -71,10 +71,13 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
         a: ty::Const<'tcx>,
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        if a == b {
-            return Ok(a);
-        }
-        relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+        self.infcx.probe(|_| {
+            if a.is_ct_infer() || b.is_ct_infer() {
+                Ok(a)
+            } else {
+                relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+            }
+        })
     }
 
     fn binders<T: Relate<'tcx>>(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 5f06c4d8282..20bede22c34 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1724,7 +1724,19 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 .and_then(|(predicate, _, normalized_term, expected_term)| {
                     self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
                 })
-                .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
+                .unwrap_or_else(|| {
+                    with_forced_trimmed_paths!(format!(
+                        "type mismatch resolving `{}`",
+                        self.resolve_vars_if_possible(predicate)
+                            .print(FmtPrinter::new_with_limit(
+                                self.tcx,
+                                Namespace::TypeNS,
+                                rustc_session::Limit(10),
+                            ))
+                            .unwrap()
+                            .into_buffer()
+                    ))
+                });
             let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
 
             let secondary_span = match predicate.kind().skip_binder() {
@@ -1755,7 +1767,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 kind: hir::ImplItemKind::Type(ty),
                                 ..
                             }),
-                        ) => Some((ty.span, format!("type mismatch resolving `{}`", predicate))),
+                        ) => Some((
+                            ty.span,
+                            with_forced_trimmed_paths!(format!(
+                                "type mismatch resolving `{}`",
+                                self.resolve_vars_if_possible(predicate)
+                                    .print(FmtPrinter::new_with_limit(
+                                        self.tcx,
+                                        Namespace::TypeNS,
+                                        rustc_session::Limit(5),
+                                    ))
+                                    .unwrap()
+                                    .into_buffer()
+                            )),
+                        )),
                         _ => None,
                     }),
                 _ => None,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index b0a730c8ad1..e599996230f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -37,6 +37,21 @@ pub trait TypeErrCtxtExt<'tcx> {
     ) -> OnUnimplementedNote;
 }
 
+/// The symbols which are always allowed in a format string
+static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
+    kw::SelfUpper,
+    sym::ItemContext,
+    sym::from_method,
+    sym::from_desugaring,
+    sym::direct,
+    sym::cause,
+    sym::integral,
+    sym::integer_,
+    sym::float,
+    sym::_Self,
+    sym::crate_local,
+];
+
 impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn impl_similar_to(
         &self,
@@ -543,38 +558,26 @@ impl<'tcx> OnUnimplementedFormatString {
                 Piece::NextArgument(a) => match a.position {
                     Position::ArgumentNamed(s) => {
                         match Symbol::intern(s) {
-                            // `{Self}` is allowed
-                            kw::SelfUpper => (),
                             // `{ThisTraitsName}` is allowed
                             s if s == trait_name => (),
-                            // `{from_method}` is allowed
-                            sym::from_method => (),
-                            // `{from_desugaring}` is allowed
-                            sym::from_desugaring => (),
-                            // `{ItemContext}` is allowed
-                            sym::ItemContext => (),
-                            // `{integral}` and `{integer}` and `{float}` are allowed
-                            sym::integral | sym::integer_ | sym::float => (),
+                            s if ALLOWED_FORMAT_SYMBOLS.contains(&s) => (),
                             // So is `{A}` if A is a type parameter
-                            s => match generics.params.iter().find(|param| param.name == s) {
-                                Some(_) => (),
-                                None => {
-                                    let reported = struct_span_err!(
-                                        tcx.sess,
-                                        span,
-                                        E0230,
-                                        "there is no parameter `{}` on {}",
-                                        s,
-                                        if trait_def_id == item_def_id {
-                                            format!("trait `{}`", trait_name)
-                                        } else {
-                                            "impl".to_string()
-                                        }
-                                    )
-                                    .emit();
-                                    result = Err(reported);
-                                }
-                            },
+                            s if generics.params.iter().any(|param| param.name == s) => (),
+                            s => {
+                                result = Err(struct_span_err!(
+                                    tcx.sess,
+                                    span,
+                                    E0230,
+                                    "there is no parameter `{}` on {}",
+                                    s,
+                                    if trait_def_id == item_def_id {
+                                        format!("trait `{}`", trait_name)
+                                    } else {
+                                        "impl".to_string()
+                                    }
+                                )
+                                .emit());
+                            }
                         }
                     }
                     // `{:1}` and `{}` are not to be used
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 53769742c47..1b98ead29f8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -5,7 +5,6 @@ use super::{
     PredicateObligation,
 };
 
-use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
 use crate::traits::{NormalizeExt, ObligationCtxt};
 
@@ -750,26 +749,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
 
             if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
-                let mut autoderef = Autoderef::new(
-                    self,
-                    obligation.param_env,
-                    obligation.cause.body_id,
-                    span,
-                    base_ty,
-                );
-                if let Some(steps) = autoderef.find_map(|(ty, steps)| {
-                    // Re-add the `&`
-                    let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
-
-                    // Remapping bound vars here
-                    let real_trait_pred_and_ty =
-                        real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
-                    let obligation = self.mk_trait_obligation_with_new_self_ty(
-                        obligation.param_env,
-                        real_trait_pred_and_ty,
-                    );
-                    Some(steps).filter(|_| self.predicate_may_hold(&obligation))
-                }) {
+                let autoderef = (self.autoderef_steps)(base_ty);
+                if let Some(steps) =
+                    autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
+                        // Re-add the `&`
+                        let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
+
+                        // Remapping bound vars here
+                        let real_trait_pred_and_ty =
+                            real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
+                        let obligation = self.mk_trait_obligation_with_new_self_ty(
+                            obligation.param_env,
+                            real_trait_pred_and_ty,
+                        );
+                        if obligations
+                            .iter()
+                            .chain([&obligation])
+                            .all(|obligation| self.predicate_may_hold(obligation))
+                        {
+                            Some(steps)
+                        } else {
+                            None
+                        }
+                    })
+                {
                     if steps > 0 {
                         // Don't care about `&mut` because `DerefMut` is used less
                         // often and user will not expect autoderef happens.
@@ -1358,57 +1361,117 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        let span = obligation.cause.span;
+        let mut span = obligation.cause.span;
+        let mut trait_pred = trait_pred;
+        let mut code = obligation.cause.code();
+        while let Some((c, Some(parent_trait_pred))) = code.parent() {
+            // We want the root obligation, in order to detect properly handle
+            // `for _ in &mut &mut vec![] {}`.
+            code = c;
+            trait_pred = parent_trait_pred;
+        }
+        while span.desugaring_kind().is_some() {
+            // Remove all the hir desugaring contexts while maintaining the macro contexts.
+            span.remove_mark();
+        }
+        let mut expr_finder = super::FindExprBySpan::new(span);
+        let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
+            return false;
+        };
+        expr_finder.visit_expr(&body);
+        let mut maybe_suggest = |suggested_ty, count, suggestions| {
+            // Remapping bound vars here
+            let trait_pred_and_suggested_ty =
+                trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
+
+            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
+                obligation.param_env,
+                trait_pred_and_suggested_ty,
+            );
 
-        let mut suggested = false;
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
-                // Do not suggest removal of borrow from type arguments.
-                return false;
+            if self.predicate_may_hold(&new_obligation) {
+                let msg = if count == 1 {
+                    "consider removing the leading `&`-reference".to_string()
+                } else {
+                    format!("consider removing {count} leading `&`-references")
+                };
+
+                err.multipart_suggestion_verbose(
+                    &msg,
+                    suggestions,
+                    Applicability::MachineApplicable,
+                );
+                true
+            } else {
+                false
             }
+        };
 
-            // Skipping binder here, remapping below
-            let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        // Maybe suggest removal of borrows from types in type parameters, like in
+        // `src/test/ui/not-panic/not-panic-safe.rs`.
+        let mut count = 0;
+        let mut suggestions = vec![];
+        // Skipping binder here, remapping below
+        let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        if let Some(mut hir_ty) = expr_finder.ty_result {
+            while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
+                count += 1;
+                let span = hir_ty.span.until(mut_ty.ty.span);
+                suggestions.push((span, String::new()));
 
-            for refs_remaining in 0..refs_number {
                 let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
                     break;
                 };
                 suggested_ty = *inner_ty;
 
-                // Remapping bound vars here
-                let trait_pred_and_suggested_ty =
-                    trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
+                hir_ty = mut_ty.ty;
 
-                let new_obligation = self.mk_trait_obligation_with_new_self_ty(
-                    obligation.param_env,
-                    trait_pred_and_suggested_ty,
-                );
+                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+                    return true;
+                }
+            }
+        }
 
-                if self.predicate_may_hold(&new_obligation) {
-                    let sp = self
-                        .tcx
-                        .sess
-                        .source_map()
-                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+        // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
+        let Some(mut expr) = expr_finder.result else { return false; };
+        let mut count = 0;
+        let mut suggestions = vec![];
+        // Skipping binder here, remapping below
+        let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        'outer: loop {
+            while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
+                count += 1;
+                let span = if expr.span.eq_ctxt(borrowed.span) {
+                    expr.span.until(borrowed.span)
+                } else {
+                    expr.span.with_hi(expr.span.lo() + BytePos(1))
+                };
+                suggestions.push((span, String::new()));
 
-                    let remove_refs = refs_remaining + 1;
+                let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
+                    break 'outer;
+                };
+                suggested_ty = *inner_ty;
 
-                    let msg = if remove_refs == 1 {
-                        "consider removing the leading `&`-reference".to_string()
-                    } else {
-                        format!("consider removing {} leading `&`-references", remove_refs)
-                    };
+                expr = borrowed;
 
-                    err.span_suggestion_short(sp, &msg, "", Applicability::MachineApplicable);
-                    suggested = true;
-                    break;
+                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+                    return true;
                 }
             }
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::def::Res::Local(hir_id) = path.res
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id)
+                && let None = local.ty
+                && let Some(binding_expr) = local.init
+            {
+                expr = binding_expr;
+            } else {
+                break 'outer;
+            }
         }
-        suggested
+        false
     }
 
     fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
@@ -2622,11 +2685,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
             ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
-                err.note(&format!(
-                    "required for the cast from `{}` to the object type `{}`",
-                    self.ty_to_string(concrete_ty),
-                    self.ty_to_string(object_ty)
-                ));
+                let (concrete_ty, concrete_file) =
+                    self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
+                let (object_ty, object_file) =
+                    self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
+                err.note(&with_forced_trimmed_paths!(format!(
+                    "required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
+                )));
+                if let Some(file) = concrete_file {
+                    err.note(&format!(
+                        "the full name for the casted type has been written to '{}'",
+                        file.display(),
+                    ));
+                }
+                if let Some(file) = object_file {
+                    err.note(&format!(
+                        "the full name for the object type has been written to '{}'",
+                        file.display(),
+                    ));
+                }
             }
             ObligationCauseCode::Coercion { source: _, target } => {
                 err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index c54d901e9b1..170c1673dbd 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -174,7 +174,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .param_env
             .caller_bounds()
             .iter()
-            .filter_map(|o| o.to_opt_poly_trait_pred());
+            .filter_map(|p| p.to_opt_poly_trait_pred())
+            .filter(|p| !p.references_error());
 
         // Micro-optimization: filter out predicates relating to different traits.
         let matching_bounds =
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3f14491f803..2615e262282 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2377,6 +2377,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
 
         let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
+        if impl_trait_ref.references_error() {
+            return Err(());
+        }
 
         debug!(?impl_trait_ref);
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 9e0d7cab63e..e898bca88e4 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -239,7 +239,6 @@
 #![feature(arm_target_feature)]
 #![feature(avx512_target_feature)]
 #![feature(cmpxchg16b_target_feature)]
-#![feature(f16c_target_feature)]
 #![feature(hexagon_target_feature)]
 #![feature(mips_target_feature)]
 #![feature(powerpc_target_feature)]
@@ -248,6 +247,7 @@
 #![feature(sse4a_target_feature)]
 #![feature(tbm_target_feature)]
 #![feature(wasm_target_feature)]
+#![cfg_attr(bootstrap, feature(f16c_target_feature))]
 
 // allow using `core::` in intra-doc links
 #[allow(unused_extern_crates)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 57096f43974..21518a3f551 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1514,37 +1514,50 @@ macro_rules! int_impl {
             (a as Self, b)
         }
 
-        /// Calculates `self + rhs + carry` without the ability to overflow.
+        /// Calculates `self` + `rhs` + `carry` and checks for overflow.
         ///
-        /// Performs "signed ternary addition" which takes in an extra bit to add, and may return an
-        /// additional bit of overflow. This signed function is used only on the highest-ordered data,
-        /// for which the signed overflow result indicates whether the big integer overflowed or not.
+        /// Performs "ternary addition" of two integer operands and a carry-in
+        /// bit, and returns a tuple of the sum along with a boolean indicating
+        /// whether an arithmetic overflow would occur. On overflow, the wrapped
+        /// value is returned.
         ///
-        /// # Examples
+        /// This allows chaining together multiple additions to create a wider
+        /// addition, and can be useful for bignum addition. This method should
+        /// only be used for the most significant word; for the less significant
+        /// words the unsigned method
+        #[doc = concat!("[`", stringify!($UnsignedT), "::carrying_add`]")]
+        /// should be used.
         ///
-        /// Basic usage:
+        /// The output boolean returned by this method is *not* a carry flag,
+        /// and should *not* be added to a more significant word.
         ///
-        /// ```
-        /// #![feature(bigint_helper_methods)]
-        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
-        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (", stringify!($SelfT), "::MIN, true));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (", stringify!($SelfT), "::MIN, true));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, true));")]
-        #[doc = concat!("assert_eq!(",
-            stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
-            "(-1, true));"
-        )]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.carrying_add(-1, true), (", stringify!($SelfT), "::MIN, false));")]
-        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".carrying_add(", stringify!($SelfT), "::MAX, true), (", stringify!($SelfT), "::MIN, true));")]
-        /// ```
+        /// If the input carry is false, this method is equivalent to
+        /// [`overflowing_add`](Self::overflowing_add).
         ///
-        /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+        /// # Examples
         ///
         /// ```
         /// #![feature(bigint_helper_methods)]
-        #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
+        /// // Only the  most significant word is signed.
+        /// //
+        #[doc = concat!("//   10  MAX    (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
+        #[doc = concat!("// + -5    9    (b = -5 × 2^", stringify!($BITS), " + 9)")]
+        /// // ---------
+        #[doc = concat!("//    6    8    (sum = 6 × 2^", stringify!($BITS), " + 8)")]
+        ///
+        #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (10, ", stringify!($UnsignedT), "::MAX);")]
+        #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (-5, 9);")]
+        /// let carry0 = false;
+        ///
+        #[doc = concat!("// ", stringify!($UnsignedT), "::carrying_add for the less significant words")]
+        /// let (sum0, carry1) = a0.carrying_add(b0, carry0);
+        /// assert_eq!(carry1, true);
+        ///
+        #[doc = concat!("// ", stringify!($SelfT), "::carrying_add for the most significant word")]
+        /// let (sum1, overflow) = a1.carrying_add(b1, carry1);
+        /// assert_eq!(overflow, false);
+        ///
+        /// assert_eq!((sum1, sum0), (6, 8));
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
@@ -1608,25 +1621,51 @@ macro_rules! int_impl {
             (a as Self, b)
         }
 
-        /// Calculates `self - rhs - borrow` without the ability to overflow.
+        /// Calculates `self` &minus; `rhs` &minus; `borrow` and checks for
+        /// overflow.
         ///
-        /// Performs "signed ternary subtraction" which takes in an extra bit to subtract, and may return an
-        /// additional bit of overflow. This signed function is used only on the highest-ordered data,
-        /// for which the signed overflow result indicates whether the big integer overflowed or not.
+        /// Performs "ternary subtraction" by subtracting both an integer
+        /// operandand a borrow-in bit from `self`, and returns a tuple of the
+        /// difference along with a boolean indicating whether an arithmetic
+        /// overflow would occur. On overflow, the wrapped value is returned.
         ///
-        /// # Examples
+        /// This allows chaining together multiple subtractions to create a
+        /// wider subtraction, and can be useful for bignum subtraction. This
+        /// method should only be used for the most significant word; for the
+        /// less significant words the unsigned method
+        #[doc = concat!("[`", stringify!($UnsignedT), "::borrowing_sub`]")]
+        /// should be used.
         ///
-        /// Basic usage:
+        /// The output boolean returned by this method is *not* a borrow flag,
+        /// and should *not* be subtracted from a more significant word.
+        ///
+        /// If the input borrow is false, this method is equivalent to
+        /// [`overflowing_sub`](Self::overflowing_sub).
+        ///
+        /// # Examples
         ///
         /// ```
         /// #![feature(bigint_helper_methods)]
-        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
-        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
-        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (-1, false));")]
-        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (-2, false));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, false), (", stringify!($SelfT), "::MIN, true));")]
-        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, true), (", stringify!($SelfT), "::MAX, false));")]
+        /// // Only the  most significant word is signed.
+        /// //
+        #[doc = concat!("//    6    8    (a = 6 × 2^", stringify!($BITS), " + 8)")]
+        #[doc = concat!("// - -5    9    (b = -5 × 2^", stringify!($BITS), " + 9)")]
+        /// // ---------
+        #[doc = concat!("//   10  MAX    (diff = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
+        ///
+        #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (6, 8);")]
+        #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (-5, 9);")]
+        /// let borrow0 = false;
+        ///
+        #[doc = concat!("// ", stringify!($UnsignedT), "::borrowing_sub for the less significant words")]
+        /// let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0);
+        /// assert_eq!(borrow1, true);
+        ///
+        #[doc = concat!("// ", stringify!($SelfT), "::borrowing_sub for the most significant word")]
+        /// let (diff1, overflow) = a1.borrowing_sub(b1, borrow1);
+        /// assert_eq!(overflow, false);
+        ///
+        #[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")]
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 3f8acc8505f..2eb29d4f9c5 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -622,9 +622,8 @@ impl<P: Deref> Pin<P> {
     /// that the closure is pinned.
     ///
     /// The better alternative is to avoid all that trouble and do the pinning in the outer function
-    /// instead (here using the unstable `pin` macro):
+    /// instead (here using the [`pin!`][crate::pin::pin] macro):
     /// ```
-    /// #![feature(pin_macro)]
     /// use std::pin::pin;
     /// use std::task::Context;
     /// use std::future::Future;
@@ -1026,7 +1025,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// ### Basic usage
 ///
 /// ```rust
-/// #![feature(pin_macro)]
 /// # use core::marker::PhantomPinned as Foo;
 /// use core::pin::{pin, Pin};
 ///
@@ -1044,7 +1042,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// ### Manually polling a `Future` (without `Unpin` bounds)
 ///
 /// ```rust
-/// #![feature(pin_macro)]
 /// use std::{
 ///     future::Future,
 ///     pin::pin,
@@ -1083,7 +1080,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// ### With `Generator`s
 ///
 /// ```rust
-/// #![feature(generators, generator_trait, pin_macro)]
+/// #![feature(generators, generator_trait)]
 /// use core::{
 ///     ops::{Generator, GeneratorState},
 ///     pin::pin,
@@ -1126,7 +1123,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// The following, for instance, fails to compile:
 ///
 /// ```rust,compile_fail
-/// #![feature(pin_macro)]
 /// use core::pin::{pin, Pin};
 /// # use core::{marker::PhantomPinned as Foo, mem::drop as stuff};
 ///
@@ -1168,7 +1164,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// constructor.
 ///
 /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
-#[unstable(feature = "pin_macro", issue = "93178")]
+#[stable(feature = "pin_macro", since = "CURRENT_RUSTC_VERSION")]
 #[rustc_macro_transparency = "semitransparent"]
 #[allow_internal_unstable(unsafe_pin_internals)]
 pub macro pin($value:expr $(,)?) {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index c910cb65c55..42a26ae1675 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -48,7 +48,6 @@
 #![feature(is_sorted)]
 #![feature(layout_for_ptr)]
 #![feature(pattern)]
-#![feature(pin_macro)]
 #![feature(sort_internals)]
 #![feature(slice_take)]
 #![feature(slice_from_ptr_range)]
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 7acda8e98f1..692ff0cbca6 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -177,6 +177,12 @@ use crate::sys_common::thread_parking::Parker;
 use crate::sys_common::{AsInner, IntoInner};
 use crate::time::Duration;
 
+#[stable(feature = "scoped_threads", since = "1.63.0")]
+mod scoped;
+
+#[stable(feature = "scoped_threads", since = "1.63.0")]
+pub use scoped::{scope, Scope, ScopedJoinHandle};
+
 ////////////////////////////////////////////////////////////////////////////////
 // Thread-local storage
 ////////////////////////////////////////////////////////////////////////////////
@@ -184,12 +190,6 @@ use crate::time::Duration;
 #[macro_use]
 mod local;
 
-#[stable(feature = "scoped_threads", since = "1.63.0")]
-mod scoped;
-
-#[stable(feature = "scoped_threads", since = "1.63.0")]
-pub use scoped::{scope, Scope, ScopedJoinHandle};
-
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::local::{AccessError, LocalKey};
 
@@ -209,7 +209,6 @@ pub use self::local::{AccessError, LocalKey};
 ))]
 #[doc(hidden)]
 pub use self::local::fast::Key as __FastLocalKeyInner;
-
 // when building for tests, use real std's type
 #[unstable(feature = "libstd_thread_internals", issue = "none")]
 #[cfg(test)]
@@ -220,12 +219,21 @@ pub use self::local::fast::Key as __FastLocalKeyInner;
 pub use realstd::thread::__FastLocalKeyInner;
 
 #[unstable(feature = "libstd_thread_internals", issue = "none")]
+#[cfg(not(test))]
 #[cfg(all(
     not(target_thread_local),
     not(all(target_family = "wasm", not(target_feature = "atomics"))),
 ))]
 #[doc(hidden)]
 pub use self::local::os::Key as __OsLocalKeyInner;
+// when building for tests, use real std's type
+#[unstable(feature = "libstd_thread_internals", issue = "none")]
+#[cfg(test)]
+#[cfg(all(
+    not(target_thread_local),
+    not(all(target_family = "wasm", not(target_feature = "atomics"))),
+))]
+pub use realstd::thread::__OsLocalKeyInner;
 
 #[unstable(feature = "libstd_thread_internals", issue = "none")]
 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index f3998e98583..9cf43fc7a21 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -934,7 +934,8 @@ def main():
     if len(sys.argv) > 1 and sys.argv[1] == 'help':
         sys.argv = [sys.argv[0], '-h'] + sys.argv[2:]
 
-    help_triggered = len(sys.argv) == 1 or any(x in ["-h", "--help", "--version"] for x in sys.argv)
+    help_triggered = (
+        '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
     try:
         bootstrap(help_triggered)
         if not help_triggered:
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 930f58baf02..62e3f627ec0 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -41,10 +41,6 @@ WORKDIR /
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-# We are disabling CI LLVM since this builder needs to build LLD, which is
-# currently unsupported when downloading pre-built LLVM.
-ENV NO_DOWNLOAD_CI_LLVM 1
-
 ENV RUST_CONFIGURE_ARGS \
   --musl-root-x86_64=/usr/local/x86_64-linux-musl \
   --set build.nodejs=/node-v15.14.0-linux-x64/bin/node \
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 5c63efef717..87de41fde63 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -676,7 +676,8 @@ impl Item {
         }
         let header = match *self.kind {
             ItemKind::ForeignFunctionItem(_) => {
-                let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
+                let def_id = self.item_id.as_def_id().unwrap();
+                let abi = tcx.fn_sig(def_id).abi();
                 hir::FnHeader {
                     unsafety: if abi == Abi::RustIntrinsic {
                         intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
@@ -684,7 +685,14 @@ impl Item {
                         hir::Unsafety::Unsafe
                     },
                     abi,
-                    constness: hir::Constness::NotConst,
+                    constness: if abi == Abi::RustIntrinsic
+                        && tcx.is_const_fn(def_id)
+                        && is_unstable_const_fn(tcx, def_id).is_none()
+                    {
+                        hir::Constness::Const
+                    } else {
+                        hir::Constness::NotConst
+                    },
                     asyncness: hir::IsAsync::NotAsync,
                 }
             }
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs
index 7576ba78f60..fe4078f7710 100644
--- a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs
+++ b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs
@@ -1,5 +1,3 @@
-#![feature(pin_macro)]
-
 use core::future::Future;
 use core::pin::Pin;
 use core::task::{Context, Poll};
diff --git a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
index 3ba21552fd3..96fc0be344d 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
@@ -1,5 +1,3 @@
-#![feature(pin_macro)]
-
 use std::future::*;
 use std::marker::PhantomPinned;
 use std::pin::*;
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 5f5ae3a65ef..fff83a1d097 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -11,7 +11,6 @@ miropt-test-tools = { path = "../miropt-test-tools" }
 lazy_static = "1"
 walkdir = "2"
 ignore = "0.4.18"
-semver = "1.0.14"
 termcolor = "1.1.3"
 
 [[bin]]
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index ac8b5f6834c..bc9fd35ecde 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -31,10 +31,8 @@ const IGNORE_DOCTEST_CHECK: &[&str] =
     &["E0208", "E0464", "E0570", "E0601", "E0602", "E0640", "E0717"];
 
 // Error codes that don't yet have a UI test. This list will eventually be removed.
-const IGNORE_UI_TEST_CHECK: &[&str] = &[
-    "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729",
-    "E0789",
-];
+const IGNORE_UI_TEST_CHECK: &[&str] =
+    &["E0461", "E0465", "E0476", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", "E0789"];
 
 macro_rules! verbose_print {
     ($verbose:expr, $($fmt:tt)*) => {
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 1eb146989e4..40375f1306d 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -69,4 +69,3 @@ pub mod ui_tests;
 pub mod unit_tests;
 pub mod unstable_book;
 pub mod walk;
-pub mod x_version;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 79441cda64c..ea2886a3c2f 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -60,7 +60,7 @@ fn main() {
 
                 let handle = s.spawn(|| {
                     let mut flag = false;
-                    $p::check($($args, )* &mut flag);
+                    $p::check($($args),* , &mut flag);
                     if (flag) {
                         bad.store(true, Ordering::Relaxed);
                     }
@@ -113,8 +113,6 @@ fn main() {
         check!(alphabetical, &compiler_path);
         check!(alphabetical, &library_path);
 
-        check!(x_version, &root_path, &cargo);
-
         let collected = {
             drain_handles(&mut handles);
 
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
deleted file mode 100644
index 5dc6a0588c3..00000000000
--- a/src/tools/tidy/src/x_version.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-use semver::Version;
-use std::io::ErrorKind;
-use std::path::Path;
-use std::process::{Command, Stdio};
-
-pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
-    let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn();
-    // This runs the command inside a temporary directory.
-    // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x.
-    let temp_result = Command::new("x")
-        .arg("--wrapper-version")
-        .current_dir(std::env::temp_dir())
-        .stdout(Stdio::piped())
-        .spawn();
-
-    let (child, temp_child) = match (result, temp_result) {
-        (Ok(child), Ok(temp_child)) => (child, temp_child),
-        (Err(e), _) | (_, Err(e)) => match e.kind() {
-            ErrorKind::NotFound => return,
-            _ => return tidy_error!(bad, "failed to run `x`: {}", e),
-        },
-    };
-
-    let output = child.wait_with_output().unwrap();
-    let temp_output = temp_child.wait_with_output().unwrap();
-
-    if output != temp_output {
-        return tidy_error!(
-            bad,
-            "Current version of x does not support the `--wrapper-version` argument\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
-        );
-    }
-
-    if output.status.success() {
-        let version = String::from_utf8_lossy(&output.stdout);
-        let version = Version::parse(version.trim_end()).unwrap();
-
-        if let Some(expected) = get_x_wrapper_version(root, cargo) {
-            if version < expected {
-                return tidy_error!(
-                    bad,
-                    "Current version of x is {version}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
-                );
-            }
-        } else {
-            return tidy_error!(
-                bad,
-                "Unable to parse the latest version of `x` at `src/tools/x/Cargo.toml`"
-            );
-        }
-    } else {
-        return tidy_error!(bad, "failed to check version of `x`: {}", output.status);
-    }
-}
-
-// Parse latest version out of `x` Cargo.toml
-fn get_x_wrapper_version(root: &Path, cargo: &Path) -> Option<Version> {
-    let mut cmd = cargo_metadata::MetadataCommand::new();
-    cmd.cargo_path(cargo)
-        .manifest_path(root.join("src/tools/x/Cargo.toml"))
-        .no_deps()
-        .features(cargo_metadata::CargoOpt::AllFeatures);
-    let mut metadata = t!(cmd.exec());
-    metadata.packages.pop().map(|x| x.version)
-}
diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs
new file mode 100644
index 00000000000..2fc486d01da
--- /dev/null
+++ b/tests/rustdoc/const-intrinsic.rs
@@ -0,0 +1,25 @@
+#![feature(intrinsics)]
+#![feature(staged_api)]
+
+#![crate_name = "foo"]
+#![stable(since="1.0.0", feature="rust1")]
+
+extern "rust-intrinsic" {
+    // @has 'foo/fn.transmute.html'
+    // @has - '//pre[@class="rust fn"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
+    #[stable(since="1.0.0", feature="rust1")]
+    #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
+    pub fn transmute<T, U>(_: T) -> U;
+
+    // @has 'foo/fn.unreachable.html'
+    // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    #[stable(since="1.0.0", feature="rust1")]
+    pub fn unreachable() -> !;
+}
+
+extern "C" {
+    // @has 'foo/fn.needs_drop.html'
+    // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    #[stable(since="1.0.0", feature="rust1")]
+    pub fn needs_drop() -> !;
+}
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index c19b639a8d5..65d9601e78a 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -723,7 +723,6 @@ struct SubdiagnosticEagerLint {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerCorrect {
     #[subdiagnostic(eager)]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -744,7 +743,6 @@ pub(crate) struct SubdiagnosticWithSuggestion {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerSuggestion {
     #[subdiagnostic(eager)]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     sub: SubdiagnosticWithSuggestion,
 }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index f39d32a221c..13e806a434f 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -539,7 +539,7 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(bad)]
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `subdiagnostic` does not support nested attributes
+   = help: `eager` is the only supported nested attribute for `subdiagnostic`
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:693:5
@@ -553,7 +553,7 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(bad, bad)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `subdiagnostic` does not support nested attributes
+   = help: `eager` is the only supported nested attribute for `subdiagnostic`
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:709:5
@@ -561,7 +561,7 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic("bad")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `subdiagnostic` does not support nested attributes
+   = help: `eager` is the only supported nested attribute for `subdiagnostic`
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:717:5
@@ -569,38 +569,22 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `subdiagnostic` does not support nested attributes
-
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:725:5
-   |
-LL |     #[subdiagnostic(eager)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `subdiagnostic` does not support nested attributes
-
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:746:5
-   |
-LL |     #[subdiagnostic(eager)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `subdiagnostic` does not support nested attributes
+   = help: eager subdiagnostics are not supported on lints
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:777:18
+  --> $DIR/diagnostic-derive.rs:775:18
    |
 LL |     #[suggestion(code())]
    |                  ^^^^^^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:785:23
+  --> $DIR/diagnostic-derive.rs:783:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:793:18
+  --> $DIR/diagnostic-derive.rs:791:18
    |
 LL |     #[suggestion(code = 3)]
    |                  ^^^^^^^^
@@ -676,7 +660,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
    = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 85 previous errors
+error: aborting due to 83 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr
index eadaa35b65e..acdc3be8c67 100644
--- a/tests/ui/associated-types/substs-ppaux.normal.stderr
+++ b/tests/ui/associated-types/substs-ppaux.normal.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:16:17
    |
 LL |     fn bar<'a, T>() where T: 'a {}
-   |     --------------------------- fn() {<i8 as Foo<'static, 'static, u8>>::bar::<'static, char>} defined here
+   |     --------------------------- associated function `bar` defined here
 ...
 LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::bar::<'static, char>;
    |            --   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:25:17
    |
 LL |     fn bar<'a, T>() where T: 'a {}
-   |     --------------------------- fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>} defined here
+   |     --------------------------- associated function `bar` defined here
 ...
 LL |     let x: () = <i8 as Foo<'static, 'static,  u32>>::bar::<'static, char>;
    |            --   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:33:17
    |
 LL |     fn baz() {}
-   |     -------- fn() {<i8 as Foo<'static, 'static, u8>>::baz} defined here
+   |     -------- associated function `baz` defined here
 ...
 LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::baz;
    |            --   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -56,7 +56,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:41:17
    |
 LL | fn foo<'z>() where &'z (): Sized {
-   | -------------------------------- fn() {foo::<'static>} defined here
+   | -------------------------------- function `foo` defined here
 ...
 LL |     let x: () = foo::<'static>;
    |            --   ^^^^^^^^^^^^^^ expected `()`, found fn item
diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr
index 2077543ce30..e4f6ba573ca 100644
--- a/tests/ui/associated-types/substs-ppaux.verbose.stderr
+++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:16:17
    |
 LL |     fn bar<'a, T>() where T: 'a {}
-   |     --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::bar::<ReStatic, char>} defined here
+   |     --------------------------- associated function `bar` defined here
 ...
 LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::bar::<'static, char>;
    |            --   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:25:17
    |
 LL |     fn bar<'a, T>() where T: 'a {}
-   |     --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>} defined here
+   |     --------------------------- associated function `bar` defined here
 ...
 LL |     let x: () = <i8 as Foo<'static, 'static,  u32>>::bar::<'static, char>;
    |            --   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:33:17
    |
 LL |     fn baz() {}
-   |     -------- fn() {<i8 as Foo<ReStatic, ReStatic, u8>>::baz} defined here
+   |     -------- associated function `baz` defined here
 ...
 LL |     let x: () = <i8 as Foo<'static, 'static,  u8>>::baz;
    |            --   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
@@ -56,7 +56,7 @@ error[E0308]: mismatched types
   --> $DIR/substs-ppaux.rs:41:17
    |
 LL | fn foo<'z>() where &'z (): Sized {
-   | -------------------------------- fn() {foo::<ReStatic>} defined here
+   | -------------------------------- function `foo` defined here
 ...
 LL |     let x: () = foo::<'static>;
    |            --   ^^^^^^^^^^^^^^ expected `()`, found fn item
diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
index 9aae9013d1b..bd7aaf6fb6d 100644
--- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
+++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
@@ -4,7 +4,6 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied
 LL |     is_defaulted::<&'static u32>();
    |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
    |
-   = help: the trait `Signed` is implemented for `i32`
 note: required for `&'static u32` to implement `Defaulted`
   --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
    |
@@ -17,6 +16,11 @@ note: required by a bound in `is_defaulted`
    |
 LL | fn is_defaulted<T:Defaulted>() { }
    |                   ^^^^^^^^^ required by this bound in `is_defaulted`
+help: consider removing the leading `&`-reference
+   |
+LL -     is_defaulted::<&'static u32>();
+LL +     is_defaulted::<u32>();
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs
index b30548e19f9..49d5c0390bc 100644
--- a/tests/ui/c-variadic/issue-86053-1.rs
+++ b/tests/ui/c-variadic/issue-86053-1.rs
@@ -2,7 +2,7 @@
 // error-pattern:unexpected `self` parameter in function
 // error-pattern:`...` must be the last argument of a C-variadic function
 // error-pattern:cannot find type `F` in this scope
-// error-pattern:in type `&'a &'b usize`, reference has a longer lifetime than the data it references
+
 
 #![feature(c_variadic)]
 #![crate_type="lib"]
diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr
index d1f13d52362..5a02f4aa93a 100644
--- a/tests/ui/c-variadic/issue-86053-1.stderr
+++ b/tests/ui/c-variadic/issue-86053-1.stderr
@@ -76,24 +76,6 @@ help: you might be missing a type parameter
 LL | fn ordering4 < 'a , 'b, F     > ( a :            ,   self , self ,   self ,
    |                       +++
 
-error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
-  --> $DIR/issue-86053-1.rs:11:52
-   |
-LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
-   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/issue-86053-1.rs:10:16
-   |
-LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
-   |                ^^
-note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/issue-86053-1.rs:10:21
-   |
-LL | fn ordering4 < 'a , 'b     > ( a :            ,   self , self ,   self ,
-   |                     ^^
-
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0412, E0491.
-For more information about an error, try `rustc --explain E0412`.
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr
index c3e2f8e1646..eb4ff8305da 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr
@@ -15,8 +15,14 @@ LL | struct Foo<const N: usize> {}
 LL |     Foo::foo();
    |          ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `[u8; _]: Bar<[(); _]>`
+note: trait bound `[u8; _]: Bar<[(); _]>` was not satisfied
+  --> $DIR/issue-69654.rs:11:14
+   |
+LL | impl<const N: usize> Foo<N>
+   |                      ------
+LL | where
+LL |     [u8; N]: Bar<[(); N]>,
+   |              ^^^^^^^^^^^^ unsatisfied trait bound introduced here
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
index 0af5493f816..ea6f5f69276 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
@@ -17,7 +17,7 @@ LL |     Condition<{ LHS <= RHS }>: True
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:25:25
+  --> $DIR/issue-72787.rs:23:25
    |
 LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    |                         ^ cannot perform const operation using `I`
@@ -26,7 +26,7 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:25:36
+  --> $DIR/issue-72787.rs:23:36
    |
 LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    |                                    ^ cannot perform const operation using `J`
@@ -34,42 +34,5 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    = help: const parameters may only be used as standalone arguments, i.e. `J`
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
-  --> $DIR/issue-72787.rs:21:26
-   |
-LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^
-   |
-note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
-  --> $DIR/issue-72787.rs:10:1
-   |
-LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^
-...
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                          ^^^^
-
-error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
-  --> $DIR/issue-72787.rs:21:26
-   |
-LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^
-   |
-note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
-  --> $DIR/issue-72787.rs:10:1
-   |
-LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^
-...
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                          ^^^^
-
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs
index c651bf1c8de..657fec2e9cb 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs
@@ -19,8 +19,6 @@ struct S<const I: u32, const J: u32>;
 impl<const I: u32, const J: u32> S<I, J>
 where
     IsLessOrEqual<I, 8>: True,
-//[min]~^ Error type annotations needed
-//[min]~| Error type annotations needed
     IsLessOrEqual<J, 8>: True,
     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
 //[min]~^ Error generic parameters may not be used in const operations
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
index a08c9912527..6aa8ee13b79 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
@@ -23,8 +23,17 @@ LL |     let dst = Inline::<dyn Debug>::new(0);
    |
    = note: doesn't satisfy `dyn Debug: Sized`
    |
-   = note: the following trait bounds were not satisfied:
-           `dyn Debug: Sized`
+note: trait bound `dyn Debug: Sized` was not satisfied
+  --> $DIR/issue-80742.rs:20:6
+   |
+LL | impl<T> Inline<T>
+   |      ^  ---------
+   |      |
+   |      unsatisfied trait bound introduced here
+help: consider relaxing the type parameter's implicit `Sized` bound
+   |
+LL | impl<T: ?Sized> Inline<T>
+   |       ++++++++
 
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr
index 6e61dbbd8ee..1caf1617e21 100644
--- a/tests/ui/consts/const-match-check.eval1.stderr
+++ b/tests/ui/consts/const-match-check.eval1.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-match-check.rs:25:15
    |
 LL |     A = { let 0 = 0; 0 },
diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr
index 1b3b6e06c3d..f038ba1c8ed 100644
--- a/tests/ui/consts/const-match-check.eval2.stderr
+++ b/tests/ui/consts/const-match-check.eval2.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-match-check.rs:31:24
    |
 LL |     let x: [i32; { let 0 = 0; 0 }] = [];
diff --git a/tests/ui/consts/const-match-check.matchck.stderr b/tests/ui/consts/const-match-check.matchck.stderr
index bc8edfa7af9..b1921f8a41e 100644
--- a/tests/ui/consts/const-match-check.matchck.stderr
+++ b/tests/ui/consts/const-match-check.matchck.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-match-check.rs:4:22
    |
 LL | const X: i32 = { let 0 = 0; 0 };
@@ -12,7 +12,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
 LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
    |                  ++           ~~~~~~~~~~~
 
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-match-check.rs:8:23
    |
 LL | static Y: i32 = { let 0 = 0; 0 };
@@ -26,7 +26,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
 LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
    |                   ++           ~~~~~~~~~~~
 
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-match-check.rs:13:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
@@ -40,7 +40,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
 LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
    |                      ++           ~~~~~~~~~~~
 
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-match-check.rs:19:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs
index 2105c12a168..61bdf57ffdb 100644
--- a/tests/ui/consts/const-pattern-irrefutable.rs
+++ b/tests/ui/consts/const-pattern-irrefutable.rs
@@ -9,8 +9,20 @@ use foo::d;
 const a: u8 = 2;
 
 fn main() {
-    let a = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
-    let c = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
-    let d = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
+    let a = 4;
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+    //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
+    //~| HELP introduce a variable instead
+    let c = 4;
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+    //~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
+    //~| HELP introduce a variable instead
+    let d = 4;
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+    //~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
+    //~| HELP introduce a variable instead
     fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
 }
diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr
index a2b8f072c6e..c156ea1610c 100644
--- a/tests/ui/consts/const-pattern-irrefutable.stderr
+++ b/tests/ui/consts/const-pattern-irrefutable.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-pattern-irrefutable.rs:12:9
    |
 LL | const a: u8 = 2;
@@ -7,13 +7,14 @@ LL | const a: u8 = 2;
 LL |     let a = 4;
    |         ^
    |         |
-   |         interpreted as a constant pattern, not a new variable
+   |         patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+   |         missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `a_var`
    |
    = note: the matched value is of type `u8`
 
-error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
-  --> $DIR/const-pattern-irrefutable.rs:13:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/const-pattern-irrefutable.rs:17:9
    |
 LL |     pub const b: u8 = 2;
    |     --------------- constant defined here
@@ -21,13 +22,14 @@ LL |     pub const b: u8 = 2;
 LL |     let c = 4;
    |         ^
    |         |
-   |         interpreted as a constant pattern, not a new variable
+   |         patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+   |         missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `c_var`
    |
    = note: the matched value is of type `u8`
 
-error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
-  --> $DIR/const-pattern-irrefutable.rs:14:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/const-pattern-irrefutable.rs:22:9
    |
 LL |     pub const d: u8 = 2;
    |     --------------- constant defined here
@@ -35,7 +37,8 @@ LL |     pub const d: u8 = 2;
 LL |     let d = 4;
    |         ^
    |         |
-   |         interpreted as a constant pattern, not a new variable
+   |         patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
+   |         missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `d_var`
    |
    = note: the matched value is of type `u8`
diff --git a/tests/ui/consts/const_let_refutable.stderr b/tests/ui/consts/const_let_refutable.stderr
index d7e8c048f7d..d6119028f5b 100644
--- a/tests/ui/consts/const_let_refutable.stderr
+++ b/tests/ui/consts/const_let_refutable.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
+error[E0005]: refutable pattern in function argument
   --> $DIR/const_let_refutable.rs:3:16
    |
 LL | const fn slice(&[a, b]: &[i32]) -> i32 {
diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.rs b/tests/ui/consts/ct-var-in-collect_all_mismatches.rs
new file mode 100644
index 00000000000..5fb633de983
--- /dev/null
+++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.rs
@@ -0,0 +1,20 @@
+struct Foo<T, const N: usize> {
+    array: [T; N],
+}
+
+trait Bar<const N: usize> {}
+
+impl<T, const N: usize> Foo<T, N> {
+    fn trigger(self) {
+        self.unsatisfied()
+        //~^ ERROR the trait bound `T: Bar<N>` is not satisfied
+    }
+
+    fn unsatisfied(self)
+    where
+        T: Bar<N>,
+    {
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
new file mode 100644
index 00000000000..43fba2573ff
--- /dev/null
+++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `T: Bar<N>` is not satisfied
+  --> $DIR/ct-var-in-collect_all_mismatches.rs:9:14
+   |
+LL |         self.unsatisfied()
+   |              ^^^^^^^^^^^ the trait `Bar<N>` is not implemented for `T`
+   |
+note: required by a bound in `Foo::<T, N>::unsatisfied`
+  --> $DIR/ct-var-in-collect_all_mismatches.rs:15:12
+   |
+LL |     fn unsatisfied(self)
+   |        ----------- required by a bound in this
+LL |     where
+LL |         T: Bar<N>,
+   |            ^^^^^^ required by this bound in `Foo::<T, N>::unsatisfied`
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: Bar<N>, const N: usize> Foo<T, N> {
+   |       ++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr
index c4fddcf5f24..91b334b412b 100644
--- a/tests/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr
@@ -18,9 +18,6 @@ note: trait bound `NotClone: Clone` was not satisfied
    |
 LL | #[derive(Clone)]
    |          ^^^^^ unsatisfied trait bound introduced in this `derive` macro
-   = note: the following trait bounds were not satisfied:
-           `NotClone: Clone`
-           which is required by `Bar<NotClone>: Clone`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`
diff --git a/tests/ui/derives/issue-91492.stderr b/tests/ui/derives/issue-91492.stderr
index fbd48336d91..cee30ac50a6 100644
--- a/tests/ui/derives/issue-91492.stderr
+++ b/tests/ui/derives/issue-91492.stderr
@@ -42,8 +42,13 @@ LL | struct Object<T, A>(T, A);
 LL |     foo.use_clone();
    |         ^^^^^^^^^ method cannot be called on `Object<NoDerives, SomeDerives>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: Clone`
+note: trait bound `NoDerives: Clone` was not satisfied
+  --> $DIR/issue-91492.rs:18:9
+   |
+LL | impl<T: Clone, A: Default> Object<T, A> {
+   |         ^^^^^              ------------
+   |         |
+   |         unsatisfied trait bound introduced here
 help: consider annotating `NoDerives` with `#[derive(Clone)]`
    |
 LL | #[derive(Clone)]
diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr
index 12be269565d..bf0bb3fbdf8 100644
--- a/tests/ui/derives/issue-91550.stderr
+++ b/tests/ui/derives/issue-91550.stderr
@@ -30,8 +30,13 @@ LL | struct Object<T>(T);
 LL |     foo.use_eq();
    |         ^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: Eq`
+note: trait bound `NoDerives: Eq` was not satisfied
+  --> $DIR/issue-91550.rs:15:9
+   |
+LL | impl<T: Eq> Object<T> {
+   |         ^^  ---------
+   |         |
+   |         unsatisfied trait bound introduced here
 help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
    |
 LL | #[derive(Eq, PartialEq)]
@@ -49,8 +54,13 @@ LL | struct Object<T>(T);
 LL |     foo.use_ord();
    |         ^^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: Ord`
+note: trait bound `NoDerives: Ord` was not satisfied
+  --> $DIR/issue-91550.rs:18:9
+   |
+LL | impl<T: Ord> Object<T> {
+   |         ^^^  ---------
+   |         |
+   |         unsatisfied trait bound introduced here
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
@@ -71,9 +81,16 @@ LL | struct Object<T>(T);
 LL |     foo.use_ord_and_partial_ord();
    |         ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: Ord`
-           `NoDerives: PartialOrd`
+note: the following trait bounds were not satisfied:
+      `NoDerives: Ord`
+      `NoDerives: PartialOrd`
+  --> $DIR/issue-91550.rs:21:9
+   |
+LL | impl<T: Ord + PartialOrd> Object<T> {
+   |         ^^^   ^^^^^^^^^^  ---------
+   |         |     |
+   |         |     unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs
new file mode 100644
index 00000000000..7e6b7140855
--- /dev/null
+++ b/tests/ui/diagnostic-width/E0271.rs
@@ -0,0 +1,33 @@
+// compile-flags: --diagnostic-width=40
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+trait Future {
+    type Error;
+}
+
+impl<T, E> Future for Result<T, E> {
+    type Error = E;
+}
+
+impl<T> Future for Option<T> {
+    type Error = ();
+}
+
+struct Foo;
+
+fn foo() -> Box<dyn Future<Error=Foo>> {
+    Box::new( //~ ERROR E0271
+        Ok::<_, ()>(
+            Err::<(), _>(
+                Ok::<_, ()>(
+                    Err::<(), _>(
+                        Ok::<_, ()>(
+                            Err::<(), _>(Some(5))
+                        )
+                    )
+                )
+            )
+        )
+    )
+}
+fn main() {
+}
diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.stderr
new file mode 100644
index 00000000000..ed7b6651d01
--- /dev/null
+++ b/tests/ui/diagnostic-width/E0271.stderr
@@ -0,0 +1,23 @@
+error[E0271]: type mismatch resolving `<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ...>>, ...>>, ...> as Future>::Error == Foo`
+  --> $DIR/E0271.rs:18:5
+   |
+LL | /     Box::new(
+LL | |         Ok::<_, ()>(
+LL | |             Err::<(), _>(
+LL | |                 Ok::<_, ()>(
+...  |
+LL | |         )
+LL | |     )
+   | |_____^ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
+   |
+note: expected this to be `Foo`
+  --> $DIR/E0271.rs:8:18
+   |
+LL |     type Error = E;
+   |                  ^
+   = note: required for the cast from `Result<Result<..., ...>, ...>` to the object type `dyn Future<Error = Foo>`
+   = note: the full name for the casted type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271/E0271.long-type-hash.txt'
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/dyn-star/dyn-star-to-dyn.rs b/tests/ui/dyn-star/dyn-star-to-dyn.rs
new file mode 100644
index 00000000000..a6d9df9523a
--- /dev/null
+++ b/tests/ui/dyn-star/dyn-star-to-dyn.rs
@@ -0,0 +1,9 @@
+// build-pass
+
+#![feature(dyn_star)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+fn main() {
+    let x: dyn* Send = &();
+    let x = Box::new(x) as Box<dyn Send>;
+}
diff --git a/tests/ui/dyn-star/dyn-star-to-dyn.stderr b/tests/ui/dyn-star/dyn-star-to-dyn.stderr
new file mode 100644
index 00000000000..03aedf5f797
--- /dev/null
+++ b/tests/ui/dyn-star/dyn-star-to-dyn.stderr
@@ -0,0 +1,11 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/dyn-star-to-dyn.rs:3:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/empty/empty-never-array.rs b/tests/ui/empty/empty-never-array.rs
index 3de2b1a78a3..fd93346101d 100644
--- a/tests/ui/empty/empty-never-array.rs
+++ b/tests/ui/empty/empty-never-array.rs
@@ -8,7 +8,8 @@ enum Helper<T, U> {
 
 fn transmute<T, U>(t: T) -> U {
     let Helper::U(u) = Helper::T(t, []);
-    //~^ ERROR refutable pattern in local binding: `Helper::T(_, _)` not covered
+    //~^ ERROR refutable pattern in local binding
+    //~| `Helper::T(_, _)` not covered
     u
 }
 
diff --git a/tests/ui/empty/empty-never-array.stderr b/tests/ui/empty/empty-never-array.stderr
index adf78274368..a488e484b2b 100644
--- a/tests/ui/empty/empty-never-array.stderr
+++ b/tests/ui/empty/empty-never-array.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `Helper::T(_, _)` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/empty-never-array.rs:10:9
    |
 LL |     let Helper::U(u) = Helper::T(t, []);
@@ -7,18 +7,14 @@ LL |     let Helper::U(u) = Helper::T(t, []);
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Helper<T, U>` defined here
-  --> $DIR/empty-never-array.rs:4:5
+  --> $DIR/empty-never-array.rs:3:6
    |
 LL | enum Helper<T, U> {
-   |      ------
+   |      ^^^^^^
 LL |     T(T, [!; 0]),
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `Helper<T, U>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
-   |     ++++++++++                                     ++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Helper::U(u) = Helper::T(t, []) else { todo!() };
    |                                         ++++++++++++++++
diff --git a/tests/ui/error-codes/E0005.stderr b/tests/ui/error-codes/E0005.stderr
index 0f179259356..4692b66413d 100644
--- a/tests/ui/error-codes/E0005.stderr
+++ b/tests/ui/error-codes/E0005.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `None` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/E0005.rs:3:9
    |
 LL |     let Some(y) = x;
@@ -6,17 +6,8 @@ LL |     let Some(y) = x;
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-note: `Option<i32>` defined here
-  --> $SRC_DIR/core/src/option.rs:LL:COL
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-   = note: not covered
    = note: the matched value is of type `Option<i32>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let y = if let Some(y) = x { y } else { todo!() };
-   |     ++++++++++                 ++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Some(y) = x else { todo!() };
    |                     ++++++++++++++++
diff --git a/tests/ui/error-codes/E0297.stderr b/tests/ui/error-codes/E0297.stderr
index 903422f3b9b..293028f5f68 100644
--- a/tests/ui/error-codes/E0297.stderr
+++ b/tests/ui/error-codes/E0297.stderr
@@ -1,14 +1,9 @@
-error[E0005]: refutable pattern in `for` loop binding: `None` not covered
+error[E0005]: refutable pattern in `for` loop binding
   --> $DIR/E0297.rs:4:9
    |
 LL |     for Some(x) in xs {}
    |         ^^^^^^^ pattern `None` not covered
    |
-note: `Option<i32>` defined here
-  --> $SRC_DIR/core/src/option.rs:LL:COL
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-   = note: not covered
    = note: the matched value is of type `Option<i32>`
 
 error: aborting due to previous error
diff --git a/tests/ui/error-codes/E0311.fixed b/tests/ui/error-codes/E0311.fixed
new file mode 100644
index 00000000000..4410a4d707a
--- /dev/null
+++ b/tests/ui/error-codes/E0311.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
+    with_restriction::<T>(x) //~ ERROR E0311
+}
+
+fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/error-codes/E0311.rs b/tests/ui/error-codes/E0311.rs
index 566b518b433..99e454f4d75 100644
--- a/tests/ui/error-codes/E0311.rs
+++ b/tests/ui/error-codes/E0311.rs
@@ -1,3 +1,7 @@
+// run-rustfix
+
+#![allow(warnings)]
+
 fn no_restriction<T>(x: &()) -> &() {
     with_restriction::<T>(x) //~ ERROR E0311
 }
diff --git a/tests/ui/error-codes/E0311.stderr b/tests/ui/error-codes/E0311.stderr
index 9873b5ae6ff..b0e6dd1e272 100644
--- a/tests/ui/error-codes/E0311.stderr
+++ b/tests/ui/error-codes/E0311.stderr
@@ -1,23 +1,23 @@
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/E0311.rs:2:5
+  --> $DIR/E0311.rs:6:5
    |
 LL |     with_restriction::<T>(x)
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/E0311.rs:1:25
+  --> $DIR/E0311.rs:5:25
    |
 LL | fn no_restriction<T>(x: &()) -> &() {
    |                         ^^^
 note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/E0311.rs:2:5
+  --> $DIR/E0311.rs:6:5
    |
 LL |     with_restriction::<T>(x)
    |     ^^^^^^^^^^^^^^^^^^^^^
 help: consider adding an explicit lifetime bound...
    |
-LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
-   |                   +++  ++++
+LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
+   |                   +++  ++++      ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index e253e4791e8..49e7ab6082c 100644
--- a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/feature-gate-exhaustive-patterns.rs:8:9
    |
 LL |     let Ok(_x) = foo();
@@ -6,17 +6,8 @@ LL |     let Ok(_x) = foo();
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-note: `Result<u32, !>` defined here
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-   = note: not covered
    = note: the matched value is of type `Result<u32, !>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let _x = if let Ok(_x) = foo() { _x } else { todo!() };
-   |     +++++++++++                    +++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Ok(_x) = foo() else { todo!() };
    |                        ++++++++++++++++
diff --git a/tests/ui/for/for-loop-refutable-pattern-error-message.stderr b/tests/ui/for/for-loop-refutable-pattern-error-message.stderr
index 20b689aa5e0..49a82a6769d 100644
--- a/tests/ui/for/for-loop-refutable-pattern-error-message.stderr
+++ b/tests/ui/for/for-loop-refutable-pattern-error-message.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in `for` loop binding: `&i32::MIN..=0_i32` and `&2_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in `for` loop binding
   --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
    |
 LL |     for &1 in [1].iter() {}
diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
index 36974b3df5e..83655341d6a 100644
--- a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
+++ b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
@@ -11,7 +11,7 @@ trait M {
 
 impl<T: X<Y<i32> = i32>> M for T {}
 //~^ NOTE trait bound `<S as X>::Y<i32> = i32` was not satisfied
-//~| NOTE unsatisfied trait bound introduced here
+//~| NOTE
 //~| NOTE
 //~| NOTE
 
diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
index 381865db07d..810f7c28c00 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
+++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+error[E0271]: type mismatch resolving `for<'r> <L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
   --> $DIR/issue-62203-hrtb-ice.rs:39:9
    |
 LL |       let v = Unit2.m(
@@ -10,7 +10,7 @@ LL | |             f: |x| {
 ...  |
 LL | |             },
 LL | |         },
-   | |_________^ type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+   | |_________^ type mismatch resolving `for<'r> <L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
    |
 note: expected this to be `<_ as Ty<'_>>::V`
   --> $DIR/issue-62203-hrtb-ice.rs:21:14
diff --git a/tests/ui/impl-trait/bound-normalization-fail.stderr b/tests/ui/impl-trait/bound-normalization-fail.stderr
index a9fa2da569f..f04a753a0e8 100644
--- a/tests/ui/impl-trait/bound-normalization-fail.stderr
+++ b/tests/ui/impl-trait/bound-normalization-fail.stderr
@@ -1,8 +1,8 @@
-error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait>::Assoc`
   --> $DIR/bound-normalization-fail.rs:25:32
    |
 LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait>::Assoc`
 LL |
 LL |         Foo(())
    |         ------- return type was inferred to be `Foo<()>` here
@@ -28,11 +28,11 @@ LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
    = note: see issue #103532 <https://github.com/rust-lang/rust/issues/103532> for more information
    = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable
 
-error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'a>>::Assoc`
+error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait<'a>>::Assoc`
   --> $DIR/bound-normalization-fail.rs:41:41
    |
 LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'a>>::Assoc`
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as Trait<'a>>::Assoc`
 ...
 LL |         Foo(())
    |         ------- return type was inferred to be `Foo<()>` here
diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr
index 08602185f50..18bb63745d7 100644
--- a/tests/ui/impl-trait/in-trait/issue-102140.stderr
+++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr
@@ -2,11 +2,15 @@ error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
   --> $DIR/issue-102140.rs:23:22
    |
 LL |         MyTrait::foo(&self)
-   |         ------------ -^^^^
-   |         |            |
-   |         |            the trait `MyTrait` is not implemented for `&dyn MyTrait`
-   |         |            help: consider removing the leading `&`-reference
+   |         ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+   |         |
    |         required by a bound introduced by this call
+   |
+help: consider removing the leading `&`-reference
+   |
+LL -         MyTrait::foo(&self)
+LL +         MyTrait::foo(self)
+   |
 
 error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
   --> $DIR/issue-102140.rs:23:9
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index bc342dc4689..d872291c870 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -23,8 +23,13 @@ LL | pub struct RawImpl<T>(PhantomData<T>);
 LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
    | ----------------------------------------- function or associated item `foo` not found for this struct
    |
-   = note: the following trait bounds were not satisfied:
-           `RawImpl<()>: Raw<()>`
+note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
+  --> $DIR/issue-62742.rs:28:20
+   |
+LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
+   |                    ^^^^^^  --------------
+   |                    |
+   |                    unsatisfied trait bound introduced here
 note: the trait `Raw` must be implemented
   --> $DIR/issue-62742.rs:12:1
    |
diff --git a/tests/ui/issues/issue-15381.rs b/tests/ui/issues/issue-15381.rs
index 392fb1b24dd..23b266bef1d 100644
--- a/tests/ui/issues/issue-15381.rs
+++ b/tests/ui/issues/issue-15381.rs
@@ -2,7 +2,8 @@ fn main() {
     let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
 
     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
-        //~^ ERROR refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not
+        //~^ ERROR refutable pattern in `for` loop binding
+        //~| patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
         println!("y={}", y);
     }
 }
diff --git a/tests/ui/issues/issue-15381.stderr b/tests/ui/issues/issue-15381.stderr
index c4667ce1c8b..085958411cc 100644
--- a/tests/ui/issues/issue-15381.stderr
+++ b/tests/ui/issues/issue-15381.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
+error[E0005]: refutable pattern in `for` loop binding
   --> $DIR/issue-15381.rs:4:9
    |
 LL |     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
diff --git a/tests/ui/issues/issue-35241.stderr b/tests/ui/issues/issue-35241.stderr
index 42a78ed97e0..d600e934bd5 100644
--- a/tests/ui/issues/issue-35241.stderr
+++ b/tests/ui/issues/issue-35241.stderr
@@ -2,15 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/issue-35241.rs:3:20
    |
 LL | struct Foo(u32);
-   | ---------- fn(u32) -> Foo {Foo} defined here
+   | ---------- `Foo` defines a struct constructor here, which should be called
 LL |
 LL | fn test() -> Foo { Foo }
-   |              ---   ^^^ expected struct `Foo`, found fn item
+   |              ---   ^^^ expected struct `Foo`, found struct constructor
    |              |
    |              expected `Foo` because of return type
    |
-   = note: expected struct `Foo`
-             found fn item `fn(u32) -> Foo {Foo}`
+   = note:          expected struct `Foo`
+           found struct constructor `fn(u32) -> Foo {Foo}`
 help: use parentheses to construct this tuple struct
    |
 LL | fn test() -> Foo { Foo(/* u32 */) }
diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs
new file mode 100644
index 00000000000..882a1d13954
--- /dev/null
+++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x = Some(()).iter().map(|()| 1).sum::<f32>();
+    //~^ ERROR a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}`
+}
diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
new file mode 100644
index 00000000000..3cb5e44c711
--- /dev/null
+++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
@@ -0,0 +1,24 @@
+error[E0277]: a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}`
+  --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:41
+   |
+LL |     let x = Some(()).iter().map(|()| 1).sum::<f32>();
+   |                                         ^^^ value of type `f32` cannot be made by summing a `std::iter::Iterator<Item={integer}>`
+   |
+   = help: the trait `Sum<{integer}>` is not implemented for `f32`
+   = help: the following other types implement trait `Sum<A>`:
+             <f32 as Sum<&'a f32>>
+             <f32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:29
+   |
+LL |     let x = Some(()).iter().map(|()| 1).sum::<f32>();
+   |             -------- ------ ^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+   |             |        |
+   |             |        `Iterator::Item` is `&()` here
+   |             this expression has type `Option<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/kindck/kindck-copy.stderr b/tests/ui/kindck/kindck-copy.stderr
index 9af89159a8c..aee2aa98a60 100644
--- a/tests/ui/kindck/kindck-copy.stderr
+++ b/tests/ui/kindck/kindck-copy.stderr
@@ -4,12 +4,16 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'static mut isize>();
    |                   ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
    |
-   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
 LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert_copy::<&'static mut isize>();
+LL +     assert_copy::<isize>();
+   |
 
 error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
   --> $DIR/kindck-copy.rs:28:19
@@ -17,12 +21,16 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'a mut isize>();
    |                   ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
    |
-   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
 LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert_copy::<&'a mut isize>();
+LL +     assert_copy::<isize>();
+   |
 
 error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
   --> $DIR/kindck-copy.rs:31:19
diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed
new file mode 100644
index 00000000000..f977f0bd3a8
--- /dev/null
+++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
+    with_restriction::<T>(x) //~ ERROR the parameter type `T` may not live long enough
+}
+
+fn with_restriction<'b, T: 'b>(x: &'b ()) -> &'b () {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs
index 645bc7db0dd..d6ce112ec93 100644
--- a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs
+++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs
@@ -1,3 +1,7 @@
+// run-rustfix
+
+#![allow(warnings)]
+
 fn no_restriction<T>(x: &()) -> &() {
     with_restriction::<T>(x) //~ ERROR the parameter type `T` may not live long enough
 }
diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
index 31fd8a4d633..2d58d3a02f3 100644
--- a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
+++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
@@ -1,23 +1,23 @@
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:2:5
+  --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:6:5
    |
 LL |     with_restriction::<T>(x)
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:1:25
+  --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:5:25
    |
 LL | fn no_restriction<T>(x: &()) -> &() {
    |                         ^^^
 note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:2:5
+  --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:6:5
    |
 LL |     with_restriction::<T>(x)
    |     ^^^^^^^^^^^^^^^^^^^^^
 help: consider adding an explicit lifetime bound...
    |
-LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
-   |                   +++  ++++
+LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
+   |                   +++  ++++      ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
index 8846efba871..f3db56d1d53 100644
--- a/tests/ui/methods/method-not-found-generic-arg-elision.stderr
+++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
@@ -88,9 +88,16 @@ LL | struct Struct<T> {
 LL |     s.method();
    |       ^^^^^^ method cannot be called on `Struct<f64>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `f64: Eq`
-           `f64: Ord`
+note: the following trait bounds were not satisfied:
+      `f64: Eq`
+      `f64: Ord`
+  --> $DIR/method-not-found-generic-arg-elision.rs:74:36
+   |
+LL | impl<T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord> Struct<T> {
+   |                                    ^^                ^^^  ---------
+   |                                    |                 |
+   |                                    |                 unsatisfied trait bound introduced here
+   |                                    unsatisfied trait bound introduced here
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr
index 9e94aa2c7b3..968e285af7f 100644
--- a/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr
+++ b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr
@@ -7,20 +7,16 @@ LL | struct Foo<T> {
 LL |         self.foo();
    |              ^^^ method cannot be called on `&Foo<T>` due to unsatisfied trait bounds
    |
-note: trait bound `T: Default` was not satisfied
+note: the following trait bounds were not satisfied:
+      `T: Bar`
+      `T: Default`
   --> $DIR/missing-trait-bounds-for-method-call.rs:10:9
    |
 LL | impl<T: Default + Bar> Bar for Foo<T> {}
-   |         ^^^^^^^        ---     ------
-   |         |
+   |         ^^^^^^^   ^^^  ---     ------
+   |         |         |
+   |         |         unsatisfied trait bound introduced here
    |         unsatisfied trait bound introduced here
-note: trait bound `T: Bar` was not satisfied
-  --> $DIR/missing-trait-bounds-for-method-call.rs:10:19
-   |
-LL | impl<T: Default + Bar> Bar for Foo<T> {}
-   |                   ^^^  ---     ------
-   |                   |
-   |                   unsatisfied trait bound introduced here
 help: consider restricting the type parameters to satisfy the trait bounds
    |
 LL | struct Foo<T> where T: Bar, T: Default {
diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr
index e41baf86218..40c7c1d1067 100644
--- a/tests/ui/never_type/exhaustive_patterns.stderr
+++ b/tests/ui/never_type/exhaustive_patterns.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `Either::B(_)` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/exhaustive_patterns.rs:20:9
    |
 LL |     let Either::A(()) = foo();
@@ -7,13 +7,13 @@ LL |     let Either::A(()) = foo();
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Either<(), !>` defined here
-  --> $DIR/exhaustive_patterns.rs:12:5
+  --> $DIR/exhaustive_patterns.rs:10:6
    |
 LL | enum Either<A, B> {
-   |      ------
+   |      ^^^^^^
 LL |     A(A),
 LL |     B(inner::Wrapper<B>),
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `Either<(), !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/tests/ui/not-panic/not-panic-safe-4.stderr b/tests/ui/not-panic/not-panic-safe-4.stderr
index fc1c594d0d4..9428c125651 100644
--- a/tests/ui/not-panic/not-panic-safe-4.stderr
+++ b/tests/ui/not-panic/not-panic-safe-4.stderr
@@ -12,6 +12,11 @@ note: required by a bound in `assert`
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert::<&RefCell<i32>>();
+LL +     assert::<RefCell<i32>>();
+   |
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-4.rs:9:14
@@ -28,6 +33,11 @@ note: required by a bound in `assert`
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert::<&RefCell<i32>>();
+LL +     assert::<RefCell<i32>>();
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/not-panic/not-panic-safe.rs b/tests/ui/not-panic/not-panic-safe.rs
index 4165c5dc13a..1b3c6482ce9 100644
--- a/tests/ui/not-panic/not-panic-safe.rs
+++ b/tests/ui/not-panic/not-panic-safe.rs
@@ -5,6 +5,6 @@ use std::panic::UnwindSafe;
 fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
-    assert::<&mut i32>();
-    //~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
+    assert::<&mut &mut &i32>();
+    //~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
 }
diff --git a/tests/ui/not-panic/not-panic-safe.stderr b/tests/ui/not-panic/not-panic-safe.stderr
index 2cd51a43998..37a6aee3906 100644
--- a/tests/ui/not-panic/not-panic-safe.stderr
+++ b/tests/ui/not-panic/not-panic-safe.stderr
@@ -1,19 +1,21 @@
-error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
+error[E0277]: the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
   --> $DIR/not-panic-safe.rs:8:14
    |
-LL |     assert::<&mut i32>();
-   |              -^^^^^^^
-   |              |
-   |              `&mut i32` may not be safely transferred across an unwind boundary
-   |              help: consider removing the leading `&`-reference
+LL |     assert::<&mut &mut &i32>();
+   |              ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
    |
-   = help: the trait `UnwindSafe` is not implemented for `&mut i32`
-   = note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
+   = help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
+   = note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe.rs:5:14
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing 2 leading `&`-references
+   |
+LL -     assert::<&mut &mut &i32>();
+LL +     assert::<&i32>();
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
index 95b22ac0594..4adcf4feee9 100644
--- a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
+++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:2:10
    |
 LL |     let (0 | (1 | 2)) = 0;
diff --git a/tests/ui/pattern/usefulness/issue-31561.rs b/tests/ui/pattern/usefulness/issue-31561.rs
index 5b878851a31..82414f0418b 100644
--- a/tests/ui/pattern/usefulness/issue-31561.rs
+++ b/tests/ui/pattern/usefulness/issue-31561.rs
@@ -6,5 +6,6 @@ enum Thing {
 
 fn main() {
     let Thing::Foo(y) = Thing::Foo(1);
-    //~^ ERROR refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered
+    //~^ ERROR refutable pattern in local binding
+    //~| `Thing::Bar` and `Thing::Baz` not covered
 }
diff --git a/tests/ui/pattern/usefulness/issue-31561.stderr b/tests/ui/pattern/usefulness/issue-31561.stderr
index 20f2f09500a..5367de5e513 100644
--- a/tests/ui/pattern/usefulness/issue-31561.stderr
+++ b/tests/ui/pattern/usefulness/issue-31561.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/issue-31561.rs:8:9
    |
 LL |     let Thing::Foo(y) = Thing::Foo(1);
@@ -7,21 +7,17 @@ LL |     let Thing::Foo(y) = Thing::Foo(1);
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Thing` defined here
-  --> $DIR/issue-31561.rs:3:5
+  --> $DIR/issue-31561.rs:1:6
    |
 LL | enum Thing {
-   |      -----
+   |      ^^^^^
 LL |     Foo(u8),
 LL |     Bar,
-   |     ^^^ not covered
+   |     --- not covered
 LL |     Baz
-   |     ^^^ not covered
+   |     --- not covered
    = note: the matched value is of type `Thing`
-help: you might want to use `if let` to ignore the variants that aren't matched
-   |
-LL |     let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
-   |     ++++++++++                                   ++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variants that aren't matched
+help: you might want to use `let else` to handle the variants that aren't matched
    |
 LL |     let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
    |                                       ++++++++++++++++
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
index af42fc1aeb4..5145f769075 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
@@ -15,9 +15,6 @@ enum E {
     //~^ NOTE `E` defined here
     //~| NOTE `E` defined here
     //~| NOTE `E` defined here
-    //~| NOTE `E` defined here
-    //~| NOTE `E` defined here
-    //~| NOTE `E` defined here
     //~| NOTE  not covered
     //~| NOTE  not covered
     //~| NOTE  not covered
@@ -41,37 +38,41 @@ fn by_val(e: E) {
         E::A => {}
     }
 
-    let E::A = e; //~ ERROR refutable pattern in local binding: `E::B` and `E::C` not covered
-    //~^ NOTE patterns `E::B` and `E::C` not covered
+    let E::A = e;
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `E::B` and `E::C` not covered
     //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
     //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
     //~| NOTE the matched value is of type `E`
 }
 
 fn by_ref_once(e: &E) {
-    match e { //~ ERROR non-exhaustive patterns: `&E::B` and `&E::C` not covered
-    //~^ NOTE patterns `&E::B` and `&E::C` not covered
+    match e {
+    //~^ ERROR non-exhaustive patterns
+    //~| patterns `&E::B` and `&E::C` not covered
     //~| NOTE the matched value is of type `&E`
         E::A => {}
     }
 
-    let E::A = e; //~ ERROR refutable pattern in local binding: `&E::B` and `&E::C` not covered
-    //~^ NOTE patterns `&E::B` and `&E::C` not covered
+    let E::A = e;
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `&E::B` and `&E::C` not covered
     //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
     //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
     //~| NOTE the matched value is of type `&E`
 }
 
 fn by_ref_thrice(e: & &mut &E) {
-    match e { //~ ERROR non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered
-    //~^ NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered
+    match e {
+    //~^ ERROR non-exhaustive patterns
+    //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
     //~| NOTE the matched value is of type `&&mut &E`
         E::A => {}
     }
 
     let E::A = e;
-    //~^ ERROR refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered
-    //~| NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
     //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
     //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
     //~| NOTE the matched value is of type `&&mut &E`
@@ -83,20 +84,21 @@ enum Opt {
     Some(u8),
     None,
     //~^ NOTE `Opt` defined here
-    //~| NOTE `Opt` defined here
     //~| NOTE not covered
     //~| NOTE not covered
 }
 
 fn ref_pat(e: Opt) {
-    match e {//~ ERROR non-exhaustive patterns: `Opt::None` not covered
-        //~^ NOTE pattern `Opt::None` not covered
+    match e {
+        //~^ ERROR non-exhaustive patterns
+        //~| pattern `Opt::None` not covered
         //~| NOTE the matched value is of type `Opt`
         Opt::Some(ref _x) => {}
     }
 
-    let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `Opt::None` not covered
-    //~^ NOTE the matched value is of type `Opt`
+    let Opt::Some(ref _x) = e;
+    //~^ ERROR refutable pattern in local binding
+    //~| NOTE the matched value is of type `Opt`
     //~| NOTE pattern `Opt::None` not covered
     //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
     //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
index 678c9b2ab58..769d4070fb5 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:38:11
+  --> $DIR/non-exhaustive-defined-here.rs:35:11
    |
 LL |     match e1 {
    |           ^^ patterns `E::B` and `E::C` not covered
@@ -22,8 +22,8 @@ LL ~         E::A => {}
 LL +         E::B | E::C => todo!()
    |
 
-error[E0005]: refutable pattern in local binding: `E::B` and `E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:44:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/non-exhaustive-defined-here.rs:41:9
    |
 LL |     let E::A = e;
    |         ^^^^ patterns `E::B` and `E::C` not covered
@@ -31,16 +31,16 @@ LL |     let E::A = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:14:5
+  --> $DIR/non-exhaustive-defined-here.rs:6:6
    |
 LL | enum E {
-   |      -
+   |      ^
 ...
 LL |     B,
-   |     ^ not covered
+   |     - not covered
 ...
 LL |     C
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `E`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
@@ -48,7 +48,7 @@ LL |     if let E::A = e { todo!() }
    |     ++              ~~~~~~~~~~~
 
 error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:52:11
+  --> $DIR/non-exhaustive-defined-here.rs:50:11
    |
 LL |     match e {
    |           ^ patterns `&E::B` and `&E::C` not covered
@@ -71,8 +71,8 @@ LL ~         E::A => {}
 LL +         &E::B | &E::C => todo!()
    |
 
-error[E0005]: refutable pattern in local binding: `&E::B` and `&E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:58:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/non-exhaustive-defined-here.rs:57:9
    |
 LL |     let E::A = e;
    |         ^^^^ patterns `&E::B` and `&E::C` not covered
@@ -80,16 +80,16 @@ LL |     let E::A = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:14:5
+  --> $DIR/non-exhaustive-defined-here.rs:6:6
    |
 LL | enum E {
-   |      -
+   |      ^
 ...
 LL |     B,
-   |     ^ not covered
+   |     - not covered
 ...
 LL |     C
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `&E`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
@@ -120,8 +120,8 @@ LL ~         E::A => {}
 LL +         &&mut &E::B | &&mut &E::C => todo!()
    |
 
-error[E0005]: refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:72:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/non-exhaustive-defined-here.rs:73:9
    |
 LL |     let E::A = e;
    |         ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
@@ -129,16 +129,16 @@ LL |     let E::A = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `E` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:14:5
+  --> $DIR/non-exhaustive-defined-here.rs:6:6
    |
 LL | enum E {
-   |      -
+   |      ^
 ...
 LL |     B,
-   |     ^ not covered
+   |     - not covered
 ...
 LL |     C
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `&&mut &E`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
@@ -152,7 +152,7 @@ LL |     match e {
    |           ^ pattern `Opt::None` not covered
    |
 note: `Opt` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:84:5
+  --> $DIR/non-exhaustive-defined-here.rs:85:5
    |
 LL | enum Opt {
    |      ---
@@ -166,8 +166,8 @@ LL ~         Opt::Some(ref _x) => {}
 LL +         Opt::None => todo!()
    |
 
-error[E0005]: refutable pattern in local binding: `Opt::None` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:98:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/non-exhaustive-defined-here.rs:99:9
    |
 LL |     let Opt::Some(ref _x) = e;
    |         ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered
@@ -175,19 +175,15 @@ LL |     let Opt::Some(ref _x) = e;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Opt` defined here
-  --> $DIR/non-exhaustive-defined-here.rs:84:5
+  --> $DIR/non-exhaustive-defined-here.rs:81:6
    |
 LL | enum Opt {
-   |      ---
+   |      ^^^
 ...
 LL |     None,
-   |     ^^^^ not covered
+   |     ---- not covered
    = note: the matched value is of type `Opt`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
-   |     +++++++++++                           +++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Opt::Some(ref _x) = e else { todo!() };
    |                               ++++++++++++++++
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.rs b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs
index 7c9aa51e748..7a3e991d593 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-errors.rs
+++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs
@@ -1,7 +1,9 @@
 fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
-//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
+//~^ ERROR refutable pattern in function argument
+//~| `(_, _)` not covered
 
 fn main() {
     let (1, (Some(1), 2..=3)) = (1, (None, 2));
-    //~^ ERROR refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
+    //~^ ERROR refutable pattern in local binding
+    //~| `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
 }
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
index d1dacc822e9..c518de47740 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
+++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in function argument: `(_, _)` not covered
+error[E0005]: refutable pattern in function argument
   --> $DIR/refutable-pattern-errors.rs:1:9
    |
 LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
@@ -6,8 +6,8 @@ LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
    |
    = note: the matched value is of type `(isize, (Option<isize>, isize))`
 
-error[E0005]: refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
-  --> $DIR/refutable-pattern-errors.rs:5:9
+error[E0005]: refutable pattern in local binding
+  --> $DIR/refutable-pattern-errors.rs:6:9
    |
 LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
    |         ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
index a2d9e1935de..17dc38ab25d 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
@@ -1,5 +1,6 @@
 fn main() {
     let f = |3: isize| println!("hello");
-    //~^ ERROR refutable pattern in function argument: `_` not covered
+    //~^ ERROR refutable pattern in function argument
+    //~| `_` not covered
     f(4);
 }
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
index c9d8cf43f95..55f0b2319fb 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in function argument: `_` not covered
+error[E0005]: refutable pattern in function argument
   --> $DIR/refutable-pattern-in-fn-arg.rs:2:14
    |
 LL |     let f = |3: isize| println!("hello");
diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs
index 120d08894f8..5826a18b571 100644
--- a/tests/ui/pin-macro/cant_access_internals.rs
+++ b/tests/ui/pin-macro/cant_access_internals.rs
@@ -1,5 +1,4 @@
 // edition:2018
-#![feature(pin_macro)]
 
 use core::{
     marker::PhantomPinned,
diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr
index 060c9c48c21..d43027657f0 100644
--- a/tests/ui/pin-macro/cant_access_internals.stderr
+++ b/tests/ui/pin-macro/cant_access_internals.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'unsafe_pin_internals'
-  --> $DIR/cant_access_internals.rs:12:15
+  --> $DIR/cant_access_internals.rs:11:15
    |
 LL |     mem::take(phantom_pinned.pointer);
    |               ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs
index ca2b6cf7593..59774bc753d 100644
--- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs
+++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs
@@ -1,5 +1,4 @@
 // edition:2018
-#![feature(pin_macro)]
 
 use core::{
     convert::identity,
diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
index fc1be052fb7..4ecc6370d3c 100644
--- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
+++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/lifetime_errors_on_promotion_misusage.rs:12:35
+  --> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35
    |
 LL |     let phantom_pinned = identity(pin!(PhantomPinned));
    |                                   ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
@@ -13,7 +13,7 @@ LL |     stuff(phantom_pinned)
    = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/lifetime_errors_on_promotion_misusage.rs:19:30
+  --> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30
    |
 LL |     let phantom_pinned = {
    |         -------------- borrow later stored here
diff --git a/tests/ui/privacy/issue-75906.stderr b/tests/ui/privacy/issue-75906.stderr
index 4c6a68646ad..600dc7c876f 100644
--- a/tests/ui/privacy/issue-75906.stderr
+++ b/tests/ui/privacy/issue-75906.stderr
@@ -9,6 +9,10 @@ note: constructor is not visible here due to private fields
    |
 LL |     pub struct Bar(u8);
    |                    ^^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub struct Bar(pub u8);
+   |                    +++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/privacy/issue-75907.rs b/tests/ui/privacy/issue-75907.rs
index 6da99cf6435..3bed841d13e 100644
--- a/tests/ui/privacy/issue-75907.rs
+++ b/tests/ui/privacy/issue-75907.rs
@@ -2,7 +2,7 @@
 
 mod foo {
     pub(crate) struct Foo(u8);
-    pub(crate) struct Bar(pub u8, u8, Foo);
+    pub(crate) struct Bar(pub u8, pub(in crate::foo) u8, Foo);
 
     pub(crate) fn make_bar() -> Bar {
         Bar(1, 12, Foo(10))
diff --git a/tests/ui/privacy/issue-75907.stderr b/tests/ui/privacy/issue-75907.stderr
index 2f89e31a31a..f7cb874c2cc 100644
--- a/tests/ui/privacy/issue-75907.stderr
+++ b/tests/ui/privacy/issue-75907.stderr
@@ -11,6 +11,10 @@ LL |     let Bar(x, y, Foo(z)) = make_bar();
    |                ^  ^^^^^^ private field
    |                |
    |                private field
+help: consider making the fields publicly accessible
+   |
+LL |     pub(crate) struct Bar(pub u8, pub u8, pub Foo);
+   |                           ~~~     ~~~     +++
 
 error[E0532]: cannot match against a tuple struct which contains private fields
   --> $DIR/issue-75907.rs:15:19
@@ -23,6 +27,10 @@ note: constructor is not visible here due to private fields
    |
 LL |     let Bar(x, y, Foo(z)) = make_bar();
    |                       ^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub(crate) struct Foo(pub u8);
+   |                           +++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/privacy/privacy5.stderr b/tests/ui/privacy/privacy5.stderr
index 680161272ce..615b0af2762 100644
--- a/tests/ui/privacy/privacy5.stderr
+++ b/tests/ui/privacy/privacy5.stderr
@@ -12,6 +12,10 @@ note: the tuple struct constructor `A` is defined here
    |
 LL |     pub struct A(());
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub ());
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:52:16
@@ -27,6 +31,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:53:16
@@ -42,6 +50,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:56:12
@@ -57,6 +69,10 @@ note: the tuple struct constructor `A` is defined here
    |
 LL |     pub struct A(());
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub ());
+   |                  +++
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:57:12
@@ -72,6 +88,10 @@ note: the tuple struct constructor `A` is defined here
    |
 LL |     pub struct A(());
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub ());
+   |                  +++
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:58:18
@@ -87,6 +107,10 @@ note: the tuple struct constructor `A` is defined here
    |
 LL |     pub struct A(());
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub ());
+   |                  +++
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:59:18
@@ -102,6 +126,10 @@ note: the tuple struct constructor `A` is defined here
    |
 LL |     pub struct A(());
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub ());
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:61:12
@@ -117,6 +145,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:62:12
@@ -132,6 +164,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:63:18
@@ -147,6 +183,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:64:18
@@ -162,6 +202,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:18
@@ -177,6 +221,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:32
@@ -192,6 +240,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:68:12
@@ -207,6 +259,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:69:12
@@ -222,6 +278,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:70:12
@@ -237,6 +297,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:71:12
@@ -252,6 +316,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:72:18
@@ -267,6 +335,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:73:18
@@ -282,6 +354,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:74:18
@@ -297,6 +373,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:75:18
@@ -312,6 +392,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:83:17
@@ -327,6 +411,10 @@ note: the tuple struct constructor `A` is defined here
    |
 LL |     pub struct A(());
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub ());
+   |                  +++
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:84:17
@@ -342,6 +430,10 @@ note: the tuple struct constructor `B` is defined here
    |
 LL |     pub struct B(isize);
    |     ^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct B(pub isize);
+   |                  +++
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:85:17
@@ -357,6 +449,10 @@ note: the tuple struct constructor `C` is defined here
    |
 LL |     pub struct C(pub isize, isize);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the fields publicly accessible
+   |
+LL |     pub struct C(pub isize, pub isize);
+   |                  ~~~        +++
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:90:20
diff --git a/tests/ui/privacy/suggest-making-field-public.fixed b/tests/ui/privacy/suggest-making-field-public.fixed
new file mode 100644
index 00000000000..78e335b3db1
--- /dev/null
+++ b/tests/ui/privacy/suggest-making-field-public.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+mod a {
+    pub struct A(pub String);
+}
+
+mod b {
+    use crate::a::A;
+    pub fn x() {
+        A("".into()); //~ ERROR cannot initialize a tuple struct which contains private fields
+    }
+}
+fn main() {
+    a::A("a".into()); //~ ERROR tuple struct constructor `A` is private
+    b::x();
+}
diff --git a/tests/ui/privacy/suggest-making-field-public.rs b/tests/ui/privacy/suggest-making-field-public.rs
new file mode 100644
index 00000000000..b65c801d10e
--- /dev/null
+++ b/tests/ui/privacy/suggest-making-field-public.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+mod a {
+    pub struct A(pub(self)String);
+}
+
+mod b {
+    use crate::a::A;
+    pub fn x() {
+        A("".into()); //~ ERROR cannot initialize a tuple struct which contains private fields
+    }
+}
+fn main() {
+    a::A("a".into()); //~ ERROR tuple struct constructor `A` is private
+    b::x();
+}
diff --git a/tests/ui/privacy/suggest-making-field-public.stderr b/tests/ui/privacy/suggest-making-field-public.stderr
new file mode 100644
index 00000000000..e92e9aae310
--- /dev/null
+++ b/tests/ui/privacy/suggest-making-field-public.stderr
@@ -0,0 +1,39 @@
+error[E0603]: tuple struct constructor `A` is private
+  --> $DIR/suggest-making-field-public.rs:13:8
+   |
+LL |     pub struct A(pub(self)String);
+   |                  --------------- a constructor is private if any of the fields is private
+...
+LL |     a::A("a".into());
+   |        ^ private tuple struct constructor
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/suggest-making-field-public.rs:3:5
+   |
+LL |     pub struct A(pub(self)String);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub String);
+   |                  ~~~
+
+error[E0423]: cannot initialize a tuple struct which contains private fields
+  --> $DIR/suggest-making-field-public.rs:9:9
+   |
+LL |         A("".into());
+   |         ^
+   |
+note: constructor is not visible here due to private fields
+  --> $DIR/suggest-making-field-public.rs:3:18
+   |
+LL |     pub struct A(pub(self)String);
+   |                  ^^^^^^^^^^^^^^^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub struct A(pub String);
+   |                  ~~~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0603.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr
index 86ad6aa847c..1b4d80d9057 100644
--- a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/recursive-types-are-not-uninhabited.rs:6:9
    |
 LL |     let Ok(x) = res;
@@ -6,17 +6,8 @@ LL |     let Ok(x) = res;
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-note: `Result<u32, &R<'_>>` defined here
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-   = note: not covered
    = note: the matched value is of type `Result<u32, &R<'_>>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let x = if let Ok(x) = res { x } else { todo!() };
-   |     ++++++++++                 ++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Ok(x) = res else { todo!() };
    |                     ++++++++++++++++
diff --git a/tests/ui/resolve/issue-42944.rs b/tests/ui/resolve/issue-42944.rs
index a4404857a56..7e439c10b7b 100644
--- a/tests/ui/resolve/issue-42944.rs
+++ b/tests/ui/resolve/issue-42944.rs
@@ -1,5 +1,5 @@
 mod foo {
-    pub struct Bx(());
+    pub struct Bx(pub(in crate::foo) ());
 }
 
 mod bar {
diff --git a/tests/ui/resolve/issue-42944.stderr b/tests/ui/resolve/issue-42944.stderr
index 0ee9fd391fe..4ffa9402c66 100644
--- a/tests/ui/resolve/issue-42944.stderr
+++ b/tests/ui/resolve/issue-42944.stderr
@@ -7,8 +7,8 @@ LL |         Bx(());
 note: tuple struct `foo::Bx` exists but is inaccessible
   --> $DIR/issue-42944.rs:2:5
    |
-LL |     pub struct Bx(());
-   |     ^^^^^^^^^^^^^^^^^^ not accessible
+LL |     pub struct Bx(pub(in crate::foo) ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible
 
 error[E0423]: cannot initialize a tuple struct which contains private fields
   --> $DIR/issue-42944.rs:9:9
@@ -19,8 +19,12 @@ LL |         Bx(());
 note: constructor is not visible here due to private fields
   --> $DIR/issue-42944.rs:2:19
    |
-LL |     pub struct Bx(());
-   |                   ^^ private field
+LL |     pub struct Bx(pub(in crate::foo) ());
+   |                   ^^^^^^^^^^^^^^^^^^^^^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub struct Bx(pub ());
+   |                   ~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr
index d734fa76b4a..a24fe4d23ea 100644
--- a/tests/ui/resolve/privacy-enum-ctor.stderr
+++ b/tests/ui/resolve/privacy-enum-ctor.stderr
@@ -264,15 +264,15 @@ error[E0308]: mismatched types
   --> $DIR/privacy-enum-ctor.rs:27:20
    |
 LL |             Fn(u8),
-   |             -- fn(u8) -> Z {Z::Fn} defined here
+   |             -- `Fn` defines an enum variant constructor here, which should be called
 ...
 LL |         let _: Z = Z::Fn;
-   |                -   ^^^^^ expected enum `Z`, found fn item
+   |                -   ^^^^^ expected enum `Z`, found enum constructor
    |                |
    |                expected due to this
    |
-   = note: expected enum `Z`
-           found fn item `fn(u8) -> Z {Z::Fn}`
+   = note:          expected enum `Z`
+           found enum constructor `fn(u8) -> Z {Z::Fn}`
 help: use parentheses to construct this tuple variant
    |
 LL |         let _: Z = Z::Fn(/* u8 */);
@@ -305,15 +305,15 @@ error[E0308]: mismatched types
   --> $DIR/privacy-enum-ctor.rs:43:16
    |
 LL |         Fn(u8),
-   |         -- fn(u8) -> E {E::Fn} defined here
+   |         -- `Fn` defines an enum variant constructor here, which should be called
 ...
 LL |     let _: E = m::E::Fn;
-   |            -   ^^^^^^^^ expected enum `E`, found fn item
+   |            -   ^^^^^^^^ expected enum `E`, found enum constructor
    |            |
    |            expected due to this
    |
-   = note: expected enum `E`
-           found fn item `fn(u8) -> E {E::Fn}`
+   = note:          expected enum `E`
+           found enum constructor `fn(u8) -> E {E::Fn}`
 help: use parentheses to construct this tuple variant
    |
 LL |     let _: E = m::E::Fn(/* u8 */);
@@ -346,15 +346,15 @@ error[E0308]: mismatched types
   --> $DIR/privacy-enum-ctor.rs:51:16
    |
 LL |         Fn(u8),
-   |         -- fn(u8) -> E {E::Fn} defined here
+   |         -- `Fn` defines an enum variant constructor here, which should be called
 ...
 LL |     let _: E = E::Fn;
-   |            -   ^^^^^ expected enum `E`, found fn item
+   |            -   ^^^^^ expected enum `E`, found enum constructor
    |            |
    |            expected due to this
    |
-   = note: expected enum `E`
-           found fn item `fn(u8) -> E {E::Fn}`
+   = note:          expected enum `E`
+           found enum constructor `fn(u8) -> E {E::Fn}`
 help: use parentheses to construct this tuple variant
    |
 LL |     let _: E = E::Fn(/* u8 */);
diff --git a/tests/ui/resolve/privacy-struct-ctor.stderr b/tests/ui/resolve/privacy-struct-ctor.stderr
index 17a666a401c..c1fcaaf0573 100644
--- a/tests/ui/resolve/privacy-struct-ctor.stderr
+++ b/tests/ui/resolve/privacy-struct-ctor.stderr
@@ -53,6 +53,10 @@ note: the tuple struct constructor `Z` is defined here
    |
 LL |         pub(in m) struct Z(pub(in m::n) u8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |         pub(in m) struct Z(pub u8);
+   |                            ~~~
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:29:8
@@ -68,6 +72,10 @@ note: the tuple struct constructor `S` is defined here
    |
 LL |     pub struct S(u8);
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct S(pub u8);
+   |                  +++
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:31:19
@@ -83,6 +91,10 @@ note: the tuple struct constructor `S` is defined here
    |
 LL |     pub struct S(u8);
    |     ^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |     pub struct S(pub u8);
+   |                  +++
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:35:11
@@ -98,6 +110,10 @@ note: the tuple struct constructor `Z` is defined here
    |
 LL |         pub(in m) struct Z(pub(in m::n) u8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider making the field publicly accessible
+   |
+LL |         pub(in m) struct Z(pub u8);
+   |                            ~~~
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:41:16
diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
index ac819dce6db..15f08486f0f 100644
--- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
+++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
@@ -1,7 +1,8 @@
 fn main() {
     let A = 3;
-    //~^ ERROR refutable pattern in local binding: `i32::MIN..=1_i32` and
-    //~| interpreted as a constant pattern, not a new variable
+    //~^ ERROR refutable pattern in local binding
+    //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
+    //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
     //~| HELP introduce a variable instead
     //~| SUGGESTION a_var
 
diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
index 618bcaca14c..1c1cab25fbf 100644
--- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
+++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
@@ -1,10 +1,11 @@
-error[E0005]: refutable pattern in local binding: `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
    |
 LL |     let A = 3;
    |         ^
    |         |
-   |         interpreted as a constant pattern, not a new variable
+   |         patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
+   |         missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `a_var`
 ...
 LL |     const A: i32 = 2;
diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr
index 14e8a2675dd..924b26a8c75 100644
--- a/tests/ui/suggestions/derive-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr
@@ -16,10 +16,18 @@ LL | struct Foo<X, Y> (X, Y);
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Enum, CloneEnum>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `Enum: Clone`
-           `Enum: Default`
-           `CloneEnum: Default`
+note: the following trait bounds were not satisfied:
+      `CloneEnum: Default`
+      `Enum: Clone`
+      `Enum: Default`
+  --> $DIR/derive-trait-for-method-call.rs:20:9
+   |
+LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+   |         ^^^^^   ^^^^^^^                ^^^^^^^  ---------
+   |         |       |                      |
+   |         |       |                      unsatisfied trait bound introduced here
+   |         |       unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
 note: the trait `Default` must be implemented
   --> $SRC_DIR/core/src/default.rs:LL:COL
 help: consider annotating `Enum` with `#[derive(Clone)]`
@@ -45,10 +53,18 @@ LL | struct Foo<X, Y> (X, Y);
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Struct, CloneStruct>` due to unsatisfied trait bounds
    |
-   = note: the following trait bounds were not satisfied:
-           `Struct: Clone`
-           `Struct: Default`
-           `CloneStruct: Default`
+note: the following trait bounds were not satisfied:
+      `CloneStruct: Default`
+      `Struct: Clone`
+      `Struct: Default`
+  --> $DIR/derive-trait-for-method-call.rs:20:9
+   |
+LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+   |         ^^^^^   ^^^^^^^                ^^^^^^^  ---------
+   |         |       |                      |
+   |         |       |                      unsatisfied trait bound introduced here
+   |         |       unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
 help: consider annotating `CloneStruct` with `#[derive(Default)]`
    |
 LL | #[derive(Default)]
@@ -73,9 +89,16 @@ LL |     let y = x.test();
    |
    = note: doesn't satisfy `Vec<Enum>: Clone`
    |
-   = note: the following trait bounds were not satisfied:
-           `Vec<Enum>: Clone`
-           `Instant: Default`
+note: the following trait bounds were not satisfied:
+      `Instant: Default`
+      `Vec<Enum>: Clone`
+  --> $DIR/derive-trait-for-method-call.rs:20:9
+   |
+LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+   |         ^^^^^                          ^^^^^^^  ---------
+   |         |                              |
+   |         |                              unsatisfied trait bound introduced here
+   |         unsatisfied trait bound introduced here
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index d0ddb34d9fe..4cbcd31fa5e 100644
--- a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:29:20
    |
 LL | fn foo(a: usize, b: usize) -> usize { a }
-   | ----------------------------------- fn(usize, usize) -> usize {foo} defined here
+   | ----------------------------------- function `foo` defined here
 ...
 LL |     let _: usize = foo;
    |            -----   ^^^ expected `usize`, found fn item
@@ -20,15 +20,15 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:30:16
    |
 LL | struct S(usize, usize);
-   | -------- fn(usize, usize) -> S {S} defined here
+   | -------- `S` defines a struct constructor here, which should be called
 ...
 LL |     let _: S = S;
-   |            -   ^ expected struct `S`, found fn item
+   |            -   ^ expected struct `S`, found struct constructor
    |            |
    |            expected due to this
    |
-   = note: expected struct `S`
-             found fn item `fn(usize, usize) -> S {S}`
+   = note:          expected struct `S`
+           found struct constructor `fn(usize, usize) -> S {S}`
 help: use parentheses to construct this tuple struct
    |
 LL |     let _: S = S(/* usize */, /* usize */);
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:31:20
    |
 LL | fn bar() -> usize { 42 }
-   | ----------------- fn() -> usize {bar} defined here
+   | ----------------- function `bar` defined here
 ...
 LL |     let _: usize = bar;
    |            -----   ^^^ expected `usize`, found fn item
@@ -56,15 +56,15 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:32:16
    |
 LL | struct V();
-   | -------- fn() -> V {V} defined here
+   | -------- `V` defines a struct constructor here, which should be called
 ...
 LL |     let _: V = V;
-   |            -   ^ expected struct `V`, found fn item
+   |            -   ^ expected struct `V`, found struct constructor
    |            |
    |            expected due to this
    |
-   = note: expected struct `V`
-             found fn item `fn() -> V {V}`
+   = note:          expected struct `V`
+           found struct constructor `fn() -> V {V}`
 help: use parentheses to construct this tuple struct
    |
 LL |     let _: V = V();
@@ -74,7 +74,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:33:20
    |
 LL |     fn baz(x: usize, y: usize) -> usize { x }
-   |     ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here
+   |     ----------------------------------- associated function `baz` defined here
 ...
 LL |     let _: usize = T::baz;
    |            -----   ^^^^^^ expected `usize`, found fn item
@@ -92,7 +92,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:34:20
    |
 LL |     fn bat(x: usize) -> usize { 42 }
-   |     ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here
+   |     ------------------------- associated function `bat` defined here
 ...
 LL |     let _: usize = T::bat;
    |            -----   ^^^^^^ expected `usize`, found fn item
@@ -110,15 +110,15 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:35:16
    |
 LL |     A(usize),
-   |     - fn(usize) -> E {E::A} defined here
+   |     - `A` defines an enum variant constructor here, which should be called
 ...
 LL |     let _: E = E::A;
-   |            -   ^^^^ expected enum `E`, found fn item
+   |            -   ^^^^ expected enum `E`, found enum constructor
    |            |
    |            expected due to this
    |
-   = note: expected enum `E`
-           found fn item `fn(usize) -> E {E::A}`
+   = note:          expected enum `E`
+           found enum constructor `fn(usize) -> E {E::A}`
 help: use parentheses to construct this tuple variant
    |
 LL |     let _: E = E::A(/* usize */);
@@ -134,7 +134,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:37:20
    |
 LL |     fn baz(x: usize, y: usize) -> usize { x }
-   |     ----------------------------------- fn(usize, usize) -> usize {<X as T>::baz} defined here
+   |     ----------------------------------- associated function `baz` defined here
 ...
 LL |     let _: usize = X::baz;
    |            -----   ^^^^^^ expected `usize`, found fn item
@@ -152,7 +152,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:38:20
    |
 LL |     fn bat(x: usize) -> usize { 42 }
-   |     ------------------------- fn(usize) -> usize {<X as T>::bat} defined here
+   |     ------------------------- associated function `bat` defined here
 ...
 LL |     let _: usize = X::bat;
    |            -----   ^^^^^^ expected `usize`, found fn item
@@ -170,7 +170,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:39:20
    |
 LL |     fn bax(x: usize) -> usize { 42 }
-   |     ------------------------- fn(usize) -> usize {<X as T>::bax} defined here
+   |     ------------------------- associated function `bax` defined here
 ...
 LL |     let _: usize = X::bax;
    |            -----   ^^^^^^ expected `usize`, found fn item
@@ -188,7 +188,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:40:20
    |
 LL |     fn bach(x: usize) -> usize;
-   |     --------------------------- fn(usize) -> usize {<X as T>::bach} defined here
+   |     --------------------------- associated function `bach` defined here
 ...
 LL |     let _: usize = X::bach;
    |            -----   ^^^^^^^ expected `usize`, found fn item
@@ -206,7 +206,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:41:20
    |
 LL |     fn ban(&self) -> usize { 42 }
-   |     ---------------------- for<'a> fn(&'a X) -> usize {<X as T>::ban} defined here
+   |     ---------------------- associated function `ban` defined here
 ...
 LL |     let _: usize = X::ban;
    |            -----   ^^^^^^ expected `usize`, found fn item
@@ -224,7 +224,7 @@ error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:42:20
    |
 LL |     fn bal(&self) -> usize;
-   |     ----------------------- for<'a> fn(&'a X) -> usize {<X as T>::bal} defined here
+   |     ----------------------- associated function `bal` defined here
 ...
 LL |     let _: usize = X::bal;
    |            -----   ^^^^^^ expected `usize`, found fn item
diff --git a/tests/ui/suggestions/lifetimes/issue-105544.fixed b/tests/ui/suggestions/lifetimes/issue-105544.fixed
new file mode 100644
index 00000000000..47087eb4749
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/issue-105544.fixed
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `impl Sized` may not live long enough
+    //~| NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+}
+
+fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+    (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+    //~^ ERROR the parameter type `impl Sized` may not live long enough
+}
+
+fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough
+    //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
+}
+
+fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+    (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/issue-105544.rs b/tests/ui/suggestions/lifetimes/issue-105544.rs
new file mode 100644
index 00000000000..bd3bc1ef9bd
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/issue-105544.rs
@@ -0,0 +1,45 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `impl Sized` may not live long enough
+    //~| NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+}
+
+fn foo1<'b>(d: impl Sized, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+    (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds
+    //~^ ERROR the parameter type `impl Sized` may not live long enough
+}
+
+fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough
+    //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
+}
+
+fn bar<T : Sized>(d: T, p: & mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn bar1<'b, T : Sized>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+//~^ HELP consider adding an explicit lifetime bound...
+    (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
+//~^ HELP consider adding an explicit lifetime bound
+    (d, p)
+    //~^ ERROR the parameter type `T` may not live long enough
+    //~| NOTE ...so that the type `T` will meet its required lifetime bounds
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/issue-105544.stderr b/tests/ui/suggestions/lifetimes/issue-105544.stderr
new file mode 100644
index 00000000000..08fe21b11b5
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/issue-105544.stderr
@@ -0,0 +1,110 @@
+error[E0311]: the parameter type `impl Sized` may not live long enough
+  --> $DIR/issue-105544.rs:7:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+   |
+note: the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
+  --> $DIR/issue-105544.rs:5:26
+   |
+LL | fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ {
+   |                          ^^^^^^^
+note: ...so that the type `impl Sized` will meet its required lifetime bounds
+  --> $DIR/issue-105544.rs:7:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ {
+   |       ++++               ++++      ++
+
+error[E0309]: the parameter type `impl Sized` may not live long enough
+  --> $DIR/issue-105544.rs:14:5
+   |
+LL |     (d, p)
+   |     ^^^^^^ ...so that the type `impl Sized` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ {
+   |                           ++++
+
+error[E0311]: the parameter type `impl Sized + 'a` may not live long enough
+  --> $DIR/issue-105544.rs:20:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+   |
+note: the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
+  --> $DIR/issue-105544.rs:18:36
+   |
+LL | fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ {
+   |                                    ^^^^^^^
+note: ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
+  --> $DIR/issue-105544.rs:20:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ {
+   |         +++                        ++++      ++
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/issue-105544.rs:27:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/issue-105544.rs:25:28
+   |
+LL | fn bar<T : Sized>(d: T, p: & mut ()) -> impl Sized + '_ {
+   |                            ^^^^^^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/issue-105544.rs:27:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ {
+   |        +++           ++++            ++
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/issue-105544.rs:34:5
+   |
+LL |     (d, p)
+   |     ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+   |                       ++++
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/issue-105544.rs:40:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/issue-105544.rs:38:38
+   |
+LL | fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ {
+   |                                      ^^^^^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/issue-105544.rs:40:5
+   |
+LL |     (d, p)
+   |     ^^^^^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
+   |         +++                    ++++            ++
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0309, E0311.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed
new file mode 100644
index 00000000000..4013d98c3cf
--- /dev/null
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed
@@ -0,0 +1,29 @@
+// Regression test for #81650
+// run-rustfix
+
+#![allow(warnings)]
+
+struct Foo<'a> {
+    x: &'a mut &'a i32,
+}
+
+impl<'a> Foo<'a> {
+    fn bar<F, T>(&self, f: F)
+    where
+        F: FnOnce(&Foo<'a>) -> T,
+        F: 'a,
+    {}
+}
+
+trait Test {
+    fn test(&self);
+}
+
+fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) {
+    foo.bar(move |_| {
+    //~^ ERROR the parameter type `T` may not live long enough
+        t.test();
+    });
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs
index c6802ac6cc7..4096d95e5fd 100644
--- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs
@@ -1,4 +1,7 @@
 // Regression test for #81650
+// run-rustfix
+
+#![allow(warnings)]
 
 struct Foo<'a> {
     x: &'a mut &'a i32,
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
index 872263fd731..936d87f7968 100644
--- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
@@ -1,5 +1,5 @@
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature-2.rs:20:5
+  --> $DIR/missing-lifetimes-in-signature-2.rs:23:5
    |
 LL | /     foo.bar(move |_| {
 LL | |
@@ -8,12 +8,12 @@ LL | |     });
    | |______^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/missing-lifetimes-in-signature-2.rs:19:24
+  --> $DIR/missing-lifetimes-in-signature-2.rs:22:24
    |
 LL | fn func<T: Test>(foo: &Foo, t: T) {
    |                        ^^^
 note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature-2.rs:20:5
+  --> $DIR/missing-lifetimes-in-signature-2.rs:23:5
    |
 LL | /     foo.bar(move |_| {
 LL | |
@@ -22,8 +22,8 @@ LL | |     });
    | |______^
 help: consider adding an explicit lifetime bound...
    |
-LL | fn func<'a, T: Test + 'a>(foo: &Foo, t: T) {
-   |         +++         ++++
+LL | fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) {
+   |         +++         ++++        ++    ++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index fa758bf05df..c5c3f7b468c 100644
--- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -47,7 +47,7 @@ LL | |     }
    | |_____^
 help: consider adding an explicit lifetime bound...
    |
-LL ~ fn bar<'a, G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_
 LL | where
 LL ~     G: Get<T> + 'a,
    |
@@ -76,8 +76,8 @@ LL | |     }
    | |_____^
 help: consider adding an explicit lifetime bound...
    |
-LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |        +++           ++++
+LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_
+   |        +++           ++++                  ++
 
 error[E0311]: the parameter type `G` may not live long enough
   --> $DIR/missing-lifetimes-in-signature.rs:61:9
@@ -103,8 +103,8 @@ LL | |         }
    | |_________^
 help: consider adding an explicit lifetime bound...
    |
-LL |     fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |            +++                    ++++
+LL |     fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + '_ {
+   |            +++                    ++++                  ++
 
 error[E0311]: the parameter type `G` may not live long enough
   --> $DIR/missing-lifetimes-in-signature.rs:73:5
@@ -132,8 +132,8 @@ LL | |     }
    | |_____^
 help: consider adding an explicit lifetime bound...
    |
-LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |        +++           ++++
+LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ + 'a
+   |        +++           ++++                  ++
 
 error[E0621]: explicit lifetime required in the type of `dest`
   --> $DIR/missing-lifetimes-in-signature.rs:73:5
diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr
index 1a843f3f509..387770535f6 100644
--- a/tests/ui/suggestions/suggest-remove-refs-1.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr
@@ -2,13 +2,15 @@ error[E0277]: `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
   --> $DIR/suggest-remove-refs-1.rs:6:19
    |
 LL |     for (i, _) in &v.iter().enumerate() {
-   |                   -^^^^^^^^^^^^^^^^^^^^
-   |                   |
-   |                   `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
-   |                   help: consider removing the leading `&`-reference
+   |                   ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing the leading `&`-reference
+   |
+LL -     for (i, _) in &v.iter().enumerate() {
+LL +     for (i, _) in v.iter().enumerate() {
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr
index f39361d529f..1632b2abb2f 100644
--- a/tests/ui/suggestions/suggest-remove-refs-2.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr
@@ -2,13 +2,15 @@ error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterat
   --> $DIR/suggest-remove-refs-2.rs:6:19
    |
 LL |     for (i, _) in & & & & &v.iter().enumerate() {
-   |                   ---------^^^^^^^^^^^^^^^^^^^^
-   |                   |
-   |                   `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
-   |                   help: consider removing 5 leading `&`-references
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing 5 leading `&`-references
+   |
+LL -     for (i, _) in & & & & &v.iter().enumerate() {
+LL +     for (i, _) in v.iter().enumerate() {
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr
index 31cca323d0e..7bf421a7729 100644
--- a/tests/ui/suggestions/suggest-remove-refs-3.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr
@@ -1,18 +1,20 @@
 error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
   --> $DIR/suggest-remove-refs-3.rs:6:19
    |
-LL |        for (i, _) in & & &
-   |  ____________________^
-   | | ___________________|
-   | ||
-LL | ||         & &v
-   | ||___________- help: consider removing 5 leading `&`-references
-LL | |          .iter()
-LL | |          .enumerate() {
-   | |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
+LL |       for (i, _) in & & &
+   |  ___________________^
+LL | |         & &v
+LL | |         .iter()
+LL | |         .enumerate() {
+   | |____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
+help: consider removing 5 leading `&`-references
+   |
+LL -     for (i, _) in & & &
+LL +     for (i, _) in v
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.fixed b/tests/ui/suggestions/suggest-remove-refs-4.fixed
new file mode 100644
index 00000000000..dd63d215972
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-4.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let foo = [1,2,3].iter();
+    for _i in foo {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.rs b/tests/ui/suggestions/suggest-remove-refs-4.rs
new file mode 100644
index 00000000000..3c3d9b1b3f9
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-4.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let foo = &[1,2,3].iter();
+    for _i in &foo {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr
new file mode 100644
index 00000000000..e4ad17e0671
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator
+  --> $DIR/suggest-remove-refs-4.rs:4:15
+   |
+LL |     for _i in &foo {}
+   |               ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`
+   = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
+help: consider removing 2 leading `&`-references
+   |
+LL ~     let foo = [1,2,3].iter();
+LL ~     for _i in foo {}
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.fixed b/tests/ui/suggestions/suggest-remove-refs-5.fixed
new file mode 100644
index 00000000000..9f59f9c199a
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-5.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+    let v = &mut Vec::<i32>::new();
+    for _ in v {} //~ ERROR E0277
+
+    let v = &mut [1u8];
+    for _ in v {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.rs b/tests/ui/suggestions/suggest-remove-refs-5.rs
new file mode 100644
index 00000000000..d56aa0c9ca4
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-5.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+fn main() {
+    let v = &mut &mut Vec::<i32>::new();
+    for _ in &mut &mut v {} //~ ERROR E0277
+
+    let v = &mut &mut [1u8];
+    for _ in &mut v {} //~ ERROR E0277
+}
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr
new file mode 100644
index 00000000000..7de84d6122b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr
@@ -0,0 +1,37 @@
+error[E0277]: `Vec<i32>` is not an iterator
+  --> $DIR/suggest-remove-refs-5.rs:4:14
+   |
+LL |     for _ in &mut &mut v {}
+   |              ^^^^^^^^^^^ `Vec<i32>` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |
+   = help: the trait `Iterator` is not implemented for `Vec<i32>`
+   = note: required for `&mut Vec<i32>` to implement `Iterator`
+   = note: 3 redundant requirements hidden
+   = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
+   = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `IntoIterator`
+help: consider removing 3 leading `&`-references
+   |
+LL ~     let v = &mut Vec::<i32>::new();
+LL ~     for _ in v {}
+   |
+
+error[E0277]: `[u8; 1]` is not an iterator
+  --> $DIR/suggest-remove-refs-5.rs:7:14
+   |
+LL |     for _ in &mut v {}
+   |              ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |
+   = help: the trait `Iterator` is not implemented for `[u8; 1]`
+   = note: required for `&mut [u8; 1]` to implement `Iterator`
+   = note: 2 redundant requirements hidden
+   = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
+   = note: required for `&mut &mut &mut [u8; 1]` to implement `IntoIterator`
+help: consider removing 2 leading `&`-references
+   |
+LL ~     let v = &mut [1u8];
+LL ~     for _ in v {}
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/ignore-err-impls.rs b/tests/ui/traits/ignore-err-impls.rs
new file mode 100644
index 00000000000..67e880b006a
--- /dev/null
+++ b/tests/ui/traits/ignore-err-impls.rs
@@ -0,0 +1,9 @@
+pub struct S;
+
+trait Generic<T> {}
+
+impl<'a, T> Generic<&'a T> for S {}
+impl Generic<Type> for S {}
+//~^ ERROR cannot find type `Type` in this scope
+
+fn main() {}
diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr
new file mode 100644
index 00000000000..1390106a291
--- /dev/null
+++ b/tests/ui/traits/ignore-err-impls.stderr
@@ -0,0 +1,11 @@
+error[E0412]: cannot find type `Type` in this scope
+  --> $DIR/ignore-err-impls.rs:6:14
+   |
+LL | impl Generic<Type> for S {}
+   |     -        ^^^^ not found in this scope
+   |     |
+   |     help: you might be missing a type parameter: `<Type>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.rs b/tests/ui/type-alias-impl-trait/unnameable_type.rs
new file mode 100644
index 00000000000..1739ab0063f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.rs
@@ -0,0 +1,24 @@
+#![feature(type_alias_impl_trait)]
+
+// This test ensures that unnameable types stay unnameable
+// https://github.com/rust-lang/rust/issues/63063#issuecomment-1360053614
+
+// library
+mod private {
+    pub struct Private;
+    pub trait Trait {
+        fn dont_define_this(_private: Private) {}
+    }
+}
+
+use private::Trait;
+
+// downstream
+type MyPrivate = impl Sized;
+//~^ ERROR: unconstrained opaque type
+impl Trait for u32 {
+    fn dont_define_this(_private: MyPrivate) {}
+    //~^ ERROR: incompatible type for trait
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
new file mode 100644
index 00000000000..7dc6efc4b1b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
@@ -0,0 +1,31 @@
+error: unconstrained opaque type
+  --> $DIR/unnameable_type.rs:17:18
+   |
+LL | type MyPrivate = impl Sized;
+   |                  ^^^^^^^^^^
+   |
+   = note: `MyPrivate` must be used in combination with a concrete type within the same module
+
+error[E0053]: method `dont_define_this` has an incompatible type for trait
+  --> $DIR/unnameable_type.rs:20:35
+   |
+LL | type MyPrivate = impl Sized;
+   |                  ---------- the found opaque type
+...
+LL |     fn dont_define_this(_private: MyPrivate) {}
+   |                                   ^^^^^^^^^
+   |                                   |
+   |                                   expected struct `Private`, found opaque type
+   |                                   help: change the parameter type to match the trait: `Private`
+   |
+note: type in trait
+  --> $DIR/unnameable_type.rs:10:39
+   |
+LL |         fn dont_define_this(_private: Private) {}
+   |                                       ^^^^^^^
+   = note: expected signature `fn(Private)`
+              found signature `fn(MyPrivate)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/typeck/issue-57404.stderr b/tests/ui/typeck/issue-57404.stderr
index 5065ac32ad2..a631dbb39fb 100644
--- a/tests/ui/typeck/issue-57404.stderr
+++ b/tests/ui/typeck/issue-57404.stderr
@@ -2,14 +2,17 @@ error[E0277]: `&mut ()` is not a tuple
   --> $DIR/issue-57404.rs:6:41
    |
 LL |     handlers.unwrap().as_mut().call_mut(&mut ());
-   |                                -------- -^^^^^^
-   |                                |        |
-   |                                |        the trait `Tuple` is not implemented for `&mut ()`
-   |                                |        help: consider removing the leading `&`-reference
+   |                                -------- ^^^^^^^ the trait `Tuple` is not implemented for `&mut ()`
+   |                                |
    |                                required by a bound introduced by this call
    |
 note: required by a bound in `call_mut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider removing the leading `&`-reference
+   |
+LL -     handlers.unwrap().as_mut().call_mut(&mut ());
+LL +     handlers.unwrap().as_mut().call_mut(());
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/issue-87181/empty-tuple-method.rs b/tests/ui/typeck/issue-87181/empty-tuple-method.rs
index be68ad32ae5..96b3f8dab8d 100644
--- a/tests/ui/typeck/issue-87181/empty-tuple-method.rs
+++ b/tests/ui/typeck/issue-87181/empty-tuple-method.rs
@@ -10,5 +10,5 @@ impl Foo {
 fn main() {
     let thing = Bar { bar: Foo };
     thing.bar.foo();
-    //~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope [E0599]
+    //~^ ERROR no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope [E0599]
 }
diff --git a/tests/ui/typeck/issue-87181/empty-tuple-method.stderr b/tests/ui/typeck/issue-87181/empty-tuple-method.stderr
index 23e7b7cc363..f0ca49e6d1e 100644
--- a/tests/ui/typeck/issue-87181/empty-tuple-method.stderr
+++ b/tests/ui/typeck/issue-87181/empty-tuple-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo}` in the current scope
+error[E0599]: no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope
   --> $DIR/empty-tuple-method.rs:12:15
    |
 LL |     thing.bar.foo();
diff --git a/tests/ui/typeck/issue-87181/enum-variant.rs b/tests/ui/typeck/issue-87181/enum-variant.rs
index d87f99c3c5a..ed01656ce72 100644
--- a/tests/ui/typeck/issue-87181/enum-variant.rs
+++ b/tests/ui/typeck/issue-87181/enum-variant.rs
@@ -12,5 +12,5 @@ impl Foo {
 fn main() {
     let thing = Bar { bar: Foo::Tup };
     thing.bar.foo();
-    //~^ ERROR no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` in the current scope [E0599]
+    //~^ ERROR no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope [E0599]
 }
diff --git a/tests/ui/typeck/issue-87181/enum-variant.stderr b/tests/ui/typeck/issue-87181/enum-variant.stderr
index 2247ea27021..d313a887abd 100644
--- a/tests/ui/typeck/issue-87181/enum-variant.stderr
+++ b/tests/ui/typeck/issue-87181/enum-variant.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` in the current scope
+error[E0599]: no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope
   --> $DIR/enum-variant.rs:14:15
    |
 LL |     thing.bar.foo();
diff --git a/tests/ui/typeck/issue-87181/tuple-method.rs b/tests/ui/typeck/issue-87181/tuple-method.rs
index e88f642b070..6310984438c 100644
--- a/tests/ui/typeck/issue-87181/tuple-method.rs
+++ b/tests/ui/typeck/issue-87181/tuple-method.rs
@@ -10,5 +10,5 @@ impl Foo {
 fn main() {
     let thing = Bar { bar: Foo };
     thing.bar.foo();
-    //~^ ERROR no method named `foo` found for fn item `fn(u8, i32) -> Foo {Foo}` in the current scope [E0599]
+    //~^ ERROR no method named `foo` found for struct constructor `fn(u8, i32) -> Foo {Foo}` in the current scope [E0599]
 }
diff --git a/tests/ui/typeck/issue-87181/tuple-method.stderr b/tests/ui/typeck/issue-87181/tuple-method.stderr
index e27c41858d3..de3dc15a54b 100644
--- a/tests/ui/typeck/issue-87181/tuple-method.stderr
+++ b/tests/ui/typeck/issue-87181/tuple-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `foo` found for fn item `fn(u8, i32) -> Foo {Foo}` in the current scope
+error[E0599]: no method named `foo` found for struct constructor `fn(u8, i32) -> Foo {Foo}` in the current scope
   --> $DIR/tuple-method.rs:12:15
    |
 LL |     thing.bar.foo();
diff --git a/tests/ui/typeck/issue-96738.stderr b/tests/ui/typeck/issue-96738.stderr
index 0d4d87ef47e..547cffffa2e 100644
--- a/tests/ui/typeck/issue-96738.stderr
+++ b/tests/ui/typeck/issue-96738.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `nonexistent_method` found for fn item `fn(_) -> Option<_> {Option::<_>::Some}` in the current scope
+error[E0599]: no method named `nonexistent_method` found for enum constructor `fn(_) -> Option<_> {Option::<_>::Some}` in the current scope
   --> $DIR/issue-96738.rs:2:10
    |
 LL |     Some.nonexistent_method();
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs
index 1a0f3c5e550..4b001aca2d1 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.rs
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs
@@ -24,5 +24,7 @@ enum Foo {
 
 fn main() {
     let x: Foo = Foo::D(123, 456);
-    let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `Foo::A(_)` not covered
+    let Foo::D(_y, _z) = x;
+    //~^ ERROR refutable pattern in local binding
+    //~| `Foo::A(_)` not covered
 }
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.stderr
index 32f287a1818..8cafea555c1 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `Foo::A(_)` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/uninhabited-irrefutable.rs:27:9
    |
 LL |     let Foo::D(_y, _z) = x;
@@ -7,18 +7,14 @@ LL |     let Foo::D(_y, _z) = x;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Foo` defined here
-  --> $DIR/uninhabited-irrefutable.rs:19:5
+  --> $DIR/uninhabited-irrefutable.rs:18:6
    |
 LL | enum Foo {
-   |      ---
+   |      ^^^
 LL |     A(foo::SecretlyEmpty),
-   |     ^ not covered
+   |     - not covered
    = note: the matched value is of type `Foo`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
-   |     +++++++++++++++++                        +++++++++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Foo::D(_y, _z) = x else { todo!() };
    |                            ++++++++++++++++
diff --git a/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index d33a61ca848..466d7f2eadb 100644
--- a/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -95,7 +95,7 @@ LL ~         Ok(x) => x,
 LL ~         Err(_) => todo!(),
    |
 
-error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+error[E0005]: refutable pattern in local binding
   --> $DIR/uninhabited-matches-feature-gated.rs:37:9
    |
 LL |     let Ok(x) = x;
@@ -103,17 +103,8 @@ LL |     let Ok(x) = x;
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-note: `Result<u32, Void>` defined here
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     let x = if let Ok(x) = x { x } else { todo!() };
-   |     ++++++++++               ++++++++++++++++++++++
-help: alternatively, you might want to use let else to handle the variant that isn't matched
+help: you might want to use `let else` to handle the variant that isn't matched
    |
 LL |     let Ok(x) = x else { todo!() };
    |                   ++++++++++++++++
diff --git a/tests/ui/union/union-derive-clone.mirunsafeck.stderr b/tests/ui/union/union-derive-clone.mirunsafeck.stderr
index 65ff72fe474..b80e8b988ad 100644
--- a/tests/ui/union/union-derive-clone.mirunsafeck.stderr
+++ b/tests/ui/union/union-derive-clone.mirunsafeck.stderr
@@ -32,9 +32,6 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied
    |
 LL | #[derive(Clone, Copy)]
    |          ^^^^^ unsatisfied trait bound introduced in this `derive` macro
-   = note: the following trait bounds were not satisfied:
-           `CloneNoCopy: Copy`
-           which is required by `U5<CloneNoCopy>: Clone`
 help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]`
    |
 LL | #[derive(Clone, Copy)]
diff --git a/tests/ui/union/union-derive-clone.thirunsafeck.stderr b/tests/ui/union/union-derive-clone.thirunsafeck.stderr
index 65ff72fe474..b80e8b988ad 100644
--- a/tests/ui/union/union-derive-clone.thirunsafeck.stderr
+++ b/tests/ui/union/union-derive-clone.thirunsafeck.stderr
@@ -32,9 +32,6 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied
    |
 LL | #[derive(Clone, Copy)]
    |          ^^^^^ unsatisfied trait bound introduced in this `derive` macro
-   = note: the following trait bounds were not satisfied:
-           `CloneNoCopy: Copy`
-           which is required by `U5<CloneNoCopy>: Clone`
 help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]`
    |
 LL | #[derive(Clone, Copy)]
diff --git a/tests/ui/where-clauses/ignore-err-clauses.rs b/tests/ui/where-clauses/ignore-err-clauses.rs
new file mode 100644
index 00000000000..c76f0e1a8b2
--- /dev/null
+++ b/tests/ui/where-clauses/ignore-err-clauses.rs
@@ -0,0 +1,14 @@
+use std::ops::Add;
+
+fn dbl<T>(x: T) -> <T as Add>::Output
+where
+    T: Copy + Add,
+    UUU: Copy,
+    //~^ ERROR cannot find type `UUU` in this scope
+{
+    x + x
+}
+
+fn main() {
+    println!("{}", dbl(3));
+}
diff --git a/tests/ui/where-clauses/ignore-err-clauses.stderr b/tests/ui/where-clauses/ignore-err-clauses.stderr
new file mode 100644
index 00000000000..cfddc3e10b6
--- /dev/null
+++ b/tests/ui/where-clauses/ignore-err-clauses.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `UUU` in this scope
+  --> $DIR/ignore-err-clauses.rs:6:5
+   |
+LL |     UUU: Copy,
+   |     ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.