about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-07 05:18:45 +0000
committerbors <bors@rust-lang.org>2023-10-07 05:18:45 +0000
commit1c42857135ca902122fdbe6e050ba1481431541b (patch)
tree10b27e1cd9ff220269c414ef591f60a79a74ddf2
parent3b08930677e5f9b5999caa2e5960df8def1b1e73 (diff)
parent722736ac4ab71b34645149b6994c0d56c6143832 (diff)
downloadrust-1c42857135ca902122fdbe6e050ba1481431541b.tar.gz
rust-1c42857135ca902122fdbe6e050ba1481431541b.zip
Auto merge of #3113 - rust-lang:rustup-2023-10-07, r=saethlin
Automatic sync from rustc
-rw-r--r--Cargo.lock35
-rw-r--r--compiler/rustc_attr/src/builtin.rs85
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs29
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0282.md25
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0283.md46
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs15
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs30
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs11
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs92
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_query_impl/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/config.rs1
-rw-r--r--compiler/rustc_smir/Cargo.toml7
-rw-r--r--compiler/rustc_smir/src/lib.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs275
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs3481
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs3241
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_transmute/src/lib.rs4
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/mod.rs110
-rw-r--r--library/core/src/convert/mod.rs40
-rw-r--r--library/core/src/option.rs8
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/build.rs8
-rw-r--r--library/std/src/sync/once.rs2
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs2
-rw-r--r--src/tools/clippy/CHANGELOG.md97
-rw-r--r--src/tools/clippy/Cargo.toml4
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md2
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md1
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs63
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml5
-rw-r--r--src/tools/clippy/clippy_lints/src/allow_attributes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/error_impl_error.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/four_forward_slashes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_hasher.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/items_after_test_module.rs108
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs249
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_float_methods.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_hash_one.rs133
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_assert_message.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_canonical_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/raw_strings.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_locals.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs142
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs69
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs31
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs44
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs55
-rw-r--r--src/tools/clippy/src/main.rs63
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs28
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.fixed15
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.rs15
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.stderr24
-rw-r--r--src/tools/clippy/tests/ui/infinite_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/infinite_loop.stderr33
-rw-r--r--src/tools/clippy/tests/ui/into_iter_without_iter.rs124
-rw-r--r--src/tools/clippy/tests/ui/into_iter_without_iter.stderr114
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs11
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs4
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr2
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs8
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr14
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs11
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed (renamed from src/tools/clippy/tests/ui/items_after_test_module/block_module.rs)15
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/root_module.rs22
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr20
-rw-r--r--src/tools/clippy/tests/ui/iter_without_into_iter.rs120
-rw-r--r--src/tools/clippy/tests/ui/iter_without_into_iter.stderr150
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_future.rs2
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_future.stderr17
-rw-r--r--src/tools/clippy/tests/ui/manual_hash_one.fixed89
-rw-r--r--src/tools/clippy/tests/ui/manual_hash_one.rs89
-rw-r--r--src/tools/clippy/tests/ui/manual_hash_one.stderr56
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.fixed4
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.rs8
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr12
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs3
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr20
-rw-r--r--src/tools/clippy/tests/ui/mut_key.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_key.stderr41
-rw-r--r--src/tools/clippy/tests/ui/mut_reference.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_reference.stderr17
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr42
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.stderr46
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr30
-rw-r--r--src/tools/clippy/tests/ui/print_literal.fixed18
-rw-r--r--src/tools/clippy/tests/ui/print_literal.rs18
-rw-r--r--src/tools/clippy/tests/ui/print_literal.stderr124
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.rs37
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.stderr139
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs2
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr36
-rw-r--r--src/tools/clippy/tests/ui/slow_vector_initialization.rs2
-rw-r--r--src/tools/clippy/tests/ui/slow_vector_initialization.stderr11
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.fixed11
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.rs11
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.stderr22
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.fixed28
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.rs28
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.stderr38
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed28
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr38
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed28
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr38
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.rs28
-rw-r--r--src/tools/clippy/tests/ui/write_literal.fixed14
-rw-r--r--src/tools/clippy/tests/ui/write_literal.rs14
-rw-r--r--src/tools/clippy/tests/ui/write_literal.stderr74
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.rs16
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.stderr82
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/concurrency/thread.rs3
-rw-r--r--tests/run-make/silly-file-names/Makefile18
-rw-r--r--tests/run-make/silly-file-names/silly-file-names.rs4
-rw-r--r--tests/run-make/silly-file-names/silly-file-names.run.stdout2
-rw-r--r--tests/ui/array-slice-vec/vector-no-ann.stderr2
-rw-r--r--tests/ui/asm/x86_64/issue-96797.rs9
-rw-r--r--tests/ui/const-generics/const-argument-if-length.full.stderr16
-rw-r--r--tests/ui/const-generics/issues/issue-83249.stderr15
-rw-r--r--tests/ui/error-codes/E0282.rs2
-rw-r--r--tests/ui/error-codes/E0282.stderr6
-rw-r--r--tests/ui/error-codes/E0401.stderr14
-rw-r--r--tests/ui/for/issue-20605.next.stderr12
-rw-r--r--tests/ui/generic-associated-types/bugs/issue-91762.stderr5
-rw-r--r--tests/ui/generic-const-items/inference-failure.stderr2
-rw-r--r--tests/ui/impl-trait/cross-return-site-inference.rs4
-rw-r--r--tests/ui/impl-trait/cross-return-site-inference.stderr27
-rw-r--r--tests/ui/impl-trait/issues/issue-84073.stderr2
-rw-r--r--tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr6
-rw-r--r--tests/ui/impl-trait/where-allowed-2.stderr6
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.stderr3
-rw-r--r--tests/ui/inference/issue-104649.stderr2
-rw-r--r--tests/ui/inference/issue-71584.rs1
-rw-r--r--tests/ui/inference/issue-71584.stderr2
-rw-r--r--tests/ui/inference/issue-72690.stderr16
-rw-r--r--tests/ui/inference/multiple-impl-apply.rs48
-rw-r--r--tests/ui/inference/multiple-impl-apply.stderr23
-rw-r--r--tests/ui/inference/need_type_info/concrete-impl.rs2
-rw-r--r--tests/ui/inference/need_type_info/concrete-impl.stderr11
-rw-r--r--tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr14
-rw-r--r--tests/ui/inference/question-mark-type-infer.stderr7
-rw-r--r--tests/ui/issues/issue-12187-1.stderr4
-rw-r--r--tests/ui/issues/issue-12187-2.stderr4
-rw-r--r--tests/ui/issues/issue-16966.stderr13
-rw-r--r--tests/ui/issues/issue-17551.stderr2
-rw-r--r--tests/ui/issues/issue-24036.stderr9
-rw-r--r--tests/ui/issues/issue-24446.stderr14
-rw-r--r--tests/ui/iterators/collect-into-slice.stderr20
-rw-r--r--tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr2
-rw-r--r--tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs (renamed from tests/ui/parser/assoc-const-underscore-semantic-fail.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr (renamed from tests/ui/parser/assoc-const-underscore-semantic-fail.stderr)0
-rw-r--r--tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs (renamed from tests/ui/parser/assoc-const-underscore-syntactic-pass.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-oddities-1.rs (renamed from tests/ui/parser/assoc-oddities-1.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-oddities-1.stderr (renamed from tests/ui/parser/assoc-oddities-1.stderr)0
-rw-r--r--tests/ui/parser/assoc/assoc-oddities-2.rs (renamed from tests/ui/parser/assoc-oddities-2.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-oddities-2.stderr (renamed from tests/ui/parser/assoc-oddities-2.stderr)0
-rw-r--r--tests/ui/parser/assoc/assoc-static-semantic-fail.rs (renamed from tests/ui/parser/assoc-static-semantic-fail.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-static-semantic-fail.stderr (renamed from tests/ui/parser/assoc-static-semantic-fail.stderr)0
-rw-r--r--tests/ui/parser/assoc/assoc-static-syntactic-fail.rs (renamed from tests/ui/parser/assoc-static-syntactic-fail.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-static-syntactic-fail.stderr (renamed from tests/ui/parser/assoc-static-syntactic-fail.stderr)0
-rw-r--r--tests/ui/parser/assoc/assoc-type-in-type-arg.rs (renamed from tests/ui/parser/assoc-type-in-type-arg.rs)0
-rw-r--r--tests/ui/parser/assoc/assoc-type-in-type-arg.stderr (renamed from tests/ui/parser/assoc-type-in-type-arg.stderr)0
-rw-r--r--tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.rs (renamed from tests/ui/parser/associated-types-project-from-hrtb-explicit.rs)0
-rw-r--r--tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.stderr (renamed from tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr)0
-rw-r--r--tests/ui/parser/issues/issue-15980.rs3
-rw-r--r--tests/ui/parser/issues/issue-15980.stderr13
-rw-r--r--tests/ui/parser/issues/issue-52496.stderr9
-rw-r--r--tests/ui/parser/issues/issue-89396.fixed4
-rw-r--r--tests/ui/parser/issues/issue-89396.rs4
-rw-r--r--tests/ui/parser/issues/issue-89396.stderr4
-rw-r--r--tests/ui/parser/missing-fat-arrow.rs38
-rw-r--r--tests/ui/parser/missing-fat-arrow.stderr78
-rw-r--r--tests/ui/parser/removed-syntax-with-2.stderr5
-rw-r--r--tests/ui/pattern/slice-patterns-irrefutable.stderr3
-rw-r--r--tests/ui/suggestions/slice-issue-87994.stderr8
-rw-r--r--tests/ui/traits/copy-guessing.stderr2
-rw-r--r--tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs4
-rw-r--r--tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr16
-rw-r--r--tests/ui/traits/issue-77982.rs1
-rw-r--r--tests/ui/traits/issue-77982.stderr32
-rw-r--r--tests/ui/traits/multidispatch-convert-ambig-dest.rs1
-rw-r--r--tests/ui/traits/multidispatch-convert-ambig-dest.stderr16
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.rs1
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.stderr40
-rw-r--r--tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr11
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs3
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr11
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr15
-rw-r--r--tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr14
-rw-r--r--tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs3
-rw-r--r--tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr12
-rw-r--r--tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs4
-rw-r--r--tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr16
-rw-r--r--tests/ui/traits/suggest-fully-qualified-closure.stderr16
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs4
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr32
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs4
-rw-r--r--tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr36
-rw-r--r--tests/ui/type-inference/sort_by_key.stderr11
-rw-r--r--tests/ui/type/type-check/cannot_infer_local_or_vec.stderr2
-rw-r--r--tests/ui/wf/wf-fn-where-clause.stderr18
255 files changed, 7078 insertions, 4889 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 60a8f77c07d..db316e998c1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -508,10 +508,12 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
 
 [[package]]
 name = "clippy"
-version = "0.1.74"
+version = "0.1.75"
 dependencies = [
+ "anstream",
  "clippy_lints",
  "clippy_utils",
+ "color-print",
  "filetime",
  "futures",
  "if_chain",
@@ -546,7 +548,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.74"
+version = "0.1.75"
 dependencies = [
  "arrayvec",
  "cargo_metadata",
@@ -566,11 +568,12 @@ dependencies = [
  "unicode-normalization",
  "unicode-script",
  "url",
+ "walkdir",
 ]
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.74"
+version = "0.1.75"
 dependencies = [
  "arrayvec",
  "if_chain",
@@ -604,6 +607,27 @@ dependencies = [
 ]
 
 [[package]]
+name = "color-print"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d"
+dependencies = [
+ "color-print-proc-macro",
+]
+
+[[package]]
+name = "color-print-proc-macro"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
 name = "color-spantrace"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -933,7 +957,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
 
 [[package]]
 name = "declare_clippy_lint"
-version = "0.1.74"
+version = "0.1.75"
 dependencies = [
  "itertools",
  "quote",
@@ -4311,7 +4335,6 @@ dependencies = [
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
- "rustc_macros",
  "rustc_middle",
  "rustc_query_system",
  "rustc_serialize",
@@ -4417,7 +4440,6 @@ dependencies = [
  "rustc_hir",
  "rustc_interface",
  "rustc_middle",
- "rustc_session",
  "rustc_span",
  "rustc_target",
  "stable_mir",
@@ -4991,6 +5013,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line",
  "alloc",
+ "cc",
  "cfg-if",
  "compiler_builtins",
  "core",
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 6f82d6f9323..f013ff45a4f 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -353,28 +353,28 @@ pub fn find_body_stability(
     body_stab
 }
 
+fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -> Option<()> {
+    if item.is_some() {
+        handle_errors(
+            &sess.parse_sess,
+            meta.span,
+            AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
+        );
+        None
+    } else if let Some(v) = meta.value_str() {
+        *item = Some(v);
+        Some(())
+    } else {
+        sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
+        None
+    }
+}
+
 /// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
 /// its stability information.
 fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
     let meta = attr.meta()?;
     let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
-    let insert_or_error = |meta: &MetaItem, item: &mut Option<Symbol>| {
-        if item.is_some() {
-            handle_errors(
-                &sess.parse_sess,
-                meta.span,
-                AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
-            );
-            return false;
-        }
-        if let Some(v) = meta.value_str() {
-            *item = Some(v);
-            true
-        } else {
-            sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
-            false
-        }
-    };
 
     let mut feature = None;
     let mut since = None;
@@ -389,16 +389,8 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
         };
 
         match mi.name_or_empty() {
-            sym::feature => {
-                if !insert_or_error(mi, &mut feature) {
-                    return None;
-                }
-            }
-            sym::since => {
-                if !insert_or_error(mi, &mut since) {
-                    return None;
-                }
-            }
+            sym::feature => insert_or_error(sess, mi, &mut feature)?,
+            sym::since => insert_or_error(sess, mi, &mut since)?,
             _ => {
                 handle_errors(
                     &sess.parse_sess,
@@ -438,23 +430,6 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
 fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
     let meta = attr.meta()?;
     let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
-    let insert_or_error = |meta: &MetaItem, item: &mut Option<Symbol>| {
-        if item.is_some() {
-            handle_errors(
-                &sess.parse_sess,
-                meta.span,
-                AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
-            );
-            return false;
-        }
-        if let Some(v) = meta.value_str() {
-            *item = Some(v);
-            true
-        } else {
-            sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
-            false
-        }
-    };
 
     let mut feature = None;
     let mut reason = None;
@@ -473,20 +448,10 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
         };
 
         match mi.name_or_empty() {
-            sym::feature => {
-                if !insert_or_error(mi, &mut feature) {
-                    return None;
-                }
-            }
-            sym::reason => {
-                if !insert_or_error(mi, &mut reason) {
-                    return None;
-                }
-            }
+            sym::feature => insert_or_error(sess, mi, &mut feature)?,
+            sym::reason => insert_or_error(sess, mi, &mut reason)?,
             sym::issue => {
-                if !insert_or_error(mi, &mut issue) {
-                    return None;
-                }
+                insert_or_error(sess, mi, &mut issue)?;
 
                 // These unwraps are safe because `insert_or_error` ensures the meta item
                 // is a name/value pair string literal.
@@ -515,11 +480,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
                 }
                 is_soft = true;
             }
-            sym::implied_by => {
-                if !insert_or_error(mi, &mut implied_by) {
-                    return None;
-                }
-            }
+            sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?,
             _ => {
                 handle_errors(
                     &sess.parse_sess,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index b7da15af6dc..ff04b0237c2 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -368,7 +368,7 @@ fn check_opaque_type_well_formed<'tcx>(
     if errors.is_empty() {
         Ok(definition_ty)
     } else {
-        Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
+        Err(infcx.err_ctxt().report_fulfillment_errors(errors))
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 0a451dad9d2..0c0a1e80a41 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -250,17 +250,6 @@ pub(crate) fn verify_func(
 }
 
 fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
-    if let Err(err) =
-        fx.mir.post_mono_checks(fx.tcx, ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c)))
-    {
-        err.emit_err(fx.tcx);
-        fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
-        fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
-        // compilation should have been aborted
-        fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
-        return;
-    }
-
     let arg_uninhabited = fx
         .mir
         .args_iter()
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index fde4e85f966..558f64fffc2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -21,6 +21,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     }
 
     pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::ConstValue<'tcx> {
+        // `MirUsedCollector` visited all constants before codegen began, so if we got here there
+        // can be no more constants that fail to evaluate.
         self.monomorphize(constant.const_)
             .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
             .expect("erroneous constant not captured by required_consts")
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index a61018f9870..d0b799e087b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -209,18 +209,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         caller_location: None,
     };
 
-    fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
+    // It may seem like we should iterate over `required_consts` to ensure they all successfully
+    // evaluate; however, the `MirUsedCollector` already did that during the collection phase of
+    // monomorphization so we don't have to do it again.
 
-    // Rust post-monomorphization checks; we later rely on them.
-    if let Err(err) =
-        mir.post_mono_checks(cx.tcx(), ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c)))
-    {
-        err.emit_err(cx.tcx());
-        // This IR shouldn't ever be emitted, but let's try to guard against any of this code
-        // ever running.
-        start_bx.abort();
-        return;
-    }
+    fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
 
     let memory_locals = analyze::non_ssa_locals(&fx);
 
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index af7dfbef2ff..1c2e8d807f4 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -750,12 +750,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
         if M::POST_MONO_CHECKS {
-            // `ctfe_query` does some error message decoration that we want to be in effect here.
-            self.ctfe_query(None, |tcx| {
-                body.post_mono_checks(*tcx, self.param_env, |c| {
-                    self.subst_from_current_frame_and_normalize_erasing_regions(c)
-                })
-            })?;
+            for &const_ in &body.required_consts {
+                let c =
+                    self.subst_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
+                c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| {
+                    err.emit_note(*self.tcx);
+                    err
+                })?;
+            }
         }
 
         // done
@@ -1054,14 +1056,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
-    /// Call a query that can return `ErrorHandled`. If `span` is `Some`, point to that span when an error occurs.
+    /// Call a query that can return `ErrorHandled`. Should be used for statics and other globals.
+    /// (`mir::Const`/`ty::Const` have `eval` methods that can be used directly instead.)
     pub fn ctfe_query<T>(
         &self,
-        span: Option<Span>,
         query: impl FnOnce(TyCtxtAt<'tcx>) -> Result<T, ErrorHandled>,
     ) -> Result<T, ErrorHandled> {
         // Use a precise span for better cycle errors.
-        query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| {
+        query(self.tcx.at(self.cur_span())).map_err(|err| {
             err.emit_note(*self.tcx);
             err
         })
@@ -1082,7 +1084,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         } else {
             self.param_env
         };
-        let val = self.ctfe_query(None, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
+        let val = self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
         self.raw_const_to_mplace(val)
     }
 
@@ -1092,7 +1094,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         span: Option<Span>,
         layout: Option<TyAndLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
-        let const_val = self.ctfe_query(span, |tcx| val.eval(*tcx, self.param_env, span))?;
+        let const_val = val.eval(*self.tcx, self.param_env, span).map_err(|err| {
+            // FIXME: somehow this is reachable even when POST_MONO_CHECKS is on.
+            // Are we not always populating `required_consts`?
+            err.emit_note(*self.tcx);
+            err
+        })?;
         self.const_val_to_op(const_val, val.ty(), layout)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 2c0ba9b2673..2c6a4de456d 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -164,7 +164,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     sym::type_name => Ty::new_static_str(self.tcx.tcx),
                     _ => bug!(),
                 };
-                let val = self.ctfe_query(None, |tcx| {
+                let val = self.ctfe_query(|tcx| {
                     tcx.const_eval_global_id(self.param_env, gid, Some(tcx.span))
                 })?;
                 let val = self.const_val_to_op(val, ty, Some(dest.layout))?;
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 436c4d521a5..ce666e6af3b 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -536,7 +536,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
 
                 // We don't give a span -- statics don't need that, they cannot be generic or associated.
-                let val = self.ctfe_query(None, |tcx| tcx.eval_static_initializer(def_id))?;
+                let val = self.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
                 (val, Some(def_id))
             }
         };
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index c4d806c5161..f8f9bfb0470 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -743,7 +743,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 let errors = ocx.select_all_or_error();
                 if !errors.is_empty() {
-                    infcx.err_ctxt().report_fulfillment_errors(&errors);
+                    infcx.err_ctxt().report_fulfillment_errors(errors);
                 }
 
                 // Attempting to call a trait method?
diff --git a/compiler/rustc_error_codes/src/error_codes/E0282.md b/compiler/rustc_error_codes/src/error_codes/E0282.md
index 49d2205f92c..5de43982e8b 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0282.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0282.md
@@ -3,7 +3,7 @@ The compiler could not infer a type and asked for a type annotation.
 Erroneous code example:
 
 ```compile_fail,E0282
-let x = "hello".chars().rev().collect();
+let x = Vec::new();
 ```
 
 This error indicates that type inference did not result in one unique possible
@@ -11,21 +11,24 @@ type, and extra information is required. In most cases this can be provided
 by adding a type annotation. Sometimes you need to specify a generic type
 parameter manually.
 
-A common example is the `collect` method on `Iterator`. It has a generic type
-parameter with a `FromIterator` bound, which for a `char` iterator is
-implemented by `Vec` and `String` among others. Consider the following snippet
-that reverses the characters of a string:
+In the example above, type `Vec` has a type parameter `T`. When calling
+`Vec::new`, barring any other later usage of the variable `x` that allows the
+compiler to infer what type `T` is, the compiler needs to be told what it is.
 
-In the first code example, the compiler cannot infer what the type of `x` should
-be: `Vec<char>` and `String` are both suitable candidates. To specify which type
-to use, you can use a type annotation on `x`:
+The type can be specified on the variable:
 
 ```
-let x: Vec<char> = "hello".chars().rev().collect();
+let x: Vec<i32> = Vec::new();
 ```
 
-It is not necessary to annotate the full type. Once the ambiguity is resolved,
-the compiler can infer the rest:
+The type can also be specified in the path of the expression:
+
+```
+let x = Vec::<i32>::new();
+```
+
+In cases with more complex types, it is not necessary to annotate the full
+type. Once the ambiguity is resolved, the compiler can infer the rest:
 
 ```
 let x: Vec<_> = "hello".chars().rev().collect();
diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md
index 79d2c8204f9..b2f0ede6a0b 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0283.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0283.md
@@ -1,8 +1,52 @@
-An implementation cannot be chosen unambiguously because of lack of information.
+The compiler could not infer a type and asked for a type annotation.
 
 Erroneous code example:
 
 ```compile_fail,E0283
+let x = "hello".chars().rev().collect();
+```
+
+This error indicates that type inference did not result in one unique possible
+type, and extra information is required. In most cases this can be provided
+by adding a type annotation. Sometimes you need to specify a generic type
+parameter manually.
+
+A common example is the `collect` method on `Iterator`. It has a generic type
+parameter with a `FromIterator` bound, which for a `char` iterator is
+implemented by `Vec` and `String` among others. Consider the following snippet
+that reverses the characters of a string:
+
+In the first code example, the compiler cannot infer what the type of `x` should
+be: `Vec<char>` and `String` are both suitable candidates. To specify which type
+to use, you can use a type annotation on `x`:
+
+```
+let x: Vec<char> = "hello".chars().rev().collect();
+```
+
+It is not necessary to annotate the full type. Once the ambiguity is resolved,
+the compiler can infer the rest:
+
+```
+let x: Vec<_> = "hello".chars().rev().collect();
+```
+
+Another way to provide the compiler with enough information, is to specify the
+generic type parameter:
+
+```
+let x = "hello".chars().rev().collect::<Vec<char>>();
+```
+
+Again, you need not specify the full type if the compiler can infer it:
+
+```
+let x = "hello".chars().rev().collect::<Vec<_>>();
+```
+
+We can see a self-contained example below:
+
+```compile_fail,E0283
 struct Foo;
 
 impl Into<u32> for Foo {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 44e1bdb8370..486aac21972 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -327,7 +327,7 @@ fn check_opaque_meets_bounds<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
+        let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
         return Err(guar);
     }
     match origin {
@@ -1512,6 +1512,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let errors = fulfillment_cx.select_all_or_error(&infcx);
     debug!(?errors);
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors);
+        infcx.err_ctxt().report_fulfillment_errors(errors);
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 6a1da615055..f1514ecf69c 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -323,7 +323,7 @@ fn compare_method_predicate_entailment<'tcx>(
         // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed.
         let errors = ocx.select_where_possible();
         if !errors.is_empty() {
-            let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+            let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
             return Err(reported);
         }
 
@@ -394,7 +394,7 @@ fn compare_method_predicate_entailment<'tcx>(
                 });
             }
             CheckImpliedWfMode::Skip => {
-                let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+                let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
                 return Err(reported);
             }
         }
@@ -874,7 +874,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     // RPITs.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
         return Err(reported);
     }
 
@@ -2050,7 +2050,7 @@ fn compare_const_predicate_entailment<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
+        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
     }
 
     let outlives_env = OutlivesEnvironment::new(param_env);
@@ -2143,7 +2143,7 @@ fn compare_type_predicate_entailment<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
         return Err(reported);
     }
 
@@ -2358,7 +2358,7 @@ pub(super) fn check_type_bounds<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
         return Err(reported);
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index 3cd3f5bcfdd..6681292c93d 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -158,7 +158,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
         ocx.register_bound(cause, param_env, norm_return_ty, term_did);
         let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
-            infcx.err_ctxt().report_fulfillment_errors(&errors);
+            infcx.err_ctxt().report_fulfillment_errors(errors);
             error = true;
         }
         // now we can take the return type of the given main function
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 5fa65f33c76..5d67a36288c 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -588,7 +588,7 @@ pub fn check_function_signature<'tcx>(
         Ok(()) => {
             let errors = ocx.select_all_or_error();
             if !errors.is_empty() {
-                infcx.err_ctxt().report_fulfillment_errors(&errors);
+                infcx.err_ctxt().report_fulfillment_errors(errors);
                 return;
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index de6ca0d61dc..97ebd42d077 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -116,7 +116,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
 
     let errors = wfcx.select_all_or_error();
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors);
+        infcx.err_ctxt().report_fulfillment_errors(errors);
         return;
     }
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index be70acfc35d..e3e724df272 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -261,7 +261,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                 }
                 let errors = ocx.select_all_or_error();
                 if !errors.is_empty() {
-                    infcx.err_ctxt().report_fulfillment_errors(&errors);
+                    infcx.err_ctxt().report_fulfillment_errors(errors);
                 }
 
                 // Finally, resolve all regions.
@@ -470,7 +470,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
     ocx.register_obligation(obligation);
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors);
+        infcx.err_ctxt().report_fulfillment_errors(errors);
     }
 
     // Finally, resolve all regions.
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index dbd38e1b1fe..b4af321fcc9 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -196,7 +196,7 @@ fn get_impl_args(
 
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
+        let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors);
         return Err(guar);
     }
 
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index d9d0dd93010..a00f3c5d0d8 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2958,7 +2958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // There should be at least one error reported. If not, we
             // will still delay a span bug in `report_fulfillment_errors`.
             Ok::<_, NoSolution>((
-                self.err_ctxt().report_fulfillment_errors(&errors),
+                self.err_ctxt().report_fulfillment_errors(errors),
                 impl_trait_ref.args.type_at(1),
                 element_ty,
             ))
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 415920221f5..5dae74a1f9b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -564,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if !errors.is_empty() {
             self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
-            self.err_ctxt().report_fulfillment_errors(&errors);
+            self.err_ctxt().report_fulfillment_errors(errors);
         }
     }
 
@@ -577,7 +577,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if !result.is_empty() {
             mutate_fulfillment_errors(&mut result);
             self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
-            self.err_ctxt().report_fulfillment_errors(&result);
+            self.err_ctxt().report_fulfillment_errors(result);
         }
     }
 
@@ -1477,7 +1477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 Ok(normalized_ty) => normalized_ty,
                 Err(errors) => {
-                    let guar = self.err_ctxt().report_fulfillment_errors(&errors);
+                    let guar = self.err_ctxt().report_fulfillment_errors(errors);
                     return Ty::new_error(self.tcx,guar);
                 }
             }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index a9029a8cec0..e45108d1713 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -27,7 +27,7 @@ use std::iter;
 
 pub enum TypeAnnotationNeeded {
     /// ```compile_fail,E0282
-    /// let x = "hello".chars().rev().collect();
+    /// let x;
     /// ```
     E0282,
     /// An implementation cannot be chosen unambiguously because of lack of information.
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index 12aeae17725..572751d9511 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -1,3 +1,8 @@
+//! "Hooks" provide a way for `tcx` functionality to be provided by some downstream crate without
+//! everything in rustc having to depend on that crate. This is somewhat similar to queries, but
+//! queries come with a lot of machinery for caching and incremental compilation, whereas hooks are
+//! just plain function pointers without any of the query magic.
+
 use crate::mir;
 use crate::query::TyCtxtAt;
 use crate::ty::{Ty, TyCtxt};
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index bc464aca5f3..9de40b3f974 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -43,21 +43,6 @@ impl ErrorHandled {
         }
     }
 
-    pub fn emit_err(&self, tcx: TyCtxt<'_>) -> ErrorGuaranteed {
-        match self {
-            &ErrorHandled::Reported(err, span) => {
-                if !err.is_tainted_by_errors && !span.is_dummy() {
-                    tcx.sess.emit_err(error::ErroneousConstant { span });
-                }
-                err.error
-            }
-            &ErrorHandled::TooGeneric(span) => tcx.sess.delay_span_bug(
-                span,
-                "encountered TooGeneric error when monomorphic data was expected",
-            ),
-        }
-    }
-
     pub fn emit_note(&self, tcx: TyCtxt<'_>) {
         match self {
             &ErrorHandled::Reported(err, span) => {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 7534c9c0a68..34b6250a89d 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2,7 +2,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
-use crate::mir::interpret::{AllocRange, ConstAllocation, ErrorHandled, Scalar};
+use crate::mir::interpret::{AllocRange, ConstAllocation, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
@@ -568,34 +568,6 @@ impl<'tcx> Body<'tcx> {
     pub fn is_custom_mir(&self) -> bool {
         self.injection_phase.is_some()
     }
-
-    /// *Must* be called once the full substitution for this body is known, to ensure that the body
-    /// is indeed fit for code generation or consumption more generally.
-    ///
-    /// Sadly there's no nice way to represent an "arbitrary normalizer", so we take one for
-    /// constants specifically. (`Option<GenericArgsRef>` could be used for that, but the fact
-    /// that `Instance::args_for_mir_body` is private and instead instance exposes normalization
-    /// functions makes it seem like exposing the generic args is not the intended strategy.)
-    ///
-    /// Also sadly, CTFE doesn't even know whether it runs on MIR that is already polymorphic or still monomorphic,
-    /// so we cannot just immediately ICE on TooGeneric.
-    ///
-    /// Returns Ok(()) if everything went fine, and `Err` if a problem occurred and got reported.
-    pub fn post_mono_checks(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        normalize_const: impl Fn(Const<'tcx>) -> Result<Const<'tcx>, ErrorHandled>,
-    ) -> Result<(), ErrorHandled> {
-        // For now, the only thing we have to check is is to ensure that all the constants used in
-        // the body successfully evaluate.
-        for &const_ in &self.required_consts {
-            let c = normalize_const(const_.const_)?;
-            c.eval(tcx, param_env, Some(const_.span))?;
-        }
-
-        Ok(())
-    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 9bd682d37ab..95c1848bc9b 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -184,6 +184,8 @@ macro_rules! make_mir_visitor {
 
             visit_place_fns!($($mutability)?);
 
+            /// This is called for every constant in the MIR body and every `required_consts`
+            /// (i.e., including consts that have been dead-code-eliminated).
             fn visit_constant(
                 &mut self,
                 constant: & $($mutability)? ConstOperand<'tcx>,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 1a9f0e8352e..8525a4e74c2 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1426,6 +1426,8 @@ fn collect_used_items<'tcx>(
         );
     }
 
+    // Here we rely on the visitor also visiting `required_consts`, so that we evaluate them
+    // and abort compilation if any of them errors.
     MirUsedCollector {
         tcx,
         body: &body,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 88a305e8214..e0778f72bfe 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -225,6 +225,10 @@ parse_expected_semi_found_str = expected `;`, found `{$token}`
 
 parse_expected_statement_after_outer_attr = expected statement after outer attribute
 
+parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$token}`
+    .label = expected one of `,`, `:`, or `{"}"}`
+    .ident_label = while parsing this struct field
+
 parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
 
 parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 7c75e440aaa..aeb4fd0a304 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -431,6 +431,17 @@ pub(crate) struct ExpectedElseBlock {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_expected_struct_field)]
+pub(crate) struct ExpectedStructField {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub token: Token,
+    #[label(parse_ident_label)]
+    pub ident_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_outer_attribute_not_allowed_on_if_else)]
 pub(crate) struct OuterAttributeNotAllowedOnIfElse {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index f4cee3a661e..91bb2d9eb66 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2834,7 +2834,7 @@ impl<'a> Parser<'a> {
             )?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
-                let mut cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?;
+                let mut cond = this.parse_match_guard_condition()?;
 
                 CondChecker { parser: this, forbid_let_reason: None }.visit_expr(&mut cond);
 
@@ -2860,9 +2860,9 @@ impl<'a> Parser<'a> {
                 {
                     err.span_suggestion(
                         this.token.span,
-                        "try using a fat arrow here",
+                        "use a fat arrow to start a match arm",
                         "=>",
-                        Applicability::MaybeIncorrect,
+                        Applicability::MachineApplicable,
                     );
                     err.emit();
                     this.bump();
@@ -2979,6 +2979,33 @@ impl<'a> Parser<'a> {
         })
     }
 
+    fn parse_match_guard_condition(&mut self) -> PResult<'a, P<Expr>> {
+        self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, None).map_err(
+            |mut err| {
+                if self.prev_token == token::OpenDelim(Delimiter::Brace) {
+                    let sugg_sp = self.prev_token.span.shrink_to_lo();
+                    // Consume everything within the braces, let's avoid further parse
+                    // errors.
+                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
+                    let msg = "you might have meant to start a match arm after the match guard";
+                    if self.eat(&token::CloseDelim(Delimiter::Brace)) {
+                        let applicability = if self.token.kind != token::FatArrow {
+                            // We have high confidence that we indeed didn't have a struct
+                            // literal in the match guard, but rather we had some operation
+                            // that ended in a path, immediately followed by a block that was
+                            // meant to be the match arm.
+                            Applicability::MachineApplicable
+                        } else {
+                            Applicability::MaybeIncorrect
+                        };
+                        err.span_suggestion_verbose(sugg_sp, msg, "=> ".to_string(), applicability);
+                    }
+                }
+                err
+            },
+        )
+    }
+
     pub(crate) fn is_builtin(&self) -> bool {
         self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
     }
@@ -3049,9 +3076,10 @@ impl<'a> Parser<'a> {
                     || self.look_ahead(2, |t| t == &token::Colon)
                         && (
                             // `{ ident: token, ` cannot start a block.
-                            self.look_ahead(4, |t| t == &token::Comma) ||
-                // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`.
-                self.look_ahead(3, |t| !t.can_begin_type())
+                            self.look_ahead(4, |t| t == &token::Comma)
+                                // `{ ident: ` cannot start a block unless it's a type ascription
+                                // `ident: Type`.
+                                || self.look_ahead(3, |t| !t.can_begin_type())
                         )
             )
     }
@@ -3091,6 +3119,7 @@ impl<'a> Parser<'a> {
         let mut fields = ThinVec::new();
         let mut base = ast::StructRest::None;
         let mut recover_async = false;
+        let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);
 
         let mut async_block_err = |e: &mut Diagnostic, span: Span| {
             recover_async = true;
@@ -3128,6 +3157,26 @@ impl<'a> Parser<'a> {
                         e.span_label(pth.span, "while parsing this struct");
                     }
 
+                    if let Some((ident, _)) = self.token.ident()
+                        && !self.token.is_reserved_ident()
+                        && self.look_ahead(1, |t| {
+                            AssocOp::from_token(&t).is_some()
+                                || matches!(t.kind, token::OpenDelim(_))
+                                || t.kind == token::Dot
+                        })
+                    {
+                        // Looks like they tried to write a shorthand, complex expression.
+                        e.span_suggestion_verbose(
+                            self.token.span.shrink_to_lo(),
+                            "try naming a field",
+                            &format!("{ident}: ", ),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    if in_if_guard && close_delim == Delimiter::Brace {
+                        return Err(e);
+                    }
+
                     if !recover {
                         return Err(e);
                     }
@@ -3173,19 +3222,6 @@ impl<'a> Parser<'a> {
                                 ",",
                                 Applicability::MachineApplicable,
                             );
-                        } else if is_shorthand
-                            && (AssocOp::from_token(&self.token).is_some()
-                                || matches!(&self.token.kind, token::OpenDelim(_))
-                                || self.token.kind == token::Dot)
-                        {
-                            // Looks like they tried to write a shorthand, complex expression.
-                            let ident = parsed_field.expect("is_shorthand implies Some").ident;
-                            e.span_suggestion(
-                                ident.span.shrink_to_lo(),
-                                "try naming a field",
-                                &format!("{ident}: "),
-                                Applicability::HasPlaceholders,
-                            );
                         }
                     }
                     if !recover {
@@ -3288,6 +3324,24 @@ impl<'a> Parser<'a> {
 
             // Check if a colon exists one ahead. This means we're parsing a fieldname.
             let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq);
+            // Proactively check whether parsing the field will be incorrect.
+            let is_wrong = this.token.is_ident()
+                && !this.token.is_reserved_ident()
+                && !this.look_ahead(1, |t| {
+                    t == &token::Colon
+                        || t == &token::Eq
+                        || t == &token::Comma
+                        || t == &token::CloseDelim(Delimiter::Brace)
+                        || t == &token::CloseDelim(Delimiter::Parenthesis)
+                });
+            if is_wrong {
+                return Err(errors::ExpectedStructField {
+                    span: this.look_ahead(1, |t| t.span),
+                    ident_span: this.token.span,
+                    token: this.look_ahead(1, |t| t.clone()),
+                }
+                .into_diagnostic(&self.sess.span_diagnostic));
+            }
             let (ident, expr) = if is_shorthand {
                 // Mimic `x: x` for the `x` field shorthand.
                 let ident = this.parse_ident_common(false)?;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index e84d8f5b358..6c24646f39a 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -52,6 +52,7 @@ bitflags::bitflags! {
         const NO_STRUCT_LITERAL = 1 << 1;
         const CONST_EXPR        = 1 << 2;
         const ALLOW_LET         = 1 << 3;
+        const IN_IF_GUARD       = 1 << 4;
     }
 }
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 9a7564cb213..52fb193f3da 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2373,7 +2373,7 @@ impl CheckAttrVisitor<'_> {
 
         let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
-            infcx.err_ctxt().report_fulfillment_errors(&errors);
+            infcx.err_ctxt().report_fulfillment_errors(errors);
             self.abort.set(true);
         }
     }
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index e195f9ab6da..2129a98cda3 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -57,7 +57,7 @@ pub fn ensure_wf<'tcx>(
     ocx.register_obligation(obligation);
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors);
+        infcx.err_ctxt().report_fulfillment_errors(errors);
         false
     } else {
         // looks WF!
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index a44dd5ede2f..a350e8b2e3a 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
-rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc-rayon-core = { version = "0.5.0", optional = true }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index d29ab02c1a6..e120f595d92 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -813,7 +813,6 @@ impl Input {
                 FileName::Anon(_) => None,
                 FileName::MacroExpansion(_) => None,
                 FileName::ProcMacroSourceCode(_) => None,
-                FileName::CfgSpec(_) => None,
                 FileName::CliCrateAttr(_) => None,
                 FileName::Custom(_) => None,
                 FileName::DocTest(path, _) => Some(path),
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index 4c29f743708..3e0d6baab6a 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -4,14 +4,13 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+rustc_driver = { path = "../rustc_driver" }
 rustc_hir = { path = "../rustc_hir" }
+rustc_interface = { path = "../rustc_interface" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-rustc_driver = { path = "../rustc_driver" }
-rustc_interface = { path = "../rustc_interface" }
-rustc_session = {path = "../rustc_session" }
-tracing = "0.1"
 stable_mir = {path = "../stable_mir" }
+tracing = "0.1"
 
 [features]
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index b6c36678db5..d10f46fad9e 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -10,10 +10,6 @@
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(attr(allow(unused_variables), deny(warnings)))
 )]
-#![feature(rustc_private)]
-#![feature(ptr_metadata)]
-#![feature(type_alias_impl_trait)] // Used to define opaque types.
-#![feature(intra_doc_pointers)]
 
 pub mod rustc_internal;
 
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 1a9dea99f64..36eb2247253 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -11,7 +11,7 @@ use rustc_driver::{Callbacks, Compilation, RunCompiler};
 use rustc_interface::{interface, Queries};
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::ty::TyCtxt;
-pub use rustc_span::def_id::{CrateNum, DefId};
+use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Span;
 use stable_mir::CompilerError;
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 772e09291a1..6fd61e45fcc 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -280,8 +280,7 @@ impl RealFileName {
 }
 
 /// Differentiates between real files and common virtual files.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
-#[derive(Decodable, Encodable)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)]
 pub enum FileName {
     Real(RealFileName),
     /// Call to `quote!`.
@@ -292,8 +291,6 @@ pub enum FileName {
     // FIXME(jseyfried)
     MacroExpansion(Hash64),
     ProcMacroSourceCode(Hash64),
-    /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`.
-    CfgSpec(Hash64),
     /// Strings provided as crate attributes in the CLI.
     CliCrateAttr(Hash64),
     /// Custom sources for explicit parser calls from plugins and drivers.
@@ -305,7 +302,6 @@ pub enum FileName {
 
 impl From<PathBuf> for FileName {
     fn from(p: PathBuf) -> Self {
-        assert!(!p.to_string_lossy().ends_with('>'));
         FileName::Real(RealFileName::LocalPath(p))
     }
 }
@@ -339,7 +335,6 @@ impl fmt::Display for FileNameDisplay<'_> {
             MacroExpansion(_) => write!(fmt, "<macro expansion>"),
             Anon(_) => write!(fmt, "<anon>"),
             ProcMacroSourceCode(_) => write!(fmt, "<proc-macro source code>"),
-            CfgSpec(_) => write!(fmt, "<cfgspec>"),
             CliCrateAttr(_) => write!(fmt, "<crate attribute>"),
             Custom(ref s) => write!(fmt, "<{s}>"),
             DocTest(ref path, _) => write!(fmt, "{}", path.display()),
@@ -365,7 +360,6 @@ impl FileName {
             Anon(_)
             | MacroExpansion(_)
             | ProcMacroSourceCode(_)
-            | CfgSpec(_)
             | CliCrateAttr(_)
             | Custom(_)
             | QuoteExpansion(_)
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 015e38b2ac0..88f47b03cc8 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -218,7 +218,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         def_id: LocalDefId,
     ) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
         self.assumed_wf_types(param_env, def_id)
-            .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors))
+            .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
     }
 
     pub fn assumed_wf_types(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
new file mode 100644
index 00000000000..b4835b011dd
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
@@ -0,0 +1,275 @@
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::InferCtxt;
+use crate::traits::{Obligation, ObligationCause, ObligationCtxt};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_hir as hir;
+use rustc_hir::Node;
+use rustc_middle::ty::{self, Ty};
+use rustc_span::{Span, DUMMY_SP};
+
+use super::ArgKind;
+
+pub use rustc_infer::traits::error_reporting::*;
+
+pub trait InferCtxtExt<'tcx> {
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>;
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+        closure_pipe_span: Option<Span>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+
+    /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
+    /// in that order, and returns the generic type corresponding to the
+    /// argument of that trait (corresponding to the closure arguments).
+    fn type_implements_fn_trait(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: ty::Binder<'tcx, Ty<'tcx>>,
+        polarity: ty::ImplPolarity,
+    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
+}
+
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)> {
+        let sm = self.tcx.sess.source_map();
+        let hir = self.tcx.hir();
+        Some(match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }),
+                ..
+            }) => (
+                fn_decl_span,
+                fn_arg_span,
+                hir.body(body)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+                            *arg.pat
+                        {
+                            Some(ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        sm.span_to_snippet(pat.span)
+                                            .ok()
+                                            .map(|snippet| (snippet, "_".to_owned()))
+                                    })
+                                    .collect::<Option<Vec<_>>>()?,
+                            ))
+                        } else {
+                            let name = sm.span_to_snippet(arg.pat.span).ok()?;
+                            Some(ArgKind::Arg(name, "_".to_owned()))
+                        }
+                    })
+                    .collect::<Option<Vec<ArgKind>>>()?,
+            ),
+            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
+            | Node::TraitItem(&hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(ref sig, _), ..
+            }) => (
+                sig.span,
+                None,
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.kind {
+                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
+                (span, None, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {node:?}"),
+        })
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+        closure_arg_span: Option<Span>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = matches!(other, &[ArgKind::Tuple(..)]);
+            match (arg_length, arguments.get(0)) {
+                (1, Some(ArgKind::Tuple(_, fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {kind} that takes {expected_str}"));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {found_str}"));
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion_verbose(
+                    closure_arg_span.unwrap_or(found_span),
+                    format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        pluralize!(expected_args.len())
+                    ),
+                    format!("|{underscores}|"),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion_verbose(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{sugg}|"),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
+                && fields.len() == found_args.len()
+                && is_closure
+            {
+                let sugg = format!(
+                    "|({}){}|",
+                    found_args
+                        .iter()
+                        .map(|arg| match arg {
+                            ArgKind::Arg(name, _) => name.to_owned(),
+                            _ => "_".to_owned(),
+                        })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    // add type annotations if available
+                    if found_args.iter().any(|arg| match arg {
+                        ArgKind::Arg(_, ty) => ty != "_",
+                        _ => false,
+                    }) {
+                        format!(
+                            ": ({})",
+                            fields
+                                .iter()
+                                .map(|(_, ty)| ty.to_owned())
+                                .collect::<Vec<String>>()
+                                .join(", ")
+                        )
+                    } else {
+                        String::new()
+                    },
+                );
+                err.span_suggestion_verbose(
+                    found_span,
+                    "change the closure to accept a tuple instead of individual arguments",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+
+        err
+    }
+
+    fn type_implements_fn_trait(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: ty::Binder<'tcx, Ty<'tcx>>,
+        polarity: ty::ImplPolarity,
+    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
+        self.commit_if_ok(|_| {
+            for trait_def_id in [
+                self.tcx.lang_items().fn_trait(),
+                self.tcx.lang_items().fn_mut_trait(),
+                self.tcx.lang_items().fn_once_trait(),
+            ] {
+                let Some(trait_def_id) = trait_def_id else { continue };
+                // Make a fresh inference variable so we can determine what the substitutions
+                // of the trait are.
+                let var = self.next_ty_var(TypeVariableOrigin {
+                    span: DUMMY_SP,
+                    kind: TypeVariableOriginKind::MiscVariable,
+                });
+                // FIXME(effects)
+                let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
+                let obligation = Obligation::new(
+                    self.tcx,
+                    ObligationCause::dummy(),
+                    param_env,
+                    ty.rebind(ty::TraitPredicate { trait_ref, polarity }),
+                );
+                let ocx = ObligationCtxt::new(self);
+                ocx.register_obligation(obligation);
+                if ocx.select_all_or_error().is_empty() {
+                    return Ok((
+                        self.tcx
+                            .fn_trait_kind_from_def_id(trait_def_id)
+                            .expect("expected to map DefId to ClosureKind"),
+                        ty.rebind(self.resolve_vars_if_possible(var)),
+                    ));
+                }
+            }
+
+            Err(())
+        })
+    }
+}
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 9a728b1060f..989c1310b76 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,58 +1,25 @@
 // ignore-tidy-filelength :(
 
 mod ambiguity;
+mod infer_ctxt_ext;
 pub mod on_unimplemented;
 pub mod suggestions;
+mod type_err_ctxt_ext;
 
-use super::{
-    FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, ObligationCause,
-    ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
-    PredicateObligation, SelectionError, TraitNotObjectSafe,
-};
-use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch};
-use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt};
+use super::{Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
+use crate::infer::InferCtxt;
 use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::specialize::to_pretty_impl_header;
-use crate::traits::NormalizeExt;
-use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_errors::{
-    pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan, Style,
-};
 use rustc_hir as hir;
-use rustc_hir::def::Namespace;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{GenericParam, Item, Node};
-use rustc_infer::infer::error_reporting::TypeErrCtxt;
-use rustc_infer::infer::{InferOk, TypeTrace};
-use rustc_middle::traits::select::OverflowError;
 use rustc_middle::traits::solve::Goal;
-use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
-use rustc_middle::ty::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
-use rustc_middle::ty::{
-    self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
-    TypeVisitable, TypeVisitableExt,
-};
-use rustc_session::config::{DumpSolverProofTree, TraitSolver};
-use rustc_session::Limit;
-use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::symbol::sym;
-use rustc_span::{ExpnKind, Span, DUMMY_SP};
-use std::borrow::Cow;
-use std::fmt;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
 use std::io::Write;
-use std::iter;
 use std::ops::ControlFlow;
-use suggestions::TypeErrCtxtExt as _;
 
+pub use self::infer_ctxt_ext::*;
+pub use self::type_err_ctxt_ext::*;
 pub use rustc_infer::traits::error_reporting::*;
 
 // When outputting impl candidates, prefer showing those that are more similar.
@@ -77,3438 +44,8 @@ enum GetSafeTransmuteErrorAndReason {
     Error { err_msg: String, safe_transmute_explanation: String },
 }
 
-pub trait InferCtxtExt<'tcx> {
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>;
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-        closure_pipe_span: Option<Span>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
-
-    /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
-    /// in that order, and returns the generic type corresponding to the
-    /// argument of that trait (corresponding to the closure arguments).
-    fn type_implements_fn_trait(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: ty::Binder<'tcx, Ty<'tcx>>,
-        polarity: ty::ImplPolarity,
-    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
-}
-
-pub trait TypeErrCtxtExt<'tcx> {
-    fn build_overflow_error<T>(
-        &self,
-        predicate: &T,
-        span: Span,
-        suggest_increasing_limit: bool,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
-    where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
-
-    fn report_overflow_error<T>(
-        &self,
-        predicate: &T,
-        span: Span,
-        suggest_increasing_limit: bool,
-        mutate: impl FnOnce(&mut Diagnostic),
-    ) -> !
-    where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
-
-    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
-
-    fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed;
-
-    fn report_overflow_obligation<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: ToPredicate<'tcx> + Clone;
-
-    fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
-
-    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
-
-    /// The `root_obligation` parameter should be the `root_obligation` field
-    /// from a `FulfillmentError`. If no `FulfillmentError` is available,
-    /// then it should be the same as `obligation`.
-    fn report_selection_error(
-        &self,
-        obligation: PredicateObligation<'tcx>,
-        root_obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-    );
-
-    fn report_const_param_not_wf(
-        &self,
-        ty: Ty<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)> {
-        let sm = self.tcx.sess.source_map();
-        let hir = self.tcx.hir();
-        Some(match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }),
-                ..
-            }) => (
-                fn_decl_span,
-                fn_arg_span,
-                hir.body(body)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            Some(ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        sm.span_to_snippet(pat.span)
-                                            .ok()
-                                            .map(|snippet| (snippet, "_".to_owned()))
-                                    })
-                                    .collect::<Option<Vec<_>>>()?,
-                            ))
-                        } else {
-                            let name = sm.span_to_snippet(arg.pat.span).ok()?;
-                            Some(ArgKind::Arg(name, "_".to_owned()))
-                        }
-                    })
-                    .collect::<Option<Vec<ArgKind>>>()?,
-            ),
-            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
-            | Node::TraitItem(&hir::TraitItem {
-                kind: hir::TraitItemKind::Fn(ref sig, _), ..
-            }) => (
-                sig.span,
-                None,
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
-                (span, None, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {node:?}"),
-        })
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-        closure_arg_span: Option<Span>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = matches!(other, &[ArgKind::Tuple(..)]);
-            match (arg_length, arguments.get(0)) {
-                (1, Some(ArgKind::Tuple(_, fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {kind} that takes {expected_str}"));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {found_str}"));
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion_verbose(
-                    closure_arg_span.unwrap_or(found_span),
-                    format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        pluralize!(expected_args.len())
-                    ),
-                    format!("|{underscores}|"),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion_verbose(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{sugg}|"),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
-                && fields.len() == found_args.len()
-                && is_closure
-            {
-                let sugg = format!(
-                    "|({}){}|",
-                    found_args
-                        .iter()
-                        .map(|arg| match arg {
-                            ArgKind::Arg(name, _) => name.to_owned(),
-                            _ => "_".to_owned(),
-                        })
-                        .collect::<Vec<String>>()
-                        .join(", "),
-                    // add type annotations if available
-                    if found_args.iter().any(|arg| match arg {
-                        ArgKind::Arg(_, ty) => ty != "_",
-                        _ => false,
-                    }) {
-                        format!(
-                            ": ({})",
-                            fields
-                                .iter()
-                                .map(|(_, ty)| ty.to_owned())
-                                .collect::<Vec<String>>()
-                                .join(", ")
-                        )
-                    } else {
-                        String::new()
-                    },
-                );
-                err.span_suggestion_verbose(
-                    found_span,
-                    "change the closure to accept a tuple instead of individual arguments",
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-
-        err
-    }
-
-    fn type_implements_fn_trait(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: ty::Binder<'tcx, Ty<'tcx>>,
-        polarity: ty::ImplPolarity,
-    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
-        self.commit_if_ok(|_| {
-            for trait_def_id in [
-                self.tcx.lang_items().fn_trait(),
-                self.tcx.lang_items().fn_mut_trait(),
-                self.tcx.lang_items().fn_once_trait(),
-            ] {
-                let Some(trait_def_id) = trait_def_id else { continue };
-                // Make a fresh inference variable so we can determine what the substitutions
-                // of the trait are.
-                let var = self.next_ty_var(TypeVariableOrigin {
-                    span: DUMMY_SP,
-                    kind: TypeVariableOriginKind::MiscVariable,
-                });
-                // FIXME(effects)
-                let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
-                let obligation = Obligation::new(
-                    self.tcx,
-                    ObligationCause::dummy(),
-                    param_env,
-                    ty.rebind(ty::TraitPredicate { trait_ref, polarity }),
-                );
-                let ocx = ObligationCtxt::new(self);
-                ocx.register_obligation(obligation);
-                if ocx.select_all_or_error().is_empty() {
-                    return Ok((
-                        self.tcx
-                            .fn_trait_kind_from_def_id(trait_def_id)
-                            .expect("expected to map DefId to ClosureKind"),
-                        ty.rebind(self.resolve_vars_if_possible(var)),
-                    ));
-                }
-            }
-
-            Err(())
-        })
-    }
-}
-
-impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
-    fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxIndexMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // We want to ignore desugarings here: spans are equivalent even
-            // if one is the result of a desugaring and the other is not.
-            let mut span = error.obligation.cause.span;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate,
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate);
-        }
-
-        // We do this in 2 passes because we want to display errors in order, though
-        // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed = vec![false; errors.len()];
-        for (_, error_set) in error_map.iter() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.is_some_and(|index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(error2.predicate, error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(error.predicate, error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for from_expansion in [false, true] {
-            for (error, suppressed) in iter::zip(errors, &is_suppressed) {
-                if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
-                    self.report_fulfillment_error(error);
-                }
-            }
-        }
-
-        self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fulfillment errors")
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    fn report_overflow_error<T>(
-        &self,
-        predicate: &T,
-        span: Span,
-        suggest_increasing_limit: bool,
-        mutate: impl FnOnce(&mut Diagnostic),
-    ) -> !
-    where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
-    {
-        let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit);
-        mutate(&mut err);
-        err.emit();
-
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    fn build_overflow_error<T>(
-        &self,
-        predicate: &T,
-        span: Span,
-        suggest_increasing_limit: bool,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
-    where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
-    {
-        let predicate = self.resolve_vars_if_possible(predicate.clone());
-        let mut pred_str = predicate.to_string();
-
-        if pred_str.len() > 50 {
-            // We don't need to save the type to a file, we will be talking about this type already
-            // in a separate note when we explain the obligation, so it will be available that way.
-            pred_str = predicate
-                .print(FmtPrinter::new_with_limit(
-                    self.tcx,
-                    Namespace::TypeNS,
-                    rustc_session::Limit(6),
-                ))
-                .unwrap()
-                .into_buffer();
-        }
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            pred_str,
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        err
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    fn report_overflow_obligation<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: ToPredicate<'tcx> + Clone,
-    {
-        let predicate = obligation.predicate.clone().to_predicate(self.tcx);
-        let predicate = self.resolve_vars_if_possible(predicate);
-        self.report_overflow_error(
-            &predicate,
-            obligation.cause.span,
-            suggest_increasing_limit,
-            |err| {
-                self.note_obligation_cause_code(
-                    obligation.cause.body_id,
-                    err,
-                    predicate,
-                    obligation.param_env,
-                    obligation.cause.code(),
-                    &mut vec![],
-                    &mut Default::default(),
-                );
-            },
-        );
-    }
-
-    fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
-        let suggested_limit = match self.tcx.recursion_limit() {
-            Limit(0) => Limit(2),
-            limit => limit * 2,
-        };
-        err.help(format!(
-            "consider increasing the recursion limit by adding a \
-             `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit,
-            self.tcx.crate_name(LOCAL_CRATE),
-        ));
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_obligation` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(cycle.to_owned());
-        assert!(!cycle.is_empty());
-
-        debug!(?cycle, "report_overflow_error_cycle");
-
-        // The 'deepest' obligation is most likely to have a useful
-        // cause 'backtrace'
-        self.report_overflow_obligation(
-            cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
-            false,
-        );
-    }
-
-    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
-        let obligation = self.resolve_vars_if_possible(obligation);
-        let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
-        self.note_obligation_cause(&mut err, &obligation);
-        self.point_at_returns_when_relevant(&mut err, &obligation);
-        err.emit()
-    }
-
-    fn report_selection_error(
-        &self,
-        mut obligation: PredicateObligation<'tcx>,
-        root_obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-    ) {
-        let tcx = self.tcx;
-
-        if tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError {
-            dump_proof_tree(root_obligation, self.infcx);
-        }
-
-        let mut span = obligation.cause.span;
-        // FIXME: statically guarantee this by tainting after the diagnostic is emitted
-        self.set_tainted_by_errors(
-            tcx.sess.delay_span_bug(span, "`report_selection_error` did not emit an error"),
-        );
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                // If this obligation was generated as a result of well-formedness checking, see if we
-                // can get a better error message by performing HIR-based well-formedness checking.
-                if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
-                    root_obligation.cause.code().peel_derives()
-                    && !obligation.predicate.has_non_region_infer()
-                {
-                    if let Some(cause) = self
-                        .tcx
-                        .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc))
-                    {
-                        obligation.cause = cause.clone();
-                        span = obligation.cause.span;
-                    }
-                }
-
-                if let ObligationCauseCode::CompareImplItemObligation {
-                    impl_item_def_id,
-                    trait_item_def_id,
-                    kind: _,
-                } = *obligation.cause.code()
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-
-                // Report a const-param specific error
-                if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()
-                {
-                    self.report_const_param_not_wf(ty, &obligation).emit();
-                    return;
-                }
-
-                let bound_predicate = obligation.predicate.kind();
-                match bound_predicate.skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
-                        let trait_predicate = bound_predicate.rebind(trait_predicate);
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        // FIXME(effects)
-                        let predicate_is_const = false;
-
-                        if self.tcx.sess.has_errors().is_some()
-                            && trait_predicate.references_error()
-                        {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-
-                        let (post_message, pre_message, type_def) = self
-                            .get_parent_trait_ref(obligation.cause.code())
-                            .map(|(t, s)| {
-                                (
-                                    format!(" in `{t}`"),
-                                    format!("within `{t}`, "),
-                                    s.map(|s| (format!("within this `{t}`"), s)),
-                                )
-                            })
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote {
-                            message,
-                            label,
-                            note,
-                            parent_label,
-                            append_const_msg,
-                        } = self.on_unimplemented_note(trait_ref, &obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
-                        let is_unsize =
-                            Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait();
-                        let (message, note, append_const_msg) = if is_try_conversion {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.skip_binder().self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                     conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                                Some(AppendConstMessage::Default),
-                            )
-                        } else {
-                            (message, note, append_const_msg)
-                        };
-
-                        let err_msg = self.get_standard_error_message(
-                            &trait_predicate,
-                            message,
-                            predicate_is_const,
-                            append_const_msg,
-                            post_message,
-                        );
-
-                        let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id())
-                            == self.tcx.lang_items().transmute_trait()
-                        {
-                            // Recompute the safe transmute reason and use that for the error reporting
-                            match self.get_safe_transmute_error_and_reason(
-                                obligation.clone(),
-                                trait_ref,
-                                span,
-                            ) {
-                                GetSafeTransmuteErrorAndReason::Silent => return,
-                                GetSafeTransmuteErrorAndReason::Error {
-                                    err_msg,
-                                    safe_transmute_explanation,
-                                } => (err_msg, Some(safe_transmute_explanation)),
-                            }
-                        } else {
-                            (err_msg, None)
-                        };
-
-                        let mut err = struct_span_err!(self.tcx.sess, span, E0277, "{}", err_msg);
-
-                        if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
-                            err.span_label(
-                                ret_span,
-                                format!(
-                                    "expected `{}` because of this",
-                                    trait_ref.skip_binder().self_ty()
-                                ),
-                            );
-                        }
-
-                        if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
-                            self.add_tuple_trait_message(
-                                &obligation.cause.code().peel_derives(),
-                                &mut err,
-                            );
-                        }
-
-                        if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait()
-                            && predicate_is_const
-                        {
-                            err.note("`~const Drop` was renamed to `~const Destruct`");
-                            err.note("See <https://github.com/rust-lang/rust/pull/94901> for more details");
-                        }
-
-                        let explanation = get_explanation_based_on_obligation(
-                            &obligation,
-                            trait_ref,
-                            &trait_predicate,
-                            pre_message,
-                        );
-
-                        self.check_for_binding_assigned_block_without_tail_expression(
-                            &obligation,
-                            &mut err,
-                            trait_predicate,
-                        );
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            trait_predicate,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, &obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s);
-                            if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
-                                // When the self type is a type param We don't need to "the trait
-                                // `std::marker::Sized` is not implemented for `T`" as we will point
-                                // at the type param with a label to suggest constraining it.
-                                err.help(explanation);
-                            }
-                        } else if let Some(custom_explanation) = safe_transmute_explanation {
-                            err.span_label(span, custom_explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-
-                        if let ObligationCauseCode::Coercion { source, target } =
-                            *obligation.cause.code().peel_derives()
-                        {
-                            if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
-                                self.suggest_borrowing_for_object_cast(
-                                    &mut err,
-                                    &root_obligation,
-                                    source,
-                                    target,
-                                );
-                            }
-                        }
-
-                        let UnsatisfiedConst(unsatisfied_const) = self
-                            .maybe_add_note_for_unsatisfied_const(
-                                &obligation,
-                                trait_ref,
-                                &trait_predicate,
-                                &mut err,
-                                span,
-                            );
-
-                        if let Some((msg, span)) = type_def {
-                            err.span_label(span, msg);
-                        }
-                        if let Some(s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s);
-                        }
-                        if let Some(s) = parent_label {
-                            let body = obligation.cause.body_id;
-                            err.span_label(tcx.def_span(body), s);
-                        }
-
-                        self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
-                        self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate);
-                        let mut suggested =
-                            self.suggest_dereferences(&obligation, &mut err, trait_predicate);
-                        suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
-                        let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
-                        suggested = if let &[cand] = &impl_candidates[..] {
-                            let cand = cand.trait_ref;
-                            if let (ty::FnPtr(_), ty::FnDef(..)) =
-                                (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind())
-                            {
-                                err.span_suggestion(
-                                    span.shrink_to_hi(),
-                                    format!(
-                                        "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
-                                        cand.print_only_trait_path(),
-                                        cand.self_ty(),
-                                    ),
-                                    format!(" as {}", cand.self_ty()),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                true
-                            } else {
-                                false
-                            }
-                        } else {
-                            false
-                        } || suggested;
-                        suggested |=
-                            self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
-                        suggested |= self.suggest_semicolon_removal(
-                            &obligation,
-                            &mut err,
-                            span,
-                            trait_predicate,
-                        );
-                        self.note_version_mismatch(&mut err, &trait_ref);
-                        self.suggest_remove_await(&obligation, &mut err);
-                        self.suggest_derive(&obligation, &mut err, trait_predicate);
-
-                        if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
-                            self.suggest_await_before_try(
-                                &mut err,
-                                &obligation,
-                                trait_predicate,
-                                span,
-                            );
-                        }
-
-                        if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) {
-                            err.emit();
-                            return;
-                        }
-
-                        if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
-                            err.emit();
-                            return;
-                        }
-
-                        if is_unsize {
-                            // If the obligation failed due to a missing implementation of the
-                            // `Unsize` trait, give a pointer to why that might be the case
-                            err.note(
-                                "all implementations of `Unsize` are provided \
-                                automatically by the compiler, see \
-                                <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \
-                                for more information",
-                            );
-                        }
-
-                        let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id());
-                        let is_target_feature_fn = if let ty::FnDef(def_id, _) =
-                            *trait_ref.skip_binder().self_ty().kind()
-                        {
-                            !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
-                        } else {
-                            false
-                        };
-                        if is_fn_trait && is_target_feature_fn {
-                            err.note(
-                                "`#[target_feature]` functions do not implement the `Fn` traits",
-                            );
-                        }
-
-                        self.try_to_add_help_message(
-                            &obligation,
-                            trait_ref,
-                            &trait_predicate,
-                            &mut err,
-                            span,
-                            is_fn_trait,
-                            suggested,
-                            unsatisfied_const,
-                        );
-
-                        // Changing mutability doesn't make a difference to whether we have
-                        // an `Unsize` impl (Fixes ICE in #71036)
-                        if !is_unsize {
-                            self.suggest_change_mut(&obligation, &mut err, trait_predicate);
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && self.fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|trait_pred| {
-                                trait_pred.with_self_ty(self.tcx, Ty::new_unit(self.tcx))
-                            });
-                            let unit_obligation = obligation.with(tcx, predicate);
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.note(
-                                    "this error might have been caused by changes to \
-                                    Rust's type-inference algorithm (see issue #48950 \
-                                    <https://github.com/rust-lang/rust/issues/48950> \
-                                    for more information)",
-                                );
-                                err.help("did you intend to use the type `()` here instead?");
-                            }
-                        }
-
-                        self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause);
-                        self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref);
-
-                        // Return early if the trait is Debug or Display and the invocation
-                        // originates within a standard library macro, because the output
-                        // is otherwise overwhelming and unhelpful (see #85844 for an
-                        // example).
-
-                        let in_std_macro =
-                            match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
-                                Some(macro_def_id) => {
-                                    let crate_name = tcx.crate_name(macro_def_id.krate);
-                                    crate_name == sym::std || crate_name == sym::core
-                                }
-                                None => false,
-                            };
-
-                        if in_std_macro
-                            && matches!(
-                                self.tcx.get_diagnostic_name(trait_ref.def_id()),
-                                Some(sym::Debug | sym::Display)
-                            )
-                        {
-                            err.emit();
-                            return;
-                        }
-
-                        err
-                    }
-
-                    ty::PredicateKind::Subtype(predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::PredicateKind::Coerce(predicate) => {
-                        // Errors for Coerce predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
-                    | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => {
-                        span_bug!(
-                            span,
-                            "outlives clauses should not error outside borrowck. obligation: `{:?}`",
-                            obligation
-                        )
-                    }
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
-                        span_bug!(
-                            span,
-                            "projection clauses should be implied from elsewhere. obligation: `{:?}`",
-                            obligation
-                        )
-                    }
-
-                    ty::PredicateKind::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
-                        let found_kind = self.closure_kind(closure_args).unwrap();
-                        self.report_closure_error(&obligation, closure_def_id, found_kind, kind)
-                    }
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
-                        let ty = self.resolve_vars_if_possible(ty);
-                        match self.tcx.sess.opts.unstable_opts.trait_solver {
-                            TraitSolver::Classic => {
-                                // WF predicates cannot themselves make
-                                // errors. They can only block due to
-                                // ambiguity; otherwise, they always
-                                // degenerate into other obligations
-                                // (which may fail).
-                                span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                            }
-                            TraitSolver::Next | TraitSolver::NextCoherence => {
-                                // FIXME: we'll need a better message which takes into account
-                                // which bounds actually failed to hold.
-                                self.tcx.sess.struct_span_err(
-                                    span,
-                                    format!("the type `{ty}` is not well-formed"),
-                                )
-                            }
-                        }
-                    }
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-
-                    ty::PredicateKind::ConstEquate(..) => {
-                        // Errors for `ConstEquate` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-equate requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-
-                    ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
-
-                    ty::PredicateKind::AliasRelate(..) => span_bug!(
-                        span,
-                        "AliasRelate predicate should never be the predicate cause of a SelectionError"
-                    ),
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
-                        let mut diag = self.tcx.sess.struct_span_err(
-                            span,
-                            format!("the constant `{ct}` is not of type `{ty}`"),
-                        );
-                        self.note_type_err(
-                            &mut diag,
-                            &obligation.cause,
-                            None,
-                            None,
-                            TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())),
-                            false,
-                            false,
-                        );
-                        diag
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
-                found_trait_ref,
-                expected_trait_ref,
-                terr: terr @ TypeError::CyclicTy(_),
-            }) => self.report_type_parameter_mismatch_cyclic_type_error(
-                &obligation,
-                found_trait_ref,
-                expected_trait_ref,
-                terr,
-            ),
-            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
-                found_trait_ref,
-                expected_trait_ref,
-                terr: _,
-            }) => {
-                match self.report_type_parameter_mismatch_error(
-                    &obligation,
-                    span,
-                    found_trait_ref,
-                    expected_trait_ref,
-                ) {
-                    Some(err) => err,
-                    None => return,
-                }
-            }
-
-            SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage(
-                &obligation,
-                def_id,
-            ),
-
-            TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {
-                bug!(
-                    "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"
-                )
-            }
-            SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
-                match self.report_not_const_evaluatable_error(&obligation, span) {
-                    Some(err) => err,
-                    None => return,
-                }
-            }
-
-            // Already reported in the query.
-            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) |
-            // Already reported.
-            Overflow(OverflowError::Error(_)) => return,
-
-            Overflow(_) => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-            SelectionError::ErrorReporting => {
-                bug!("ErrorReporting Overflow should not reach `report_selection_err` call")
-            }
-        };
-
-        self.note_obligation_cause(&mut err, &obligation);
-        self.point_at_returns_when_relevant(&mut err, &obligation);
-        err.emit();
-    }
-
-    fn report_const_param_not_wf(
-        &self,
-        ty: Ty<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let span = obligation.cause.span;
-
-        let mut diag = match ty.kind() {
-            _ if ty.has_param() => {
-                span_bug!(span, "const param tys cannot mention other generic parameters");
-            }
-            ty::Float(_) => {
-                struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0741,
-                    "`{ty}` is forbidden as the type of a const generic parameter",
-                )
-            }
-            ty::FnPtr(_) => {
-                struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0741,
-                    "using function pointers as const generic parameters is forbidden",
-                )
-            }
-            ty::RawPtr(_) => {
-                struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0741,
-                    "using raw pointers as const generic parameters is forbidden",
-                )
-            }
-            ty::Adt(def, _) => {
-                // We should probably see if we're *allowed* to derive `ConstParamTy` on the type...
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0741,
-                    "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
-                );
-                // Only suggest derive if this isn't a derived obligation,
-                // and the struct is local.
-                if let Some(span) = self.tcx.hir().span_if_local(def.did())
-                    && obligation.cause.code().parent().is_none()
-                {
-                    if ty.is_structural_eq_shallow(self.tcx) {
-                        diag.span_suggestion(
-                            span,
-                            "add `#[derive(ConstParamTy)]` to the struct",
-                            "#[derive(ConstParamTy)]\n",
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        // FIXME(adt_const_params): We should check there's not already an
-                        // overlapping `Eq`/`PartialEq` impl.
-                        diag.span_suggestion(
-                            span,
-                            "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct",
-                            "#[derive(ConstParamTy, PartialEq, Eq)]\n",
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                }
-                diag
-            }
-            _ => {
-                struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0741,
-                    "`{ty}` can't be used as a const parameter type",
-                )
-            }
-        };
-
-        let mut code = obligation.cause.code();
-        let mut pred = obligation.predicate.to_opt_poly_trait_pred();
-        while let Some((next_code, next_pred)) = code.parent() {
-            if let Some(pred) = pred {
-                let pred = self.instantiate_binder_with_placeholders(pred);
-                diag.note(format!(
-                    "`{}` must implement `{}`, but it does not",
-                    pred.self_ty(),
-                    pred.print_modifiers_and_trait_path()
-                ));
-            }
-            code = next_code;
-            pred = next_pred;
-        }
-
-        diag
-    }
-}
-
-trait InferCtxtPrivExt<'tcx> {
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
-
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>);
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    );
-
-    fn maybe_detailed_projection_msg(
-        &self,
-        pred: ty::ProjectionPredicate<'tcx>,
-        normalized_ty: ty::Term<'tcx>,
-        expected_ty: ty::Term<'tcx>,
-    ) -> Option<String>;
-
-    fn fuzzy_match_tys(
-        &self,
-        a: Ty<'tcx>,
-        b: Ty<'tcx>,
-        ignoring_lifetimes: bool,
-    ) -> Option<CandidateSimilarity>;
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> Vec<ImplCandidate<'tcx>>;
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: &[ImplCandidate<'tcx>],
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        body_def_id: LocalDefId,
-        err: &mut Diagnostic,
-        other: bool,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> bool;
-
-    fn report_similar_impl_candidates_for_root_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
-        body_def_id: LocalDefId,
-        err: &mut Diagnostic,
-    );
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)>;
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut Diagnostic,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) -> bool;
-
-    /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
-    /// `trait_ref`.
-    ///
-    /// For this to work, `new_self_ty` must have no escaping bound variables.
-    fn mk_trait_obligation_with_new_self_ty(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
-    ) -> PredicateObligation<'tcx>;
-
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>);
-
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
-
-    fn suggest_unsized_bound_if_applicable(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-    );
-
-    fn annotate_source_of_ambiguity(
-        &self,
-        err: &mut Diagnostic,
-        impls: &[ambiguity::Ambiguity],
-        predicate: ty::Predicate<'tcx>,
-    );
-
-    fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>);
-
-    fn maybe_indirection_for_unsized(
-        &self,
-        err: &mut Diagnostic,
-        item: &'tcx Item<'tcx>,
-        param: &'tcx GenericParam<'tcx>,
-    ) -> bool;
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<Ty<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool;
-
-    fn get_standard_error_message(
-        &self,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        message: Option<String>,
-        predicate_is_const: bool,
-        append_const_msg: Option<AppendConstMessage>,
-        post_message: String,
-    ) -> String;
-
-    fn get_safe_transmute_error_and_reason(
-        &self,
-        obligation: PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        span: Span,
-    ) -> GetSafeTransmuteErrorAndReason;
-
-    fn add_tuple_trait_message(
-        &self,
-        obligation_cause_code: &ObligationCauseCode<'tcx>,
-        err: &mut Diagnostic,
-    );
-
-    fn try_to_add_help_message(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        err: &mut Diagnostic,
-        span: Span,
-        is_fn_trait: bool,
-        suggested: bool,
-        unsatisfied_const: bool,
-    );
-
-    fn add_help_message_for_fn_trait(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        err: &mut Diagnostic,
-        implemented_kind: ty::ClosureKind,
-        params: ty::Binder<'tcx, Ty<'tcx>>,
-    );
-
-    fn maybe_add_note_for_unsatisfied_const(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        err: &mut Diagnostic,
-        span: Span,
-    ) -> UnsatisfiedConst;
-
-    fn report_closure_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        closure_def_id: DefId,
-        found_kind: ty::ClosureKind,
-        kind: ty::ClosureKind,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
-
-    fn report_type_parameter_mismatch_cyclic_type_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        terr: TypeError<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
-
-    fn report_opaque_type_auto_trait_leakage(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        def_id: DefId,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
-
-    fn report_type_parameter_mismatch_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        span: Span,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
-
-    fn report_not_const_evaluatable_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        span: Span,
-    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
-}
-
-impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        // FIXME: It should be possible to deal with `ForAll` in a cleaner way.
-        let bound_error = error.kind();
-        let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) {
-            (
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)),
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)),
-            ) => (cond, bound_error.rebind(error)),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for pred in super::elaborate(self.tcx, std::iter::once(cond)) {
-            let bound_predicate = pred.kind();
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) =
-                bound_predicate.skip_binder()
-            {
-                let error = error.to_poly_trait_ref();
-                let implication = bound_predicate.rebind(implication.trait_ref);
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication) {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    #[instrument(skip(self), level = "debug")]
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
-        if self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError {
-            dump_proof_tree(&error.root_obligation, self.infcx);
-        }
-
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    error.obligation.clone(),
-                    &error.root_obligation,
-                    selection_error,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
-                self.maybe_report_ambiguity(&error.obligation);
-            }
-            FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
-                self.report_overflow_no_abort(error.obligation.clone());
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    *err,
-                )
-                .emit();
-            }
-            FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => {
-                let mut diag = self.report_mismatched_consts(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    *err,
-                );
-                let code = error.obligation.cause.code().peel_derives().peel_match_impls();
-                if let ObligationCauseCode::BindingObligation(..)
-                | ObligationCauseCode::ItemObligation(..)
-                | ObligationCauseCode::ExprBindingObligation(..)
-                | ObligationCauseCode::ExprItemObligation(..) = code
-                {
-                    self.note_obligation_cause_code(
-                        error.obligation.cause.body_id,
-                        &mut diag,
-                        error.obligation.predicate,
-                        error.obligation.param_env,
-                        code,
-                        &mut vec![],
-                        &mut Default::default(),
-                    );
-                }
-                diag.emit();
-            }
-            FulfillmentErrorCode::CodeCycle(ref cycle) => {
-                self.report_overflow_obligation_cycle(cycle);
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip_all)]
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let ocx = ObligationCtxt::new(self);
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            let bound_predicate = predicate.kind();
-            let (values, err) = if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) =
-                bound_predicate.skip_binder()
-            {
-                let data = self.instantiate_binder_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    bound_predicate.rebind(data),
-                );
-                let unnormalized_term = match data.term.unpack() {
-                    ty::TermKind::Ty(_) => Ty::new_projection(
-                        self.tcx,
-                        data.projection_ty.def_id,
-                        data.projection_ty.args,
-                    )
-                    .into(),
-                    ty::TermKind::Const(ct) => ty::Const::new_unevaluated(
-                        self.tcx,
-                        ty::UnevaluatedConst {
-                            def: data.projection_ty.def_id,
-                            args: data.projection_ty.args,
-                        },
-                        ct.ty(),
-                    )
-                    .into(),
-                };
-                // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice
-                // to deeply normalize this type.
-                let normalized_term =
-                    ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
-
-                debug!(?obligation.cause, ?obligation.param_env);
-
-                debug!(?normalized_term, data.ty = ?data.term);
-
-                let is_normalized_term_expected = !matches!(
-                    obligation.cause.code().peel_derives(),
-                    ObligationCauseCode::ItemObligation(_)
-                        | ObligationCauseCode::BindingObligation(_, _)
-                        | ObligationCauseCode::ExprItemObligation(..)
-                        | ObligationCauseCode::ExprBindingObligation(..)
-                        | ObligationCauseCode::Coercion { .. }
-                        | ObligationCauseCode::OpaqueType
-                );
-
-                // constrain inference variables a bit more to nested obligations from normalize so
-                // we can have more helpful errors.
-                //
-                // we intentionally drop errors from normalization here,
-                // since the normalization is just done to improve the error message.
-                let _ = ocx.select_where_possible();
-
-                if let Err(new_err) = ocx.eq_exp(
-                    &obligation.cause,
-                    obligation.param_env,
-                    is_normalized_term_expected,
-                    normalized_term,
-                    data.term,
-                ) {
-                    (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
-                } else {
-                    (None, error.err)
-                }
-            } else {
-                (None, error.err)
-            };
-
-            let msg = values
-                .and_then(|(predicate, _, normalized_term, expected_term)| {
-                    self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
-                })
-                .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 = (|| {
-                let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
-                    predicate.kind().skip_binder()
-                else {
-                    return None;
-                };
-
-                let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
-                let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
-
-                let mut associated_items = vec![];
-                self.tcx.for_each_relevant_impl(
-                    self.tcx.trait_of_item(proj.projection_ty.def_id)?,
-                    proj.projection_ty.self_ty(),
-                    |impl_def_id| {
-                        associated_items.extend(
-                            self.tcx
-                                .associated_items(impl_def_id)
-                                .in_definition_order()
-                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
-                        );
-                    },
-                );
-
-                let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
-                    return None;
-                };
-                match self.tcx.hir().get_if_local(associated_item.def_id) {
-                    Some(
-                        hir::Node::TraitItem(hir::TraitItem {
-                            kind: hir::TraitItemKind::Type(_, Some(ty)),
-                            ..
-                        })
-                        | hir::Node::ImplItem(hir::ImplItem {
-                            kind: hir::ImplItemKind::Type(ty),
-                            ..
-                        }),
-                    ) => Some((
-                        ty.span,
-                        with_forced_trimmed_paths!(Cow::from(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,
-                }
-            })();
-
-            self.note_type_err(
-                &mut diag,
-                &obligation.cause,
-                secondary_span,
-                values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| {
-                    infer::ValuePairs::Terms(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        expected_ty,
-                    ))
-                }),
-                err,
-                true,
-                false,
-            );
-            self.note_obligation_cause(&mut diag, obligation);
-            diag.emit();
-        });
-    }
-
-    fn maybe_detailed_projection_msg(
-        &self,
-        pred: ty::ProjectionPredicate<'tcx>,
-        normalized_ty: ty::Term<'tcx>,
-        expected_ty: ty::Term<'tcx>,
-    ) -> Option<String> {
-        let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
-        let self_ty = pred.projection_ty.self_ty();
-
-        with_forced_trimmed_paths! {
-            if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
-                let fn_kind = self_ty.prefix_string(self.tcx);
-                let item = match self_ty.kind() {
-                    ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
-                    _ => self_ty.to_string(),
-                };
-                Some(format!(
-                    "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
-                     returns `{normalized_ty}`",
-                ))
-            } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
-                Some(format!(
-                    "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
-                     resolves to `{normalized_ty}`"
-                ))
-            } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
-                Some(format!(
-                    "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
-                     yields `{normalized_ty}`"
-                ))
-            } else {
-                None
-            }
-        }
-    }
-
-    fn fuzzy_match_tys(
-        &self,
-        mut a: Ty<'tcx>,
-        mut b: Ty<'tcx>,
-        ignoring_lifetimes: bool,
-    ) -> Option<CandidateSimilarity> {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
-            match t.kind() {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => Some(2),
-                ty::Int(..)
-                | ty::Uint(..)
-                | ty::Float(..)
-                | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Param(..) => Some(11),
-                ty::Alias(ty::Projection, ..) => Some(12),
-                ty::Alias(ty::Inherent, ..) => Some(13),
-                ty::Alias(ty::Opaque, ..) => Some(14),
-                ty::Alias(ty::Weak, ..) => Some(15),
-                ty::Never => Some(16),
-                ty::Adt(..) => Some(17),
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
-            }
-        }
-
-        let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> {
-            loop {
-                match t.kind() {
-                    ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => {
-                        t = *inner
-                    }
-                    _ => break t,
-                }
-            }
-        };
-
-        if !ignoring_lifetimes {
-            a = strip_references(a);
-            b = strip_references(b);
-        }
-
-        let cat_a = type_category(self.tcx, a)?;
-        let cat_b = type_category(self.tcx, b)?;
-        if a == b {
-            Some(CandidateSimilarity::Exact { ignoring_lifetimes })
-        } else if cat_a == cat_b {
-            match (a.kind(), b.kind()) {
-                (ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,
-                (ty::Foreign(def_a), ty::Foreign(def_b)) => def_a == def_b,
-                // Matching on references results in a lot of unhelpful
-                // suggestions, so let's just not do that for now.
-                //
-                // We still upgrade successful matches to `ignoring_lifetimes: true`
-                // to prioritize that impl.
-                (ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => {
-                    self.fuzzy_match_tys(a, b, true).is_some()
-                }
-                _ => true,
-            }
-            .then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes })
-        } else if ignoring_lifetimes {
-            None
-        } else {
-            self.fuzzy_match_tys(a, b, true)
-        }
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> Vec<ImplCandidate<'tcx>> {
-        let mut candidates: Vec<_> = self
-            .tcx
-            .all_impls(trait_pred.def_id())
-            .filter_map(|def_id| {
-                if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
-                    || !self.tcx.is_user_visible_dep(def_id.krate)
-                {
-                    return None;
-                }
-
-                let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();
-
-                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
-                    |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
-                )
-            })
-            .collect();
-        if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
-            // If any of the candidates is a perfect match, we don't want to show all of them.
-            // This is particularly relevant for the case of numeric types (as they all have the
-            // same category).
-            candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
-        }
-        candidates
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: &[ImplCandidate<'tcx>],
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        body_def_id: LocalDefId,
-        err: &mut Diagnostic,
-        other: bool,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> bool {
-        // If we have a single implementation, try to unify it with the trait ref
-        // that failed. This should uncover a better hint for what *is* implemented.
-        if let [single] = &impl_candidates {
-            if self.probe(|_| {
-                let ocx = ObligationCtxt::new(self);
-                let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
-                let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
-                let impl_trait_ref = ocx.normalize(
-                    &ObligationCause::dummy(),
-                    param_env,
-                    ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
-                );
-
-                ocx.register_obligations(
-                    self.tcx
-                        .predicates_of(single.impl_def_id)
-                        .instantiate(self.tcx, impl_args)
-                        .into_iter()
-                        .map(|(clause, _)| {
-                            Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
-                        }),
-                );
-                if !ocx.select_where_possible().is_empty() {
-                    return false;
-                }
-
-                let mut terrs = vec![];
-                for (obligation_arg, impl_arg) in
-                    std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
-                {
-                    if let Err(terr) =
-                        ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
-                    {
-                        terrs.push(terr);
-                    }
-                    if !ocx.select_where_possible().is_empty() {
-                        return false;
-                    }
-                }
-
-                // Literally nothing unified, just give up.
-                if terrs.len() == impl_trait_ref.args.len() {
-                    return false;
-                }
-
-                let cand =
-                    self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
-                        tcx: self.tcx,
-                        ty_op: |ty| ty,
-                        lt_op: |lt| lt,
-                        ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
-                    });
-                err.highlighted_help(vec![
-                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
-                    ("is".to_string(), Style::Highlight),
-                    (" implemented for `".to_string(), Style::NoStyle),
-                    (cand.self_ty().to_string(), Style::Highlight),
-                    ("`".to_string(), Style::NoStyle),
-                ]);
-
-                if let [TypeError::Sorts(exp_found)] = &terrs[..] {
-                    let exp_found = self.resolve_vars_if_possible(*exp_found);
-                    err.help(format!(
-                        "for that trait implementation, expected `{}`, found `{}`",
-                        exp_found.expected, exp_found.found
-                    ));
-                }
-
-                true
-            }) {
-                return true;
-            }
-        }
-
-        let other = if other { "other " } else { "" };
-        let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
-            if candidates.is_empty() {
-                return false;
-            }
-            if let &[cand] = &candidates[..] {
-                let (desc, mention_castable) =
-                    match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
-                        (ty::FnPtr(_), ty::FnDef(..)) => {
-                            (" implemented for fn pointer `", ", cast using `as`")
-                        }
-                        (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""),
-                        _ => (" implemented for `", ""),
-                    };
-                err.highlighted_help(vec![
-                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
-                    ("is".to_string(), Style::Highlight),
-                    (desc.to_string(), Style::NoStyle),
-                    (cand.self_ty().to_string(), Style::Highlight),
-                    ("`".to_string(), Style::NoStyle),
-                    (mention_castable.to_string(), Style::NoStyle),
-                ]);
-                return true;
-            }
-            let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id);
-            // Check if the trait is the same in all cases. If so, we'll only show the type.
-            let mut traits: Vec<_> =
-                candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
-            traits.sort();
-            traits.dedup();
-            // FIXME: this could use a better heuristic, like just checking
-            // that args[1..] is the same.
-            let all_traits_equal = traits.len() == 1;
-
-            let candidates: Vec<String> = candidates
-                .into_iter()
-                .map(|c| {
-                    if all_traits_equal {
-                        format!("\n  {}", c.self_ty())
-                    } else {
-                        format!("\n  {c}")
-                    }
-                })
-                .collect();
-
-            let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
-            err.help(format!(
-                "the following {other}types implement trait `{}`:{}{}",
-                trait_ref.print_only_trait_path(),
-                candidates[..end].join(""),
-                if candidates.len() > 9 {
-                    format!("\nand {} others", candidates.len() - 8)
-                } else {
-                    String::new()
-                }
-            ));
-            true
-        };
-
-        let def_id = trait_ref.def_id();
-        if impl_candidates.is_empty() {
-            if self.tcx.trait_is_auto(def_id)
-                || self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
-                || self.tcx.get_diagnostic_name(def_id).is_some()
-            {
-                // Mentioning implementers of `Copy`, `Debug` and friends is not useful.
-                return false;
-            }
-            let mut impl_candidates: Vec<_> = self
-                .tcx
-                .all_impls(def_id)
-                // Ignore automatically derived impls and `!Trait` impls.
-                .filter(|&def_id| {
-                    self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
-                        || self.tcx.is_automatically_derived(def_id)
-                })
-                .filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
-                .map(ty::EarlyBinder::instantiate_identity)
-                .filter(|trait_ref| {
-                    let self_ty = trait_ref.self_ty();
-                    // Avoid mentioning type parameters.
-                    if let ty::Param(_) = self_ty.kind() {
-                        false
-                    }
-                    // Avoid mentioning types that are private to another crate
-                    else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
-                        // FIXME(compiler-errors): This could be generalized, both to
-                        // be more granular, and probably look past other `#[fundamental]`
-                        // types, too.
-                        self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
-                    } else {
-                        true
-                    }
-                })
-                .collect();
-
-            impl_candidates.sort();
-            impl_candidates.dedup();
-            return report(impl_candidates, err);
-        }
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        //
-        // Prefer more similar candidates first, then sort lexicographically
-        // by their normalized string representation.
-        let mut impl_candidates: Vec<_> = impl_candidates
-            .iter()
-            .cloned()
-            .map(|mut cand| {
-                // Fold the consts so that they shows up as, e.g., `10`
-                // instead of `core::::array::{impl#30}::{constant#0}`.
-                cand.trait_ref = cand.trait_ref.fold_with(&mut BottomUpFolder {
-                    tcx: self.tcx,
-                    ty_op: |ty| ty,
-                    lt_op: |lt| lt,
-                    ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
-                });
-                cand
-            })
-            .collect();
-        impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
-        let mut impl_candidates: Vec<_> =
-            impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
-        impl_candidates.dedup();
-
-        report(impl_candidates, err)
-    }
-
-    fn report_similar_impl_candidates_for_root_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
-        body_def_id: LocalDefId,
-        err: &mut Diagnostic,
-    ) {
-        // This is *almost* equivalent to
-        // `obligation.cause.code().peel_derives()`, but it gives us the
-        // trait predicate for that corresponding root obligation. This
-        // lets us get a derived obligation from a type parameter, like
-        // when calling `string.strip_suffix(p)` where `p` is *not* an
-        // implementer of `Pattern<'_>`.
-        let mut code = obligation.cause.code();
-        let mut trait_pred = trait_predicate;
-        let mut peeled = false;
-        while let Some((parent_code, parent_trait_pred)) = code.parent() {
-            code = parent_code;
-            if let Some(parent_trait_pred) = parent_trait_pred {
-                trait_pred = parent_trait_pred;
-                peeled = true;
-            }
-        }
-        let def_id = trait_pred.def_id();
-        // Mention *all* the `impl`s for the *top most* obligation, the
-        // user might have meant to use one of them, if any found. We skip
-        // auto-traits or fundamental traits that might not be exactly what
-        // the user might expect to be presented with. Instead this is
-        // useful for less general traits.
-        if peeled
-            && !self.tcx.trait_is_auto(def_id)
-            && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
-        {
-            let trait_ref = trait_pred.to_poly_trait_ref();
-            let impl_candidates = self.find_similar_impl_candidates(trait_pred);
-            self.report_similar_impl_candidates(
-                &impl_candidates,
-                trait_ref,
-                body_def_id,
-                err,
-                true,
-                obligation.param_env,
-            );
-        }
-    }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)> {
-        match code {
-            ObligationCauseCode::BuiltinDerivedObligation(data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => {
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        let span = TyCategory::from_ty(self.tcx, ty)
-                            .map(|(_, def_id)| self.tcx.def_span(def_id));
-                        Some((ty.to_string(), span))
-                    }
-                }
-            }
-            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
-                self.get_parent_trait_ref(&parent_code)
-            }
-            _ => None,
-        }
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut Diagnostic,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        let get_trait_impls = |trait_def_id| {
-            let mut trait_impls = vec![];
-            self.tcx.for_each_relevant_impl(
-                trait_def_id,
-                trait_ref.skip_binder().self_ty(),
-                |impl_def_id| {
-                    trait_impls.push(impl_def_id);
-                },
-            );
-            trait_impls
-        };
-
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let traits_with_same_path: std::collections::BTreeSet<_> = self
-            .tcx
-            .all_traits()
-            .filter(|trait_def_id| *trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path)
-            .collect();
-        let mut suggested = false;
-        for trait_with_same_path in traits_with_same_path {
-            let trait_impls = get_trait_impls(trait_with_same_path);
-            if trait_impls.is_empty() {
-                continue;
-            }
-            let impl_spans: Vec<_> =
-                trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
-            err.span_help(
-                impl_spans,
-                format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
-            );
-            let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-            let crate_msg =
-                format!("perhaps two different versions of crate `{trait_crate}` are being used?");
-            err.note(crate_msg);
-            suggested = true;
-        }
-        suggested
-    }
-
-    fn mk_trait_obligation_with_new_self_ty(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
-    ) -> PredicateObligation<'tcx> {
-        let trait_pred =
-            trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty));
-
-        Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
-    }
-
-    #[instrument(skip(self), level = "debug")]
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
-
-        // Ambiguity errors are often caused as fallout from earlier errors.
-        // We ignore them if this `infcx` is tainted in some cases below.
-
-        let bound_predicate = predicate.kind();
-        let mut err = match bound_predicate.skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
-                let trait_ref = bound_predicate.rebind(data.trait_ref);
-                debug!(?trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized". It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and don't add the obligations to
-                // begin with in those cases.
-                if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
-                    if let None = self.tainted_by_errors() {
-                        self.emit_inference_failure_err(
-                            obligation.cause.body_id,
-                            span,
-                            trait_ref.self_ty().skip_binder().into(),
-                            ErrorCode::E0282,
-                            false,
-                        )
-                        .emit();
-                    }
-                    return;
-                }
-
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // Pick the first substitution that still contains inference variables as the one
-                // we're going to emit an error for. If there are none (see above), fall back to
-                // a more general error.
-                let subst = data.trait_ref.args.iter().find(|s| s.has_non_region_infer());
-
-                let mut err = if let Some(subst) = subst {
-                    self.emit_inference_failure_err(
-                        obligation.cause.body_id,
-                        span,
-                        subst,
-                        ErrorCode::E0283,
-                        true,
-                    )
-                } else {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0283,
-                        "type annotations needed: cannot satisfy `{}`",
-                        predicate,
-                    )
-                };
-
-                let ambiguities = ambiguity::recompute_applicable_impls(
-                    self.infcx,
-                    &obligation.with(self.tcx, trait_ref),
-                );
-                let has_non_region_infer =
-                    trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
-                // It doesn't make sense to talk about applicable impls if there are more
-                // than a handful of them.
-                if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
-                    if self.tainted_by_errors().is_some() && subst.is_none() {
-                        // If `subst.is_none()`, then this is probably two param-env
-                        // candidates or impl candidates that are equal modulo lifetimes.
-                        // Therefore, if we've already emitted an error, just skip this
-                        // one, since it's not particularly actionable.
-                        err.cancel();
-                        return;
-                    }
-                    self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
-                } else {
-                    if self.tainted_by_errors().is_some() {
-                        err.cancel();
-                        return;
-                    }
-                    err.note(format!("cannot satisfy `{predicate}`"));
-                    let impl_candidates = self
-                        .find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
-                    if impl_candidates.len() < 10 {
-                        self.report_similar_impl_candidates(
-                            impl_candidates.as_slice(),
-                            trait_ref,
-                            obligation.cause.body_id,
-                            &mut err,
-                            false,
-                            obligation.param_env,
-                        );
-                    }
-                }
-
-                if let ObligationCauseCode::ItemObligation(def_id)
-                | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
-                {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                }
-
-                if let Some(ty::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
-                    && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
-                {
-                    let mut expr_finder = FindExprBySpan::new(span);
-                    expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
-
-                    if let Some(hir::Expr {
-                        kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. }
-                    ) = expr_finder.result
-                        && let [
-                            ..,
-                            trait_path_segment @ hir::PathSegment {
-                                res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
-                                ..
-                            },
-                            hir::PathSegment {
-                                ident: assoc_item_name,
-                                res: rustc_hir::def::Res::Def(_, item_id),
-                                ..
-                            }
-                        ] = path.segments
-                        && data.trait_ref.def_id == *trait_id
-                        && self.tcx.trait_of_item(*item_id) == Some(*trait_id)
-                        && let None = self.tainted_by_errors()
-                    {
-                        let (verb, noun) = match self.tcx.associated_item(item_id).kind {
-                            ty::AssocKind::Const => ("refer to the", "constant"),
-                            ty::AssocKind::Fn => ("call", "function"),
-                            ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
-                        };
-
-                        // Replace the more general E0283 with a more specific error
-                        err.cancel();
-                        err = self.tcx.sess.struct_span_err_with_code(
-                            span,
-                            format!(
-                                "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
-                            ),
-                            rustc_errors::error_code!(E0790),
-                        );
-
-                        if let Some(local_def_id) = data.trait_ref.def_id.as_local()
-                            && let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
-                            && let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
-                            err.span_label(method_ref.span, format!("`{trait_name}::{assoc_item_name}` defined here"));
-                        }
-
-                        err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
-
-                        let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
-
-                        if trait_impls.blanket_impls().is_empty()
-                            && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
-                        {
-                            let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
-                            // If there is only one implementation of the trait, suggest using it.
-                            // Otherwise, use a placeholder comment for the implementation.
-                            let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
-                                "use the fully-qualified path to the only available implementation",
-                                format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
-                            )} else {
-                                ("use a fully-qualified path to a specific available implementation",
-                                                                "</* self type */ as ".to_string()
-                            )};
-                            let mut suggestions = vec![(
-                                path.span.shrink_to_lo(),
-                                impl_suggestion
-                            )];
-                            if let Some(generic_arg) = trait_path_segment.args {
-                                let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
-                                // get rid of :: between Trait and <type>
-                                // must be '::' between them, otherwise the parser won't accept the code
-                                suggestions.push((between_span, "".to_string(),));
-                                suggestions.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
-                            } else {
-                                suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), ">".to_string()));
-                            }
-                            err.multipart_suggestion(
-                                message,
-                                suggestions,
-                                Applicability::MaybeIncorrect
-                            );
-                        }
-                    }
-                };
-
-                err
-            }
-
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if arg.references_error()
-                    || self.tcx.sess.has_errors().is_some()
-                    || self.tainted_by_errors().is_some()
-                {
-                    return;
-                }
-
-                self.emit_inference_failure_err(
-                    obligation.cause.body_id,
-                    span,
-                    arg,
-                    ErrorCode::E0282,
-                    false,
-                )
-            }
-
-            ty::PredicateKind::Subtype(data) => {
-                if data.references_error()
-                    || self.tcx.sess.has_errors().is_some()
-                    || self.tainted_by_errors().is_some()
-                {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let SubtypePredicate { a_is_expected: _, a, b } = data;
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.emit_inference_failure_err(
-                    obligation.cause.body_id,
-                    span,
-                    a.into(),
-                    ErrorCode::E0282,
-                    true,
-                )
-            }
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
-                if predicate.references_error() || self.tainted_by_errors().is_some() {
-                    return;
-                }
-                let subst = data
-                    .projection_ty
-                    .args
-                    .iter()
-                    .chain(Some(data.term.into_arg()))
-                    .find(|g| g.has_non_region_infer());
-                if let Some(subst) = subst {
-                    let mut err = self.emit_inference_failure_err(
-                        obligation.cause.body_id,
-                        span,
-                        subst,
-                        ErrorCode::E0284,
-                        true,
-                    );
-                    err.note(format!("cannot satisfy `{predicate}`"));
-                    err
-                } else {
-                    // If we can't find a substitution, just print a generic error
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0284,
-                        "type annotations needed: cannot satisfy `{}`",
-                        predicate,
-                    );
-                    err.span_label(span, format!("cannot satisfy `{predicate}`"));
-                    err
-                }
-            }
-
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
-                if predicate.references_error() || self.tainted_by_errors().is_some() {
-                    return;
-                }
-                let subst = data.walk().find(|g| g.is_non_region_infer());
-                if let Some(subst) = subst {
-                    let err = self.emit_inference_failure_err(
-                        obligation.cause.body_id,
-                        span,
-                        subst,
-                        ErrorCode::E0284,
-                        true,
-                    );
-                    err
-                } else {
-                    // If we can't find a substitution, just print a generic error
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0284,
-                        "type annotations needed: cannot satisfy `{}`",
-                        predicate,
-                    );
-                    err.span_label(span, format!("cannot satisfy `{predicate}`"));
-                    err
-                }
-            }
-            _ => {
-                if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot satisfy `{}`",
-                    predicate,
-                );
-                err.span_label(span, format!("cannot satisfy `{predicate}`"));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    fn annotate_source_of_ambiguity(
-        &self,
-        err: &mut Diagnostic,
-        ambiguities: &[ambiguity::Ambiguity],
-        predicate: ty::Predicate<'tcx>,
-    ) {
-        let mut spans = vec![];
-        let mut crates = vec![];
-        let mut post = vec![];
-        let mut has_param_env = false;
-        for ambiguity in ambiguities {
-            match ambiguity {
-                ambiguity::Ambiguity::DefId(impl_def_id) => {
-                    match self.tcx.span_of_impl(*impl_def_id) {
-                        Ok(span) => spans.push(span),
-                        Err(name) => {
-                            crates.push(name);
-                            if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
-                                post.push(header);
-                            }
-                        }
-                    }
-                }
-                ambiguity::Ambiguity::ParamEnv(span) => {
-                    has_param_env = true;
-                    spans.push(*span);
-                }
-            }
-        }
-        let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{n}`")).collect();
-        crate_names.sort();
-        crate_names.dedup();
-        post.sort();
-        post.dedup();
-
-        if self.tainted_by_errors().is_some()
-            && (crate_names.len() == 1
-                && spans.len() == 0
-                && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
-                || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
-        {
-            // Avoid complaining about other inference issues for expressions like
-            // `42 >> 1`, where the types are still `{integer}`, but we want to
-            // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too?
-            // NOTE(eddyb) this was `.cancel()`, but `err`
-            // is borrowed, so we can't fully defuse it.
-            err.downgrade_to_delayed_bug();
-            return;
-        }
-
-        let msg = format!(
-            "multiple `impl`s{} satisfying `{}` found",
-            if has_param_env { " or `where` clauses" } else { "" },
-            predicate
-        );
-        let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
-            format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::<Vec<_>>().join("\n"),)
-        } else if post.len() == 1 {
-            format!(": `{}`", post[0])
-        } else {
-            String::new()
-        };
-
-        match (spans.len(), crates.len(), crate_names.len()) {
-            (0, 0, 0) => {
-                err.note(format!("cannot satisfy `{predicate}`"));
-            }
-            (0, _, 1) => {
-                err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,));
-            }
-            (0, _, _) => {
-                err.note(format!(
-                    "{} in the following crates: {}{}",
-                    msg,
-                    crate_names.join(", "),
-                    post,
-                ));
-            }
-            (_, 0, 0) => {
-                let span: MultiSpan = spans.into();
-                err.span_note(span, msg);
-            }
-            (_, 1, 1) => {
-                let span: MultiSpan = spans.into();
-                err.span_note(span, msg);
-                err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,));
-            }
-            _ => {
-                let span: MultiSpan = spans.into();
-                err.span_note(span, msg);
-                err.note(format!(
-                    "and more `impl`s found in the following crates: {}{}",
-                    crate_names.join(", "),
-                    post,
-                ));
-            }
-        }
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ParamToVarFolder<'a, 'tcx> {
-            fn interner(&self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(_) = *ty.kind() {
-                    let infcx = self.infcx;
-                    *self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let InferOk { value: cleaned_pred, .. } =
-                self.infcx.at(&ObligationCause::dummy(), param_env).normalize(cleaned_pred);
-
-            let obligation =
-                Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>) {
-        // First, attempt to add note to this error with an async-await-specific
-        // message, and fall back to regular note otherwise.
-        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                obligation.cause.body_id,
-                err,
-                obligation.predicate,
-                obligation.param_env,
-                obligation.cause.code(),
-                &mut vec![],
-                &mut Default::default(),
-            );
-            self.suggest_unsized_bound_if_applicable(err, obligation);
-        }
-    }
-
-    #[instrument(level = "debug", skip_all)]
-    fn suggest_unsized_bound_if_applicable(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
-            obligation.predicate.kind().skip_binder()
-        else {
-            return;
-        };
-        let (ObligationCauseCode::BindingObligation(item_def_id, span)
-        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) =
-            *obligation.cause.code().peel_derives()
-        else {
-            return;
-        };
-        debug!(?pred, ?item_def_id, ?span);
-
-        let (Some(node), true) = (
-            self.tcx.hir().get_if_local(item_def_id),
-            Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
-        ) else {
-            return;
-        };
-        self.maybe_suggest_unsized_generics(err, span, node);
-    }
-
-    #[instrument(level = "debug", skip_all)]
-    fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>) {
-        let Some(generics) = node.generics() else {
-            return;
-        };
-        let sized_trait = self.tcx.lang_items().sized_trait();
-        debug!(?generics.params);
-        debug!(?generics.predicates);
-        let Some(param) = generics.params.iter().find(|param| param.span == span) else {
-            return;
-        };
-        // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
-        // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
-        let explicitly_sized = generics
-            .bounds_for_param(param.def_id)
-            .flat_map(|bp| bp.bounds)
-            .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
-        if explicitly_sized {
-            return;
-        }
-        debug!(?param);
-        match node {
-            hir::Node::Item(
-                item @ hir::Item {
-                    // Only suggest indirection for uses of type parameters in ADTs.
-                    kind:
-                        hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
-                    ..
-                },
-            ) => {
-                if self.maybe_indirection_for_unsized(err, item, param) {
-                    return;
-                }
-            }
-            _ => {}
-        };
-        // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
-        let (span, separator) = if let Some(s) = generics.bounds_span_for_suggestions(param.def_id)
-        {
-            (s, " +")
-        } else {
-            (span.shrink_to_hi(), ":")
-        };
-        err.span_suggestion_verbose(
-            span,
-            "consider relaxing the implicit `Sized` restriction",
-            format!("{separator} ?Sized"),
-            Applicability::MachineApplicable,
-        );
-    }
-
-    fn maybe_indirection_for_unsized(
-        &self,
-        err: &mut Diagnostic,
-        item: &Item<'tcx>,
-        param: &GenericParam<'tcx>,
-    ) -> bool {
-        // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
-        // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
-        // is not. Look for invalid "bare" parameter uses, and suggest using indirection.
-        let mut visitor =
-            FindTypeParam { param: param.name.ident().name, invalid_spans: vec![], nested: false };
-        visitor.visit_item(item);
-        if visitor.invalid_spans.is_empty() {
-            return false;
-        }
-        let mut multispan: MultiSpan = param.span.into();
-        multispan.push_span_label(
-            param.span,
-            format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
-        );
-        for sp in visitor.invalid_spans {
-            multispan.push_span_label(
-                sp,
-                format!("...if indirection were used here: `Box<{}>`", param.name.ident()),
-            );
-        }
-        err.span_help(
-            multispan,
-            format!(
-                "you could relax the implicit `Sized` bound on `{T}` if it were \
-                used through indirection like `&{T}` or `Box<{T}>`",
-                T = param.name.ident(),
-            ),
-        );
-        true
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<Ty<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
-            let self_ty = parent_trait_ref.skip_binder().self_ty();
-            if obligated_types.iter().any(|ot| ot == &self_ty) {
-                return true;
-            }
-            if let ty::Adt(def, args) = self_ty.kind()
-                && let [arg] = &args[..]
-                && let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Adt(inner_def, _) = ty.kind()
-                && inner_def == def
-            {
-                return true;
-            }
-        }
-        false
-    }
-
-    fn get_standard_error_message(
-        &self,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        message: Option<String>,
-        predicate_is_const: bool,
-        append_const_msg: Option<AppendConstMessage>,
-        post_message: String,
-    ) -> String {
-        message
-            .and_then(|cannot_do_this| {
-                match (predicate_is_const, append_const_msg) {
-                    // do nothing if predicate is not const
-                    (false, _) => Some(cannot_do_this),
-                    // suggested using default post message
-                    (true, Some(AppendConstMessage::Default)) => {
-                        Some(format!("{cannot_do_this} in const contexts"))
-                    }
-                    // overridden post message
-                    (true, Some(AppendConstMessage::Custom(custom_msg))) => {
-                        Some(format!("{cannot_do_this}{custom_msg}"))
-                    }
-                    // fallback to generic message
-                    (true, None) => None,
-                }
-            })
-            .unwrap_or_else(|| {
-                format!("the trait bound `{trait_predicate}` is not satisfied{post_message}")
-            })
-    }
-
-    fn get_safe_transmute_error_and_reason(
-        &self,
-        obligation: PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        span: Span,
-    ) -> GetSafeTransmuteErrorAndReason {
-        use rustc_transmute::Answer;
-
-        // Erase regions because layout code doesn't particularly care about regions.
-        let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
-
-        let src_and_dst = rustc_transmute::Types {
-            dst: trait_ref.args.type_at(0),
-            src: trait_ref.args.type_at(1),
-        };
-        let scope = trait_ref.args.type_at(2);
-        let Some(assume) = rustc_transmute::Assume::from_const(
-            self.infcx.tcx,
-            obligation.param_env,
-            trait_ref.args.const_at(3),
-        ) else {
-            span_bug!(
-                span,
-                "Unable to construct rustc_transmute::Assume where it was previously possible"
-            );
-        };
-
-        match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
-            obligation.cause,
-            src_and_dst,
-            scope,
-            assume,
-        ) {
-            Answer::No(reason) => {
-                let dst = trait_ref.args.type_at(0);
-                let src = trait_ref.args.type_at(1);
-                let err_msg = format!(
-                    "`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
-                );
-                let safe_transmute_explanation = match reason {
-                    rustc_transmute::Reason::SrcIsUnspecified => {
-                        format!("`{src}` does not have a well-specified layout")
-                    }
-
-                    rustc_transmute::Reason::DstIsUnspecified => {
-                        format!("`{dst}` does not have a well-specified layout")
-                    }
-
-                    rustc_transmute::Reason::DstIsBitIncompatible => {
-                        format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`")
-                    }
-
-                    rustc_transmute::Reason::DstIsPrivate => format!(
-                        "`{dst}` is or contains a type or field that is not visible in that scope"
-                    ),
-                    rustc_transmute::Reason::DstIsTooBig => {
-                        format!("The size of `{src}` is smaller than the size of `{dst}`")
-                    }
-                    rustc_transmute::Reason::SrcSizeOverflow => {
-                        format!(
-                            "values of the type `{src}` are too big for the current architecture"
-                        )
-                    }
-                    rustc_transmute::Reason::DstSizeOverflow => {
-                        format!(
-                            "values of the type `{dst}` are too big for the current architecture"
-                        )
-                    }
-                    rustc_transmute::Reason::DstHasStricterAlignment {
-                        src_min_align,
-                        dst_min_align,
-                    } => {
-                        format!(
-                            "The minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})"
-                        )
-                    }
-                    rustc_transmute::Reason::DstIsMoreUnique => {
-                        format!("`{src}` is a shared reference, but `{dst}` is a unique reference")
-                    }
-                    // Already reported by rustc
-                    rustc_transmute::Reason::TypeError => {
-                        return GetSafeTransmuteErrorAndReason::Silent;
-                    }
-                    rustc_transmute::Reason::SrcLayoutUnknown => {
-                        format!("`{src}` has an unknown layout")
-                    }
-                    rustc_transmute::Reason::DstLayoutUnknown => {
-                        format!("`{dst}` has an unknown layout")
-                    }
-                };
-                GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation }
-            }
-            // Should never get a Yes at this point! We already ran it before, and did not get a Yes.
-            Answer::Yes => span_bug!(
-                span,
-                "Inconsistent rustc_transmute::is_transmutable(...) result, got Yes",
-            ),
-            other => span_bug!(span, "Unsupported rustc_transmute::Answer variant: `{other:?}`"),
-        }
-    }
-
-    fn add_tuple_trait_message(
-        &self,
-        obligation_cause_code: &ObligationCauseCode<'tcx>,
-        err: &mut Diagnostic,
-    ) {
-        match obligation_cause_code {
-            ObligationCauseCode::RustCall => {
-                err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
-            }
-            ObligationCauseCode::BindingObligation(def_id, _)
-            | ObligationCauseCode::ItemObligation(def_id)
-                if self.tcx.is_fn_trait(*def_id) =>
-            {
-                err.code(rustc_errors::error_code!(E0059));
-                err.set_primary_message(format!(
-                    "type parameter to bare `{}` trait must be a tuple",
-                    self.tcx.def_path_str(*def_id)
-                ));
-            }
-            _ => {}
-        }
-    }
-
-    fn try_to_add_help_message(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        err: &mut Diagnostic,
-        span: Span,
-        is_fn_trait: bool,
-        suggested: bool,
-        unsatisfied_const: bool,
-    ) {
-        let body_def_id = obligation.cause.body_id;
-        let span = if let ObligationCauseCode::BinOp { rhs_span: Some(rhs_span), .. } =
-            obligation.cause.code()
-        {
-            *rhs_span
-        } else {
-            span
-        };
-
-        // Try to report a help message
-        if is_fn_trait
-            && let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
-                obligation.param_env,
-                trait_ref.self_ty(),
-                trait_predicate.skip_binder().polarity,
-            )
-        {
-            self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params);
-        } else if !trait_ref.has_non_region_infer()
-            && self.predicate_can_apply(obligation.param_env, *trait_predicate)
-        {
-            // If a where-clause may be useful, remind the
-            // user that they can add it.
-            //
-            // don't display an on-unimplemented note, as
-            // these notes will often be of the form
-            //     "the type `T` can't be frobnicated"
-            // which is somewhat confusing.
-            self.suggest_restricting_param_bound(
-                err,
-                *trait_predicate,
-                None,
-                obligation.cause.body_id,
-            );
-        } else if trait_ref.def_id().is_local()
-            && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty()
-            && !self.tcx.trait_is_auto(trait_ref.def_id())
-            && !self.tcx.trait_is_alias(trait_ref.def_id())
-        {
-            err.span_help(
-                self.tcx.def_span(trait_ref.def_id()),
-                crate::fluent_generated::trait_selection_trait_has_no_impls,
-            );
-        } else if !suggested && !unsatisfied_const {
-            // Can't show anything else useful, try to find similar impls.
-            let impl_candidates = self.find_similar_impl_candidates(*trait_predicate);
-            if !self.report_similar_impl_candidates(
-                &impl_candidates,
-                trait_ref,
-                body_def_id,
-                err,
-                true,
-                obligation.param_env,
-            ) {
-                self.report_similar_impl_candidates_for_root_obligation(
-                    &obligation,
-                    *trait_predicate,
-                    body_def_id,
-                    err,
-                );
-            }
-
-            self.suggest_convert_to_slice(
-                err,
-                obligation,
-                trait_ref,
-                impl_candidates.as_slice(),
-                span,
-            );
-        }
-    }
-
-    fn add_help_message_for_fn_trait(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        err: &mut Diagnostic,
-        implemented_kind: ty::ClosureKind,
-        params: ty::Binder<'tcx, Ty<'tcx>>,
-    ) {
-        // If the type implements `Fn`, `FnMut`, or `FnOnce`, suppress the following
-        // suggestion to add trait bounds for the type, since we only typically implement
-        // these traits once.
-
-        // Note if the `FnMut` or `FnOnce` is less general than the trait we're trying
-        // to implement.
-        let selected_kind = self
-            .tcx
-            .fn_trait_kind_from_def_id(trait_ref.def_id())
-            .expect("expected to map DefId to ClosureKind");
-        if !implemented_kind.extends(selected_kind) {
-            err.note(format!(
-                "`{}` implements `{}`, but it must implement `{}`, which is more general",
-                trait_ref.skip_binder().self_ty(),
-                implemented_kind,
-                selected_kind
-            ));
-        }
-
-        // Note any argument mismatches
-        let given_ty = params.skip_binder();
-        let expected_ty = trait_ref.skip_binder().args.type_at(1);
-        if let ty::Tuple(given) = given_ty.kind()
-            && let ty::Tuple(expected) = expected_ty.kind()
-        {
-            if expected.len() != given.len() {
-                // Note number of types that were expected and given
-                err.note(
-                    format!(
-                        "expected a closure taking {} argument{}, but one taking {} argument{} was given",
-                        given.len(),
-                        pluralize!(given.len()),
-                        expected.len(),
-                        pluralize!(expected.len()),
-                    )
-                );
-            } else if !self.same_type_modulo_infer(given_ty, expected_ty) {
-                // Print type mismatch
-                let (expected_args, given_args) =
-                    self.cmp(given_ty, expected_ty);
-                err.note_expected_found(
-                    &"a closure with arguments",
-                    expected_args,
-                    &"a closure with arguments",
-                    given_args,
-                );
-            }
-        }
-    }
-
-    fn maybe_add_note_for_unsatisfied_const(
-        &self,
-        _obligation: &PredicateObligation<'tcx>,
-        _trait_ref: ty::PolyTraitRef<'tcx>,
-        _trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        _err: &mut Diagnostic,
-        _span: Span,
-    ) -> UnsatisfiedConst {
-        let unsatisfied_const = UnsatisfiedConst(false);
-        // FIXME(effects)
-        unsatisfied_const
-    }
-
-    fn report_closure_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        closure_def_id: DefId,
-        found_kind: ty::ClosureKind,
-        kind: ty::ClosureKind,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let closure_span = self.tcx.def_span(closure_def_id);
-
-        let mut err = ClosureKindMismatch {
-            closure_span,
-            expected: kind,
-            found: found_kind,
-            cause_span: obligation.cause.span,
-            fn_once_label: None,
-            fn_mut_label: None,
-        };
-
-        // Additional context information explaining why the closure only implements
-        // a particular trait.
-        if let Some(typeck_results) = &self.typeck_results {
-            let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
-            match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
-                (ty::ClosureKind::FnOnce, Some((span, place))) => {
-                    err.fn_once_label = Some(ClosureFnOnceLabel {
-                        span: *span,
-                        place: ty::place_to_string_for_capture(self.tcx, &place),
-                    })
-                }
-                (ty::ClosureKind::FnMut, Some((span, place))) => {
-                    err.fn_mut_label = Some(ClosureFnMutLabel {
-                        span: *span,
-                        place: ty::place_to_string_for_capture(self.tcx, &place),
-                    })
-                }
-                _ => {}
-            }
-        }
-
-        self.tcx.sess.create_err(err)
-    }
-
-    fn report_type_parameter_mismatch_cyclic_type_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        terr: TypeError<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let self_ty = found_trait_ref.self_ty().skip_binder();
-        let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() {
-            (
-                ObligationCause::dummy_with_span(self.tcx.def_span(def_id)),
-                TypeError::CyclicTy(self_ty),
-            )
-        } else {
-            (obligation.cause.clone(), terr)
-        };
-        self.report_and_explain_type_error(
-            TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
-            terr,
-        )
-    }
-
-    fn report_opaque_type_auto_trait_leakage(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        def_id: DefId,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
-            hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
-                "opaque type".to_string()
-            }
-            hir::OpaqueTyOrigin::TyAlias { .. } => {
-                format!("`{}`", self.tcx.def_path_debug_str(def_id))
-            }
-        };
-        let mut err = self.tcx.sess.struct_span_err(
-            obligation.cause.span,
-            format!("cannot check whether the hidden type of {name} satisfies auto traits"),
-        );
-        err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
-        match self.defining_use_anchor {
-            DefiningAnchor::Bubble | DefiningAnchor::Error => {}
-            DefiningAnchor::Bind(bind) => {
-                err.span_note(
-                    self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
-                    "this item depends on auto traits of the hidden type, \
-                    but may also be registering the hidden type. \
-                    This is not supported right now. \
-                    You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
-                );
-            }
-        };
-        err
-    }
-
-    fn report_type_parameter_mismatch_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        span: Span,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref);
-        let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref);
-
-        if expected_trait_ref.self_ty().references_error() {
-            return None;
-        }
-
-        let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else {
-            return None;
-        };
-
-        let found_did = match *found_trait_ty.kind() {
-            ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Generator(did, ..) => {
-                Some(did)
-            }
-            ty::Adt(def, _) => Some(def.did()),
-            _ => None,
-        };
-
-        let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
-        let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
-
-        if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
-            // We check closures twice, with obligations flowing in different directions,
-            // but we want to complain about them only once.
-            return None;
-        }
-
-        self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
-        let mut not_tupled = false;
-
-        let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
-            ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
-            _ => {
-                not_tupled = true;
-                vec![ArgKind::empty()]
-            }
-        };
-
-        let expected_ty = expected_trait_ref.skip_binder().args.type_at(1);
-        let expected = match expected_ty.kind() {
-            ty::Tuple(ref tys) => {
-                tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect()
-            }
-            _ => {
-                not_tupled = true;
-                vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())]
-            }
-        };
-
-        // If this is a `Fn` family trait and either the expected or found
-        // is not tupled, then fall back to just a regular mismatch error.
-        // This shouldn't be common unless manually implementing one of the
-        // traits manually, but don't make it more confusing when it does
-        // happen.
-        Some(
-            if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().gen_trait() && not_tupled
-            {
-                self.report_and_explain_type_error(
-                    TypeTrace::poly_trait_refs(
-                        &obligation.cause,
-                        true,
-                        expected_trait_ref,
-                        found_trait_ref,
-                    ),
-                    ty::error::TypeError::Mismatch,
-                )
-            } else if found.len() == expected.len() {
-                self.report_closure_arg_mismatch(
-                    span,
-                    found_span,
-                    found_trait_ref,
-                    expected_trait_ref,
-                    obligation.cause.code(),
-                    found_node,
-                    obligation.param_env,
-                )
-            } else {
-                let (closure_span, closure_arg_span, found) = found_did
-                    .and_then(|did| {
-                        let node = self.tcx.hir().get_if_local(did)?;
-                        let (found_span, closure_arg_span, found) =
-                            self.get_fn_like_arguments(node)?;
-                        Some((Some(found_span), closure_arg_span, found))
-                    })
-                    .unwrap_or((found_span, None, found));
-
-                self.report_arg_count_mismatch(
-                    span,
-                    closure_span,
-                    expected,
-                    found,
-                    found_trait_ty.is_closure(),
-                    closure_arg_span,
-                )
-            },
-        )
-    }
-
-    fn report_not_const_evaluatable_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        span: Span,
-    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        if !self.tcx.features().generic_const_exprs {
-            let mut err = self
-                .tcx
-                .sess
-                .struct_span_err(span, "constant expression depends on a generic parameter");
-            // FIXME(const_generics): we should suggest to the user how they can resolve this
-            // issue. However, this is currently not actually possible
-            // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
-            //
-            // Note that with `feature(generic_const_exprs)` this case should not
-            // be reachable.
-            err.note("this may fail depending on what value the parameter takes");
-            err.emit();
-            return None;
-        }
-
-        match obligation.predicate.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
-                let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
-                    bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
-                };
-                let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
-                let const_span = self.tcx.def_span(uv.def);
-                match self.tcx.sess.source_map().span_to_snippet(const_span) {
-                    Ok(snippet) => err.help(format!(
-                        "try adding a `where` bound using this expression: `where [(); {snippet}]:`"
-                    )),
-                    _ => err.help("consider adding a `where` bound using this expression"),
-                };
-                Some(err)
-            }
-            _ => {
-                span_bug!(
-                    span,
-                    "unexpected non-ConstEvaluatable predicate, this should not be reachable"
-                )
-            }
-        }
-    }
-}
-
 struct UnsatisfiedConst(pub bool);
 
-fn get_explanation_based_on_obligation<'tcx>(
-    obligation: &PredicateObligation<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-    pre_message: String,
-) -> String {
-    if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
-        "consider using `()`, or a `Result`".to_owned()
-    } else {
-        let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
-            ty::FnDef(_, _) => Some("fn item"),
-            ty::Closure(_, _) => Some("closure"),
-            _ => None,
-        };
-
-        match ty_desc {
-            Some(desc) => format!(
-                "{}the trait `{}` is not implemented for {} `{}`",
-                pre_message,
-                trait_predicate.print_modifiers_and_trait_path(),
-                desc,
-                trait_ref.skip_binder().self_ty(),
-            ),
-            None => format!(
-                "{}the trait `{}` is not implemented for `{}`",
-                pre_message,
-                trait_predicate.print_modifiers_and_trait_path(),
-                trait_ref.skip_binder().self_ty(),
-            ),
-        }
-    }
-}
 /// Crude way of getting back an `Expr` from a `Span`.
 pub struct FindExprBySpan<'hir> {
     pub span: Span,
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 d645dc033b8..d9059e46a8c 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
@@ -18,7 +18,7 @@ use crate::errors::{
     EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
 };
 
-use super::InferCtxtPrivExt;
+use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
 
 pub trait TypeErrCtxtExt<'tcx> {
     /*private*/
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 b7c73501280..9aebe77a104 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -41,8 +41,8 @@ use rustc_target::spec::abi;
 use std::borrow::Cow;
 use std::iter;
 
-use super::InferCtxtPrivExt;
 use crate::infer::InferCtxtExt as _;
+use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
 
@@ -4254,6 +4254,39 @@ impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
     }
 }
 
+pub(super) fn get_explanation_based_on_obligation<'tcx>(
+    obligation: &PredicateObligation<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+    pre_message: String,
+) -> String {
+    if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
+        "consider using `()`, or a `Result`".to_owned()
+    } else {
+        let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
+            ty::FnDef(_, _) => Some("fn item"),
+            ty::Closure(_, _) => Some("closure"),
+            _ => None,
+        };
+
+        match ty_desc {
+            Some(desc) => format!(
+                "{}the trait `{}` is not implemented for {} `{}`",
+                pre_message,
+                trait_predicate.print_modifiers_and_trait_path(),
+                desc,
+                trait_ref.skip_binder().self_ty(),
+            ),
+            None => format!(
+                "{}the trait `{}` is not implemented for `{}`",
+                pre_message,
+                trait_predicate.print_modifiers_and_trait_path(),
+                trait_ref.skip_binder().self_ty(),
+            ),
+        }
+    }
+}
+
 // Replace `param` with `replace_ty`
 struct ReplaceImplTraitFolder<'tcx> {
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
new file mode 100644
index 00000000000..8adfb27a3f4
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -0,0 +1,3241 @@
+use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
+use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _};
+use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch};
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{self, InferCtxt};
+use crate::traits::error_reporting::infer_ctxt_ext::InferCtxtExt;
+use crate::traits::error_reporting::{ambiguity, ambiguity::Ambiguity::*};
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::specialize::to_pretty_impl_header;
+use crate::traits::NormalizeExt;
+use crate::traits::{
+    elaborate, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
+    ObligationCause, ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
+    PredicateObligation, SelectionError, TraitNotObjectSafe,
+};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_errors::{
+    pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+    MultiSpan, Style,
+};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Namespace, Res};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{GenericParam, Item, Node};
+use rustc_infer::infer::error_reporting::TypeErrCtxt;
+use rustc_infer::infer::{InferOk, TypeTrace};
+use rustc_middle::traits::select::OverflowError;
+use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
+use rustc_middle::ty::abstract_const::NotConstEvaluatable;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
+use rustc_middle::ty::{
+    self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
+    TypeVisitable, TypeVisitableExt,
+};
+use rustc_session::config::{DumpSolverProofTree, TraitSolver};
+use rustc_session::Limit;
+use rustc_span::def_id::LOCAL_CRATE;
+use rustc_span::symbol::sym;
+use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::borrow::Cow;
+use std::fmt;
+use std::iter;
+
+use super::{
+    dump_proof_tree, ArgKind, CandidateSimilarity, FindExprBySpan, FindTypeParam,
+    GetSafeTransmuteErrorAndReason, HasNumericInferVisitor, ImplCandidate, UnsatisfiedConst,
+};
+
+pub use rustc_infer::traits::error_reporting::*;
+
+pub trait TypeErrCtxtExt<'tcx> {
+    fn build_overflow_error<T>(
+        &self,
+        predicate: &T,
+        span: Span,
+        suggest_increasing_limit: bool,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+    where
+        T: fmt::Display
+            + TypeFoldable<TyCtxt<'tcx>>
+            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
+    fn report_overflow_error<T>(
+        &self,
+        predicate: &T,
+        span: Span,
+        suggest_increasing_limit: bool,
+        mutate: impl FnOnce(&mut Diagnostic),
+    ) -> !
+    where
+        T: fmt::Display
+            + TypeFoldable<TyCtxt<'tcx>>
+            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
+    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
+
+    fn report_fulfillment_errors(&self, errors: Vec<FulfillmentError<'tcx>>) -> ErrorGuaranteed;
+
+    fn report_overflow_obligation<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: ToPredicate<'tcx> + Clone;
+
+    fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
+
+    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
+
+    /// The `root_obligation` parameter should be the `root_obligation` field
+    /// from a `FulfillmentError`. If no `FulfillmentError` is available,
+    /// then it should be the same as `obligation`.
+    fn report_selection_error(
+        &self,
+        obligation: PredicateObligation<'tcx>,
+        root_obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+    );
+
+    fn report_const_param_not_wf(
+        &self,
+        ty: Ty<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+}
+
+impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+    fn report_fulfillment_errors(
+        &self,
+        mut errors: Vec<FulfillmentError<'tcx>>,
+    ) -> ErrorGuaranteed {
+        #[derive(Debug)]
+        struct ErrorDescriptor<'tcx> {
+            predicate: ty::Predicate<'tcx>,
+            index: Option<usize>, // None if this is an old error
+        }
+
+        let mut error_map: FxIndexMap<_, Vec<_>> = self
+            .reported_trait_errors
+            .borrow()
+            .iter()
+            .map(|(&span, predicates)| {
+                (
+                    span,
+                    predicates
+                        .iter()
+                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
+                        .collect(),
+                )
+            })
+            .collect();
+
+        // Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics
+        // with more relevant type information and hide redundant E0282 errors.
+        errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() {
+            ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
+                if Some(pred.def_id()) == self.tcx.lang_items().sized_trait() =>
+            {
+                1
+            }
+            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
+            ty::PredicateKind::Coerce(_) => 2,
+            _ => 0,
+        });
+
+        for (index, error) in errors.iter().enumerate() {
+            // We want to ignore desugarings here: spans are equivalent even
+            // if one is the result of a desugaring and the other is not.
+            let mut span = error.obligation.cause.span;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
+            }
+
+            error_map.entry(span).or_default().push(ErrorDescriptor {
+                predicate: error.obligation.predicate,
+                index: Some(index),
+            });
+
+            self.reported_trait_errors
+                .borrow_mut()
+                .entry(span)
+                .or_default()
+                .push(error.obligation.predicate);
+        }
+
+        // We do this in 2 passes because we want to display errors in order, though
+        // maybe it *is* better to sort errors by span or something.
+        let mut is_suppressed = vec![false; errors.len()];
+        for (_, error_set) in error_map.iter() {
+            // We want to suppress "duplicate" errors with the same span.
+            for error in error_set {
+                if let Some(index) = error.index {
+                    // Suppress errors that are either:
+                    // 1) strictly implied by another error.
+                    // 2) implied by an error with a smaller index.
+                    for error2 in error_set {
+                        if error2.index.is_some_and(|index2| is_suppressed[index2]) {
+                            // Avoid errors being suppressed by already-suppressed
+                            // errors, to prevent all errors from being suppressed
+                            // at once.
+                            continue;
+                        }
+
+                        if self.error_implies(error2.predicate, error.predicate)
+                            && !(error2.index >= error.index
+                                && self.error_implies(error.predicate, error2.predicate))
+                        {
+                            info!("skipping {:?} (implied by {:?})", error, error2);
+                            is_suppressed[index] = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        for from_expansion in [false, true] {
+            for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
+                if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
+                    self.report_fulfillment_error(error);
+                }
+            }
+        }
+
+        self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fulfillment errors")
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    fn report_overflow_error<T>(
+        &self,
+        predicate: &T,
+        span: Span,
+        suggest_increasing_limit: bool,
+        mutate: impl FnOnce(&mut Diagnostic),
+    ) -> !
+    where
+        T: fmt::Display
+            + TypeFoldable<TyCtxt<'tcx>>
+            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+    {
+        let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit);
+        mutate(&mut err);
+        err.emit();
+
+        self.tcx.sess.abort_if_errors();
+        bug!();
+    }
+
+    fn build_overflow_error<T>(
+        &self,
+        predicate: &T,
+        span: Span,
+        suggest_increasing_limit: bool,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+    where
+        T: fmt::Display
+            + TypeFoldable<TyCtxt<'tcx>>
+            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+    {
+        let predicate = self.resolve_vars_if_possible(predicate.clone());
+        let mut pred_str = predicate.to_string();
+
+        if pred_str.len() > 50 {
+            // We don't need to save the type to a file, we will be talking about this type already
+            // in a separate note when we explain the obligation, so it will be available that way.
+            pred_str = predicate
+                .print(FmtPrinter::new_with_limit(
+                    self.tcx,
+                    Namespace::TypeNS,
+                    rustc_session::Limit(6),
+                ))
+                .unwrap()
+                .into_buffer();
+        }
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            pred_str,
+        );
+
+        if suggest_increasing_limit {
+            self.suggest_new_overflow_limit(&mut err);
+        }
+
+        err
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    fn report_overflow_obligation<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: ToPredicate<'tcx> + Clone,
+    {
+        let predicate = obligation.predicate.clone().to_predicate(self.tcx);
+        let predicate = self.resolve_vars_if_possible(predicate);
+        self.report_overflow_error(
+            &predicate,
+            obligation.cause.span,
+            suggest_increasing_limit,
+            |err| {
+                self.note_obligation_cause_code(
+                    obligation.cause.body_id,
+                    err,
+                    predicate,
+                    obligation.param_env,
+                    obligation.cause.code(),
+                    &mut vec![],
+                    &mut Default::default(),
+                );
+            },
+        );
+    }
+
+    fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
+        let suggested_limit = match self.tcx.recursion_limit() {
+            Limit(0) => Limit(2),
+            limit => limit * 2,
+        };
+        err.help(format!(
+            "consider increasing the recursion limit by adding a \
+             `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
+            suggested_limit,
+            self.tcx.crate_name(LOCAL_CRATE),
+        ));
+    }
+
+    /// Reports that a cycle was detected which led to overflow and halts
+    /// compilation. This is equivalent to `report_overflow_obligation` except
+    /// that we can give a more helpful error message (and, in particular,
+    /// we do not suggest increasing the overflow limit, which is not
+    /// going to help).
+    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+        let cycle = self.resolve_vars_if_possible(cycle.to_owned());
+        assert!(!cycle.is_empty());
+
+        debug!(?cycle, "report_overflow_error_cycle");
+
+        // The 'deepest' obligation is most likely to have a useful
+        // cause 'backtrace'
+        self.report_overflow_obligation(
+            cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
+            false,
+        );
+    }
+
+    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
+        let obligation = self.resolve_vars_if_possible(obligation);
+        let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
+        self.note_obligation_cause(&mut err, &obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+        err.emit()
+    }
+
+    fn report_selection_error(
+        &self,
+        mut obligation: PredicateObligation<'tcx>,
+        root_obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+    ) {
+        let tcx = self.tcx;
+
+        if tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError {
+            dump_proof_tree(root_obligation, self.infcx);
+        }
+
+        let mut span = obligation.cause.span;
+        // FIXME: statically guarantee this by tainting after the diagnostic is emitted
+        self.set_tainted_by_errors(
+            tcx.sess.delay_span_bug(span, "`report_selection_error` did not emit an error"),
+        );
+
+        let mut err = match *error {
+            SelectionError::Unimplemented => {
+                // If this obligation was generated as a result of well-formedness checking, see if we
+                // can get a better error message by performing HIR-based well-formedness checking.
+                if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
+                    root_obligation.cause.code().peel_derives()
+                    && !obligation.predicate.has_non_region_infer()
+                {
+                    if let Some(cause) = self
+                        .tcx
+                        .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc))
+                    {
+                        obligation.cause = cause.clone();
+                        span = obligation.cause.span;
+                    }
+                }
+
+                if let ObligationCauseCode::CompareImplItemObligation {
+                    impl_item_def_id,
+                    trait_item_def_id,
+                    kind: _,
+                } = *obligation.cause.code()
+                {
+                    self.report_extra_impl_obligation(
+                        span,
+                        impl_item_def_id,
+                        trait_item_def_id,
+                        &format!("`{}`", obligation.predicate),
+                    )
+                    .emit();
+                    return;
+                }
+
+                // Report a const-param specific error
+                if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()
+                {
+                    self.report_const_param_not_wf(ty, &obligation).emit();
+                    return;
+                }
+
+                let bound_predicate = obligation.predicate.kind();
+                match bound_predicate.skip_binder() {
+                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
+                        let trait_predicate = bound_predicate.rebind(trait_predicate);
+                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+
+                        // FIXME(effects)
+                        let predicate_is_const = false;
+
+                        if self.tcx.sess.has_errors().is_some()
+                            && trait_predicate.references_error()
+                        {
+                            return;
+                        }
+                        let trait_ref = trait_predicate.to_poly_trait_ref();
+
+                        let (post_message, pre_message, type_def) = self
+                            .get_parent_trait_ref(obligation.cause.code())
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{t}`"),
+                                    format!("within `{t}`, "),
+                                    s.map(|s| (format!("within this `{t}`"), s)),
+                                )
+                            })
+                            .unwrap_or_default();
+
+                        let OnUnimplementedNote {
+                            message,
+                            label,
+                            note,
+                            parent_label,
+                            append_const_msg,
+                        } = self.on_unimplemented_note(trait_ref, &obligation);
+                        let have_alt_message = message.is_some() || label.is_some();
+                        let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
+                        let is_unsize =
+                            Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait();
+                        let (message, note, append_const_msg) = if is_try_conversion {
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error to `{}`",
+                                    trait_ref.skip_binder().self_ty(),
+                                )),
+                                Some(
+                                    "the question mark operation (`?`) implicitly performs a \
+                                     conversion on the error value using the `From` trait"
+                                        .to_owned(),
+                                ),
+                                Some(AppendConstMessage::Default),
+                            )
+                        } else {
+                            (message, note, append_const_msg)
+                        };
+
+                        let err_msg = self.get_standard_error_message(
+                            &trait_predicate,
+                            message,
+                            predicate_is_const,
+                            append_const_msg,
+                            post_message,
+                        );
+
+                        let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id())
+                            == self.tcx.lang_items().transmute_trait()
+                        {
+                            // Recompute the safe transmute reason and use that for the error reporting
+                            match self.get_safe_transmute_error_and_reason(
+                                obligation.clone(),
+                                trait_ref,
+                                span,
+                            ) {
+                                GetSafeTransmuteErrorAndReason::Silent => return,
+                                GetSafeTransmuteErrorAndReason::Error {
+                                    err_msg,
+                                    safe_transmute_explanation,
+                                } => (err_msg, Some(safe_transmute_explanation)),
+                            }
+                        } else {
+                            (err_msg, None)
+                        };
+
+                        let mut err = struct_span_err!(self.tcx.sess, span, E0277, "{}", err_msg);
+
+                        if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
+                            err.span_label(
+                                ret_span,
+                                format!(
+                                    "expected `{}` because of this",
+                                    trait_ref.skip_binder().self_ty()
+                                ),
+                            );
+                        }
+
+                        if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
+                            self.add_tuple_trait_message(
+                                &obligation.cause.code().peel_derives(),
+                                &mut err,
+                            );
+                        }
+
+                        if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait()
+                            && predicate_is_const
+                        {
+                            err.note("`~const Drop` was renamed to `~const Destruct`");
+                            err.note("See <https://github.com/rust-lang/rust/pull/94901> for more details");
+                        }
+
+                        let explanation = get_explanation_based_on_obligation(
+                            &obligation,
+                            trait_ref,
+                            &trait_predicate,
+                            pre_message,
+                        );
+
+                        self.check_for_binding_assigned_block_without_tail_expression(
+                            &obligation,
+                            &mut err,
+                            trait_predicate,
+                        );
+                        if self.suggest_add_reference_to_arg(
+                            &obligation,
+                            &mut err,
+                            trait_predicate,
+                            have_alt_message,
+                        ) {
+                            self.note_obligation_cause(&mut err, &obligation);
+                            err.emit();
+                            return;
+                        }
+                        if let Some(s) = label {
+                            // If it has a custom `#[rustc_on_unimplemented]`
+                            // error message, let's display it as the label!
+                            err.span_label(span, s);
+                            if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
+                                // When the self type is a type param We don't need to "the trait
+                                // `std::marker::Sized` is not implemented for `T`" as we will point
+                                // at the type param with a label to suggest constraining it.
+                                err.help(explanation);
+                            }
+                        } else if let Some(custom_explanation) = safe_transmute_explanation {
+                            err.span_label(span, custom_explanation);
+                        } else {
+                            err.span_label(span, explanation);
+                        }
+
+                        if let ObligationCauseCode::Coercion { source, target } =
+                            *obligation.cause.code().peel_derives()
+                        {
+                            if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
+                                self.suggest_borrowing_for_object_cast(
+                                    &mut err,
+                                    &root_obligation,
+                                    source,
+                                    target,
+                                );
+                            }
+                        }
+
+                        let UnsatisfiedConst(unsatisfied_const) = self
+                            .maybe_add_note_for_unsatisfied_const(
+                                &obligation,
+                                trait_ref,
+                                &trait_predicate,
+                                &mut err,
+                                span,
+                            );
+
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, msg);
+                        }
+                        if let Some(s) = note {
+                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
+                            err.note(s);
+                        }
+                        if let Some(s) = parent_label {
+                            let body = obligation.cause.body_id;
+                            err.span_label(tcx.def_span(body), s);
+                        }
+
+                        self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
+                        self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate);
+                        let mut suggested =
+                            self.suggest_dereferences(&obligation, &mut err, trait_predicate);
+                        suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
+                        let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
+                        suggested = if let &[cand] = &impl_candidates[..] {
+                            let cand = cand.trait_ref;
+                            if let (ty::FnPtr(_), ty::FnDef(..)) =
+                                (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind())
+                            {
+                                err.span_suggestion(
+                                    span.shrink_to_hi(),
+                                    format!(
+                                        "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
+                                        cand.print_only_trait_path(),
+                                        cand.self_ty(),
+                                    ),
+                                    format!(" as {}", cand.self_ty()),
+                                    Applicability::MaybeIncorrect,
+                                );
+                                true
+                            } else {
+                                false
+                            }
+                        } else {
+                            false
+                        } || suggested;
+                        suggested |=
+                            self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
+                        suggested |= self.suggest_semicolon_removal(
+                            &obligation,
+                            &mut err,
+                            span,
+                            trait_predicate,
+                        );
+                        self.note_version_mismatch(&mut err, &trait_ref);
+                        self.suggest_remove_await(&obligation, &mut err);
+                        self.suggest_derive(&obligation, &mut err, trait_predicate);
+
+                        if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
+                            self.suggest_await_before_try(
+                                &mut err,
+                                &obligation,
+                                trait_predicate,
+                                span,
+                            );
+                        }
+
+                        if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) {
+                            err.emit();
+                            return;
+                        }
+
+                        if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
+                            err.emit();
+                            return;
+                        }
+
+                        if is_unsize {
+                            // If the obligation failed due to a missing implementation of the
+                            // `Unsize` trait, give a pointer to why that might be the case
+                            err.note(
+                                "all implementations of `Unsize` are provided \
+                                automatically by the compiler, see \
+                                <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \
+                                for more information",
+                            );
+                        }
+
+                        let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id());
+                        let is_target_feature_fn = if let ty::FnDef(def_id, _) =
+                            *trait_ref.skip_binder().self_ty().kind()
+                        {
+                            !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
+                        } else {
+                            false
+                        };
+                        if is_fn_trait && is_target_feature_fn {
+                            err.note(
+                                "`#[target_feature]` functions do not implement the `Fn` traits",
+                            );
+                        }
+
+                        self.try_to_add_help_message(
+                            &obligation,
+                            trait_ref,
+                            &trait_predicate,
+                            &mut err,
+                            span,
+                            is_fn_trait,
+                            suggested,
+                            unsatisfied_const,
+                        );
+
+                        // Changing mutability doesn't make a difference to whether we have
+                        // an `Unsize` impl (Fixes ICE in #71036)
+                        if !is_unsize {
+                            self.suggest_change_mut(&obligation, &mut err, trait_predicate);
+                        }
+
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occurred, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && self.fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|trait_pred| {
+                                trait_pred.with_self_ty(self.tcx, Ty::new_unit(self.tcx))
+                            });
+                            let unit_obligation = obligation.with(tcx, predicate);
+                            if self.predicate_may_hold(&unit_obligation) {
+                                err.note(
+                                    "this error might have been caused by changes to \
+                                    Rust's type-inference algorithm (see issue #48950 \
+                                    <https://github.com/rust-lang/rust/issues/48950> \
+                                    for more information)",
+                                );
+                                err.help("did you intend to use the type `()` here instead?");
+                            }
+                        }
+
+                        self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause);
+                        self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref);
+
+                        // Return early if the trait is Debug or Display and the invocation
+                        // originates within a standard library macro, because the output
+                        // is otherwise overwhelming and unhelpful (see #85844 for an
+                        // example).
+
+                        let in_std_macro =
+                            match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
+                                Some(macro_def_id) => {
+                                    let crate_name = tcx.crate_name(macro_def_id.krate);
+                                    crate_name == sym::std || crate_name == sym::core
+                                }
+                                None => false,
+                            };
+
+                        if in_std_macro
+                            && matches!(
+                                self.tcx.get_diagnostic_name(trait_ref.def_id()),
+                                Some(sym::Debug | sym::Display)
+                            )
+                        {
+                            err.emit();
+                            return;
+                        }
+
+                        err
+                    }
+
+                    ty::PredicateKind::Subtype(predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::PredicateKind::Coerce(predicate) => {
+                        // Errors for Coerce predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
+                    | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => {
+                        span_bug!(
+                            span,
+                            "outlives clauses should not error outside borrowck. obligation: `{:?}`",
+                            obligation
+                        )
+                    }
+
+                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
+                        span_bug!(
+                            span,
+                            "projection clauses should be implied from elsewhere. obligation: `{:?}`",
+                            obligation
+                        )
+                    }
+
+                    ty::PredicateKind::ObjectSafe(trait_def_id) => {
+                        let violations = self.tcx.object_safety_violations(trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                    }
+
+                    ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
+                        let found_kind = self.closure_kind(closure_args).unwrap();
+                        self.report_closure_error(&obligation, closure_def_id, found_kind, kind)
+                    }
+
+                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
+                        let ty = self.resolve_vars_if_possible(ty);
+                        match self.tcx.sess.opts.unstable_opts.trait_solver {
+                            TraitSolver::Classic => {
+                                // WF predicates cannot themselves make
+                                // errors. They can only block due to
+                                // ambiguity; otherwise, they always
+                                // degenerate into other obligations
+                                // (which may fail).
+                                span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+                            }
+                            TraitSolver::Next | TraitSolver::NextCoherence => {
+                                // FIXME: we'll need a better message which takes into account
+                                // which bounds actually failed to hold.
+                                self.tcx.sess.struct_span_err(
+                                    span,
+                                    format!("the type `{ty}` is not well-formed"),
+                                )
+                            }
+                        }
+                    }
+
+                    ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
+                        // Errors for `ConstEvaluatable` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+
+                    ty::PredicateKind::ConstEquate(..) => {
+                        // Errors for `ConstEquate` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-equate requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+
+                    ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
+
+                    ty::PredicateKind::AliasRelate(..) => span_bug!(
+                        span,
+                        "AliasRelate predicate should never be the predicate cause of a SelectionError"
+                    ),
+
+                    ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
+                        let mut diag = self.tcx.sess.struct_span_err(
+                            span,
+                            format!("the constant `{ct}` is not of type `{ty}`"),
+                        );
+                        self.note_type_err(
+                            &mut diag,
+                            &obligation.cause,
+                            None,
+                            None,
+                            TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())),
+                            false,
+                            false,
+                        );
+                        diag
+                    }
+                }
+            }
+
+            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
+                found_trait_ref,
+                expected_trait_ref,
+                terr: terr @ TypeError::CyclicTy(_),
+            }) => self.report_type_parameter_mismatch_cyclic_type_error(
+                &obligation,
+                found_trait_ref,
+                expected_trait_ref,
+                terr,
+            ),
+            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
+                found_trait_ref,
+                expected_trait_ref,
+                terr: _,
+            }) => {
+                match self.report_type_parameter_mismatch_error(
+                    &obligation,
+                    span,
+                    found_trait_ref,
+                    expected_trait_ref,
+                ) {
+                    Some(err) => err,
+                    None => return,
+                }
+            }
+
+            SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage(
+                &obligation,
+                def_id,
+            ),
+
+            TraitNotObjectSafe(did) => {
+                let violations = self.tcx.object_safety_violations(did);
+                report_object_safety_error(self.tcx, span, did, violations)
+            }
+
+            SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {
+                bug!(
+                    "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"
+                )
+            }
+            SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
+                match self.report_not_const_evaluatable_error(&obligation, span) {
+                    Some(err) => err,
+                    None => return,
+                }
+            }
+
+            // Already reported in the query.
+            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) |
+            // Already reported.
+            Overflow(OverflowError::Error(_)) => return,
+
+            Overflow(_) => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
+            SelectionError::ErrorReporting => {
+                bug!("ErrorReporting Overflow should not reach `report_selection_err` call")
+            }
+        };
+
+        self.note_obligation_cause(&mut err, &obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+        err.emit();
+    }
+
+    fn report_const_param_not_wf(
+        &self,
+        ty: Ty<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        let span = obligation.cause.span;
+
+        let mut diag = match ty.kind() {
+            _ if ty.has_param() => {
+                span_bug!(span, "const param tys cannot mention other generic parameters");
+            }
+            ty::Float(_) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0741,
+                    "`{ty}` is forbidden as the type of a const generic parameter",
+                )
+            }
+            ty::FnPtr(_) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0741,
+                    "using function pointers as const generic parameters is forbidden",
+                )
+            }
+            ty::RawPtr(_) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0741,
+                    "using raw pointers as const generic parameters is forbidden",
+                )
+            }
+            ty::Adt(def, _) => {
+                // We should probably see if we're *allowed* to derive `ConstParamTy` on the type...
+                let mut diag = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0741,
+                    "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
+                );
+                // Only suggest derive if this isn't a derived obligation,
+                // and the struct is local.
+                if let Some(span) = self.tcx.hir().span_if_local(def.did())
+                    && obligation.cause.code().parent().is_none()
+                {
+                    if ty.is_structural_eq_shallow(self.tcx) {
+                        diag.span_suggestion(
+                            span,
+                            "add `#[derive(ConstParamTy)]` to the struct",
+                            "#[derive(ConstParamTy)]\n",
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        // FIXME(adt_const_params): We should check there's not already an
+                        // overlapping `Eq`/`PartialEq` impl.
+                        diag.span_suggestion(
+                            span,
+                            "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct",
+                            "#[derive(ConstParamTy, PartialEq, Eq)]\n",
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                }
+                diag
+            }
+            _ => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0741,
+                    "`{ty}` can't be used as a const parameter type",
+                )
+            }
+        };
+
+        let mut code = obligation.cause.code();
+        let mut pred = obligation.predicate.to_opt_poly_trait_pred();
+        while let Some((next_code, next_pred)) = code.parent() {
+            if let Some(pred) = pred {
+                let pred = self.instantiate_binder_with_placeholders(pred);
+                diag.note(format!(
+                    "`{}` must implement `{}`, but it does not",
+                    pred.self_ty(),
+                    pred.print_modifiers_and_trait_path()
+                ));
+            }
+            code = next_code;
+            pred = next_pred;
+        }
+
+        diag
+    }
+}
+
+pub(super) trait InferCtxtPrivExt<'tcx> {
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
+
+    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>);
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    );
+
+    fn maybe_detailed_projection_msg(
+        &self,
+        pred: ty::ProjectionPredicate<'tcx>,
+        normalized_ty: ty::Term<'tcx>,
+        expected_ty: ty::Term<'tcx>,
+    ) -> Option<String>;
+
+    fn fuzzy_match_tys(
+        &self,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
+        ignoring_lifetimes: bool,
+    ) -> Option<CandidateSimilarity>;
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> Vec<ImplCandidate<'tcx>>;
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: &[ImplCandidate<'tcx>],
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        body_def_id: LocalDefId,
+        err: &mut Diagnostic,
+        other: bool,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool;
+
+    fn report_similar_impl_candidates_for_root_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
+        body_def_id: LocalDefId,
+        err: &mut Diagnostic,
+    );
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)>;
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut Diagnostic,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) -> bool;
+
+    /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
+    /// `trait_ref`.
+    ///
+    /// For this to work, `new_self_ty` must have no escaping bound variables.
+    fn mk_trait_obligation_with_new_self_ty(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
+    ) -> PredicateObligation<'tcx>;
+
+    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>);
+
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> bool;
+
+    fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
+
+    fn suggest_unsized_bound_if_applicable(
+        &self,
+        err: &mut Diagnostic,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn annotate_source_of_ambiguity(
+        &self,
+        err: &mut Diagnostic,
+        impls: &[ambiguity::Ambiguity],
+        predicate: ty::Predicate<'tcx>,
+    );
+
+    fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>);
+
+    fn maybe_indirection_for_unsized(
+        &self,
+        err: &mut Diagnostic,
+        item: &'tcx Item<'tcx>,
+        param: &'tcx GenericParam<'tcx>,
+    ) -> bool;
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<Ty<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool;
+
+    fn get_standard_error_message(
+        &self,
+        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        message: Option<String>,
+        predicate_is_const: bool,
+        append_const_msg: Option<AppendConstMessage>,
+        post_message: String,
+    ) -> String;
+
+    fn get_safe_transmute_error_and_reason(
+        &self,
+        obligation: PredicateObligation<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        span: Span,
+    ) -> GetSafeTransmuteErrorAndReason;
+
+    fn add_tuple_trait_message(
+        &self,
+        obligation_cause_code: &ObligationCauseCode<'tcx>,
+        err: &mut Diagnostic,
+    );
+
+    fn try_to_add_help_message(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        err: &mut Diagnostic,
+        span: Span,
+        is_fn_trait: bool,
+        suggested: bool,
+        unsatisfied_const: bool,
+    );
+
+    fn add_help_message_for_fn_trait(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        err: &mut Diagnostic,
+        implemented_kind: ty::ClosureKind,
+        params: ty::Binder<'tcx, Ty<'tcx>>,
+    );
+
+    fn maybe_add_note_for_unsatisfied_const(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        err: &mut Diagnostic,
+        span: Span,
+    ) -> UnsatisfiedConst;
+
+    fn report_closure_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        closure_def_id: DefId,
+        found_kind: ty::ClosureKind,
+        kind: ty::ClosureKind,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+
+    fn report_type_parameter_mismatch_cyclic_type_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        terr: TypeError<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+
+    fn report_opaque_type_auto_trait_leakage(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        def_id: DefId,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+
+    fn report_type_parameter_mismatch_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        span: Span,
+        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
+
+    fn report_not_const_evaluatable_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        span: Span,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
+}
+
+impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
+        if cond == error {
+            return true;
+        }
+
+        // FIXME: It should be possible to deal with `ForAll` in a cleaner way.
+        let bound_error = error.kind();
+        let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) {
+            (
+                ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)),
+                ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)),
+            ) => (cond, bound_error.rebind(error)),
+            _ => {
+                // FIXME: make this work in other cases too.
+                return false;
+            }
+        };
+
+        for pred in elaborate(self.tcx, std::iter::once(cond)) {
+            let bound_predicate = pred.kind();
+            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) =
+                bound_predicate.skip_binder()
+            {
+                let error = error.to_poly_trait_ref();
+                let implication = bound_predicate.rebind(implication.trait_ref);
+                // FIXME: I'm just not taking associated types at all here.
+                // Eventually I'll need to implement param-env-aware
+                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
+                let param_env = ty::ParamEnv::empty();
+                if self.can_sub(param_env, error, implication) {
+                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
+        if self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree == DumpSolverProofTree::OnError {
+            dump_proof_tree(&error.root_obligation, self.infcx);
+        }
+
+        match error.code {
+            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+                self.report_selection_error(
+                    error.obligation.clone(),
+                    &error.root_obligation,
+                    selection_error,
+                );
+            }
+            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+                self.report_projection_error(&error.obligation, e);
+            }
+            FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
+                self.maybe_report_ambiguity(&error.obligation);
+            }
+            FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
+                self.report_overflow_no_abort(error.obligation.clone());
+            }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    *err,
+                )
+                .emit();
+            }
+            FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => {
+                let mut diag = self.report_mismatched_consts(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    *err,
+                );
+                let code = error.obligation.cause.code().peel_derives().peel_match_impls();
+                if let ObligationCauseCode::BindingObligation(..)
+                | ObligationCauseCode::ItemObligation(..)
+                | ObligationCauseCode::ExprBindingObligation(..)
+                | ObligationCauseCode::ExprItemObligation(..) = code
+                {
+                    self.note_obligation_cause_code(
+                        error.obligation.cause.body_id,
+                        &mut diag,
+                        error.obligation.predicate,
+                        error.obligation.param_env,
+                        code,
+                        &mut vec![],
+                        &mut Default::default(),
+                    );
+                }
+                diag.emit();
+            }
+            FulfillmentErrorCode::CodeCycle(ref cycle) => {
+                self.report_overflow_obligation_cycle(cycle);
+            }
+        }
+    }
+
+    #[instrument(level = "debug", skip_all)]
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    ) {
+        let predicate = self.resolve_vars_if_possible(obligation.predicate);
+
+        if predicate.references_error() {
+            return;
+        }
+
+        self.probe(|_| {
+            let ocx = ObligationCtxt::new(self);
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            let bound_predicate = predicate.kind();
+            let (values, err) = if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) =
+                bound_predicate.skip_binder()
+            {
+                let data = self.instantiate_binder_with_fresh_vars(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    bound_predicate.rebind(data),
+                );
+                let unnormalized_term = match data.term.unpack() {
+                    ty::TermKind::Ty(_) => Ty::new_projection(
+                        self.tcx,
+                        data.projection_ty.def_id,
+                        data.projection_ty.args,
+                    )
+                    .into(),
+                    ty::TermKind::Const(ct) => ty::Const::new_unevaluated(
+                        self.tcx,
+                        ty::UnevaluatedConst {
+                            def: data.projection_ty.def_id,
+                            args: data.projection_ty.args,
+                        },
+                        ct.ty(),
+                    )
+                    .into(),
+                };
+                // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice
+                // to deeply normalize this type.
+                let normalized_term =
+                    ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
+
+                debug!(?obligation.cause, ?obligation.param_env);
+
+                debug!(?normalized_term, data.ty = ?data.term);
+
+                let is_normalized_term_expected = !matches!(
+                    obligation.cause.code().peel_derives(),
+                    ObligationCauseCode::ItemObligation(_)
+                        | ObligationCauseCode::BindingObligation(_, _)
+                        | ObligationCauseCode::ExprItemObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
+                        | ObligationCauseCode::Coercion { .. }
+                        | ObligationCauseCode::OpaqueType
+                );
+
+                // constrain inference variables a bit more to nested obligations from normalize so
+                // we can have more helpful errors.
+                //
+                // we intentionally drop errors from normalization here,
+                // since the normalization is just done to improve the error message.
+                let _ = ocx.select_where_possible();
+
+                if let Err(new_err) = ocx.eq_exp(
+                    &obligation.cause,
+                    obligation.param_env,
+                    is_normalized_term_expected,
+                    normalized_term,
+                    data.term,
+                ) {
+                    (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
+                } else {
+                    (None, error.err)
+                }
+            } else {
+                (None, error.err)
+            };
+
+            let msg = values
+                .and_then(|(predicate, _, normalized_term, expected_term)| {
+                    self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
+                })
+                .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 = (|| {
+                let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
+                    predicate.kind().skip_binder()
+                else {
+                    return None;
+                };
+
+                let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
+                let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
+
+                let mut associated_items = vec![];
+                self.tcx.for_each_relevant_impl(
+                    self.tcx.trait_of_item(proj.projection_ty.def_id)?,
+                    proj.projection_ty.self_ty(),
+                    |impl_def_id| {
+                        associated_items.extend(
+                            self.tcx
+                                .associated_items(impl_def_id)
+                                .in_definition_order()
+                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
+                        );
+                    },
+                );
+
+                let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
+                    return None;
+                };
+                match self.tcx.hir().get_if_local(associated_item.def_id) {
+                    Some(
+                        hir::Node::TraitItem(hir::TraitItem {
+                            kind: hir::TraitItemKind::Type(_, Some(ty)),
+                            ..
+                        })
+                        | hir::Node::ImplItem(hir::ImplItem {
+                            kind: hir::ImplItemKind::Type(ty),
+                            ..
+                        }),
+                    ) => Some((
+                        ty.span,
+                        with_forced_trimmed_paths!(Cow::from(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,
+                }
+            })();
+
+            self.note_type_err(
+                &mut diag,
+                &obligation.cause,
+                secondary_span,
+                values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| {
+                    infer::ValuePairs::Terms(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        expected_ty,
+                    ))
+                }),
+                err,
+                true,
+                false,
+            );
+            self.note_obligation_cause(&mut diag, obligation);
+            diag.emit();
+        });
+    }
+
+    fn maybe_detailed_projection_msg(
+        &self,
+        pred: ty::ProjectionPredicate<'tcx>,
+        normalized_ty: ty::Term<'tcx>,
+        expected_ty: ty::Term<'tcx>,
+    ) -> Option<String> {
+        let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
+        let self_ty = pred.projection_ty.self_ty();
+
+        with_forced_trimmed_paths! {
+            if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+                let fn_kind = self_ty.prefix_string(self.tcx);
+                let item = match self_ty.kind() {
+                    ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
+                    _ => self_ty.to_string(),
+                };
+                Some(format!(
+                    "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+                     returns `{normalized_ty}`",
+                ))
+            } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
+                Some(format!(
+                    "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
+                     resolves to `{normalized_ty}`"
+                ))
+            } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+                Some(format!(
+                    "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
+                     yields `{normalized_ty}`"
+                ))
+            } else {
+                None
+            }
+        }
+    }
+
+    fn fuzzy_match_tys(
+        &self,
+        mut a: Ty<'tcx>,
+        mut b: Ty<'tcx>,
+        ignoring_lifetimes: bool,
+    ) -> Option<CandidateSimilarity> {
+        /// returns the fuzzy category of a given type, or None
+        /// if the type can be equated to any type.
+        fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
+            match t.kind() {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => Some(2),
+                ty::Int(..)
+                | ty::Uint(..)
+                | ty::Float(..)
+                | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Param(..) => Some(11),
+                ty::Alias(ty::Projection, ..) => Some(12),
+                ty::Alias(ty::Inherent, ..) => Some(13),
+                ty::Alias(ty::Opaque, ..) => Some(14),
+                ty::Alias(ty::Weak, ..) => Some(15),
+                ty::Never => Some(16),
+                ty::Adt(..) => Some(17),
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
+            }
+        }
+
+        let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> {
+            loop {
+                match t.kind() {
+                    ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => {
+                        t = *inner
+                    }
+                    _ => break t,
+                }
+            }
+        };
+
+        if !ignoring_lifetimes {
+            a = strip_references(a);
+            b = strip_references(b);
+        }
+
+        let cat_a = type_category(self.tcx, a)?;
+        let cat_b = type_category(self.tcx, b)?;
+        if a == b {
+            Some(CandidateSimilarity::Exact { ignoring_lifetimes })
+        } else if cat_a == cat_b {
+            match (a.kind(), b.kind()) {
+                (ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,
+                (ty::Foreign(def_a), ty::Foreign(def_b)) => def_a == def_b,
+                // Matching on references results in a lot of unhelpful
+                // suggestions, so let's just not do that for now.
+                //
+                // We still upgrade successful matches to `ignoring_lifetimes: true`
+                // to prioritize that impl.
+                (ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => {
+                    self.fuzzy_match_tys(a, b, true).is_some()
+                }
+                _ => true,
+            }
+            .then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes })
+        } else if ignoring_lifetimes {
+            None
+        } else {
+            self.fuzzy_match_tys(a, b, true)
+        }
+    }
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
+            hir::GeneratorKind::Gen => "a generator",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+        })
+    }
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> Vec<ImplCandidate<'tcx>> {
+        let mut candidates: Vec<_> = self
+            .tcx
+            .all_impls(trait_pred.def_id())
+            .filter_map(|def_id| {
+                if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
+                    || !self.tcx.is_user_visible_dep(def_id.krate)
+                {
+                    return None;
+                }
+
+                let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();
+
+                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
+                    |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
+                )
+            })
+            .collect();
+        if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
+            // If any of the candidates is a perfect match, we don't want to show all of them.
+            // This is particularly relevant for the case of numeric types (as they all have the
+            // same category).
+            candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
+        }
+        candidates
+    }
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: &[ImplCandidate<'tcx>],
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        body_def_id: LocalDefId,
+        err: &mut Diagnostic,
+        other: bool,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        // If we have a single implementation, try to unify it with the trait ref
+        // that failed. This should uncover a better hint for what *is* implemented.
+        if let [single] = &impl_candidates {
+            if self.probe(|_| {
+                let ocx = ObligationCtxt::new(self);
+                let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
+                let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
+                let impl_trait_ref = ocx.normalize(
+                    &ObligationCause::dummy(),
+                    param_env,
+                    ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
+                );
+
+                ocx.register_obligations(
+                    self.tcx
+                        .predicates_of(single.impl_def_id)
+                        .instantiate(self.tcx, impl_args)
+                        .into_iter()
+                        .map(|(clause, _)| {
+                            Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
+                        }),
+                );
+                if !ocx.select_where_possible().is_empty() {
+                    return false;
+                }
+
+                let mut terrs = vec![];
+                for (obligation_arg, impl_arg) in
+                    std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
+                {
+                    if let Err(terr) =
+                        ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
+                    {
+                        terrs.push(terr);
+                    }
+                    if !ocx.select_where_possible().is_empty() {
+                        return false;
+                    }
+                }
+
+                // Literally nothing unified, just give up.
+                if terrs.len() == impl_trait_ref.args.len() {
+                    return false;
+                }
+
+                let cand =
+                    self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
+                        tcx: self.tcx,
+                        ty_op: |ty| ty,
+                        lt_op: |lt| lt,
+                        ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
+                    });
+                err.highlighted_help(vec![
+                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
+                    ("is".to_string(), Style::Highlight),
+                    (" implemented for `".to_string(), Style::NoStyle),
+                    (cand.self_ty().to_string(), Style::Highlight),
+                    ("`".to_string(), Style::NoStyle),
+                ]);
+
+                if let [TypeError::Sorts(exp_found)] = &terrs[..] {
+                    let exp_found = self.resolve_vars_if_possible(*exp_found);
+                    err.help(format!(
+                        "for that trait implementation, expected `{}`, found `{}`",
+                        exp_found.expected, exp_found.found
+                    ));
+                }
+
+                true
+            }) {
+                return true;
+            }
+        }
+
+        let other = if other { "other " } else { "" };
+        let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
+            if candidates.is_empty() {
+                return false;
+            }
+            if let &[cand] = &candidates[..] {
+                let (desc, mention_castable) =
+                    match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
+                        (ty::FnPtr(_), ty::FnDef(..)) => {
+                            (" implemented for fn pointer `", ", cast using `as`")
+                        }
+                        (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""),
+                        _ => (" implemented for `", ""),
+                    };
+                err.highlighted_help(vec![
+                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
+                    ("is".to_string(), Style::Highlight),
+                    (desc.to_string(), Style::NoStyle),
+                    (cand.self_ty().to_string(), Style::Highlight),
+                    ("`".to_string(), Style::NoStyle),
+                    (mention_castable.to_string(), Style::NoStyle),
+                ]);
+                return true;
+            }
+            let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id);
+            // Check if the trait is the same in all cases. If so, we'll only show the type.
+            let mut traits: Vec<_> =
+                candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect();
+            traits.sort();
+            traits.dedup();
+            // FIXME: this could use a better heuristic, like just checking
+            // that args[1..] is the same.
+            let all_traits_equal = traits.len() == 1;
+
+            let candidates: Vec<String> = candidates
+                .into_iter()
+                .map(|c| {
+                    if all_traits_equal {
+                        format!("\n  {}", c.self_ty())
+                    } else {
+                        format!("\n  {c}")
+                    }
+                })
+                .collect();
+
+            let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
+            err.help(format!(
+                "the following {other}types implement trait `{}`:{}{}",
+                trait_ref.print_only_trait_path(),
+                candidates[..end].join(""),
+                if candidates.len() > 9 {
+                    format!("\nand {} others", candidates.len() - 8)
+                } else {
+                    String::new()
+                }
+            ));
+            true
+        };
+
+        let def_id = trait_ref.def_id();
+        if impl_candidates.is_empty() {
+            if self.tcx.trait_is_auto(def_id)
+                || self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
+                || self.tcx.get_diagnostic_name(def_id).is_some()
+            {
+                // Mentioning implementers of `Copy`, `Debug` and friends is not useful.
+                return false;
+            }
+            let mut impl_candidates: Vec<_> = self
+                .tcx
+                .all_impls(def_id)
+                // Ignore automatically derived impls and `!Trait` impls.
+                .filter(|&def_id| {
+                    self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
+                        || self.tcx.is_automatically_derived(def_id)
+                })
+                .filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
+                .map(ty::EarlyBinder::instantiate_identity)
+                .filter(|trait_ref| {
+                    let self_ty = trait_ref.self_ty();
+                    // Avoid mentioning type parameters.
+                    if let ty::Param(_) = self_ty.kind() {
+                        false
+                    }
+                    // Avoid mentioning types that are private to another crate
+                    else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
+                        // FIXME(compiler-errors): This could be generalized, both to
+                        // be more granular, and probably look past other `#[fundamental]`
+                        // types, too.
+                        self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
+                    } else {
+                        true
+                    }
+                })
+                .collect();
+
+            impl_candidates.sort();
+            impl_candidates.dedup();
+            return report(impl_candidates, err);
+        }
+
+        // Sort impl candidates so that ordering is consistent for UI tests.
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
+        //
+        // Prefer more similar candidates first, then sort lexicographically
+        // by their normalized string representation.
+        let mut impl_candidates: Vec<_> = impl_candidates
+            .iter()
+            .cloned()
+            .map(|mut cand| {
+                // Fold the consts so that they shows up as, e.g., `10`
+                // instead of `core::::array::{impl#30}::{constant#0}`.
+                cand.trait_ref = cand.trait_ref.fold_with(&mut BottomUpFolder {
+                    tcx: self.tcx,
+                    ty_op: |ty| ty,
+                    lt_op: |lt| lt,
+                    ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
+                });
+                cand
+            })
+            .collect();
+        impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
+        let mut impl_candidates: Vec<_> =
+            impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
+        impl_candidates.dedup();
+
+        report(impl_candidates, err)
+    }
+
+    fn report_similar_impl_candidates_for_root_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
+        body_def_id: LocalDefId,
+        err: &mut Diagnostic,
+    ) {
+        // This is *almost* equivalent to
+        // `obligation.cause.code().peel_derives()`, but it gives us the
+        // trait predicate for that corresponding root obligation. This
+        // lets us get a derived obligation from a type parameter, like
+        // when calling `string.strip_suffix(p)` where `p` is *not* an
+        // implementer of `Pattern<'_>`.
+        let mut code = obligation.cause.code();
+        let mut trait_pred = trait_predicate;
+        let mut peeled = false;
+        while let Some((parent_code, parent_trait_pred)) = code.parent() {
+            code = parent_code;
+            if let Some(parent_trait_pred) = parent_trait_pred {
+                trait_pred = parent_trait_pred;
+                peeled = true;
+            }
+        }
+        let def_id = trait_pred.def_id();
+        // Mention *all* the `impl`s for the *top most* obligation, the
+        // user might have meant to use one of them, if any found. We skip
+        // auto-traits or fundamental traits that might not be exactly what
+        // the user might expect to be presented with. Instead this is
+        // useful for less general traits.
+        if peeled
+            && !self.tcx.trait_is_auto(def_id)
+            && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
+        {
+            let trait_ref = trait_pred.to_poly_trait_ref();
+            let impl_candidates = self.find_similar_impl_candidates(trait_pred);
+            self.report_similar_impl_candidates(
+                &impl_candidates,
+                trait_ref,
+                body_def_id,
+                err,
+                true,
+                obligation.param_env,
+            );
+        }
+    }
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
+        match code {
+            ObligationCauseCode::BuiltinDerivedObligation(data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
+                match self.get_parent_trait_ref(&data.parent_code) {
+                    Some(t) => Some(t),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span = TyCategory::from_ty(self.tcx, ty)
+                            .map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
+                }
+            }
+            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
+                self.get_parent_trait_ref(&parent_code)
+            }
+            _ => None,
+        }
+    }
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut Diagnostic,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) -> bool {
+        let get_trait_impls = |trait_def_id| {
+            let mut trait_impls = vec![];
+            self.tcx.for_each_relevant_impl(
+                trait_def_id,
+                trait_ref.skip_binder().self_ty(),
+                |impl_def_id| {
+                    trait_impls.push(impl_def_id);
+                },
+            );
+            trait_impls
+        };
+
+        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
+        let traits_with_same_path: std::collections::BTreeSet<_> = self
+            .tcx
+            .all_traits()
+            .filter(|trait_def_id| *trait_def_id != trait_ref.def_id())
+            .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path)
+            .collect();
+        let mut suggested = false;
+        for trait_with_same_path in traits_with_same_path {
+            let trait_impls = get_trait_impls(trait_with_same_path);
+            if trait_impls.is_empty() {
+                continue;
+            }
+            let impl_spans: Vec<_> =
+                trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
+            err.span_help(
+                impl_spans,
+                format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
+            );
+            let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+            let crate_msg =
+                format!("perhaps two different versions of crate `{trait_crate}` are being used?");
+            err.note(crate_msg);
+            suggested = true;
+        }
+        suggested
+    }
+
+    fn mk_trait_obligation_with_new_self_ty(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
+    ) -> PredicateObligation<'tcx> {
+        let trait_pred =
+            trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty));
+
+        Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
+        // Unable to successfully determine, probably means
+        // insufficient type information, but could mean
+        // ambiguous impls. The latter *ought* to be a
+        // coherence violation, so we don't report it here.
+
+        let predicate = self.resolve_vars_if_possible(obligation.predicate);
+        let span = obligation.cause.span;
+
+        debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
+
+        // Ambiguity errors are often caused as fallout from earlier errors.
+        // We ignore them if this `infcx` is tainted in some cases below.
+
+        let bound_predicate = predicate.kind();
+        let mut err = match bound_predicate.skip_binder() {
+            ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
+                let trait_ref = bound_predicate.rebind(data.trait_ref);
+                debug!(?trait_ref);
+
+                if predicate.references_error() {
+                    return;
+                }
+
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized". It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
+                // avoid inundating the user with unnecessary errors, but we now
+                // check upstream for type errors and don't add the obligations to
+                // begin with in those cases.
+                if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
+                    if let None = self.tainted_by_errors() {
+                        self.emit_inference_failure_err(
+                            obligation.cause.body_id,
+                            span,
+                            trait_ref.self_ty().skip_binder().into(),
+                            ErrorCode::E0282,
+                            false,
+                        )
+                        .emit();
+                    }
+                    return;
+                }
+
+                // Typically, this ambiguity should only happen if
+                // there are unresolved type inference variables
+                // (otherwise it would suggest a coherence
+                // failure). But given #21974 that is not necessarily
+                // the case -- we can have multiple where clauses that
+                // are only distinguished by a region, which results
+                // in an ambiguity even when all types are fully
+                // known, since we don't dispatch based on region
+                // relationships.
+
+                // Pick the first substitution that still contains inference variables as the one
+                // we're going to emit an error for. If there are none (see above), fall back to
+                // a more general error.
+                let subst = data.trait_ref.args.iter().find(|s| s.has_non_region_infer());
+
+                let mut err = if let Some(subst) = subst {
+                    self.emit_inference_failure_err(
+                        obligation.cause.body_id,
+                        span,
+                        subst,
+                        ErrorCode::E0283,
+                        true,
+                    )
+                } else {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        span,
+                        E0283,
+                        "type annotations needed: cannot satisfy `{}`",
+                        predicate,
+                    )
+                };
+
+                let mut ambiguities = ambiguity::recompute_applicable_impls(
+                    self.infcx,
+                    &obligation.with(self.tcx, trait_ref),
+                );
+                let has_non_region_infer =
+                    trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
+                // It doesn't make sense to talk about applicable impls if there are more than a
+                // handful of them. If there are a lot of them, but only a few of them have no type
+                // params, we only show those, as they are more likely to be useful/intended.
+                if ambiguities.len() > 5 {
+                    let infcx = self.infcx;
+                    if !ambiguities.iter().all(|option| match option {
+                        DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(),
+                        ParamEnv(_) => true,
+                    }) {
+                        // If not all are blanket impls, we filter blanked impls out.
+                        ambiguities.retain(|option| match option {
+                            DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(),
+                            ParamEnv(_) => true,
+                        });
+                    }
+                }
+                if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
+                    if self.tainted_by_errors().is_some() && subst.is_none() {
+                        // If `subst.is_none()`, then this is probably two param-env
+                        // candidates or impl candidates that are equal modulo lifetimes.
+                        // Therefore, if we've already emitted an error, just skip this
+                        // one, since it's not particularly actionable.
+                        err.cancel();
+                        return;
+                    }
+                    self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
+                } else {
+                    if self.tainted_by_errors().is_some() {
+                        err.cancel();
+                        return;
+                    }
+                    err.note(format!("cannot satisfy `{predicate}`"));
+                    let impl_candidates = self
+                        .find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
+                    if impl_candidates.len() < 40 {
+                        self.report_similar_impl_candidates(
+                            impl_candidates.as_slice(),
+                            trait_ref,
+                            obligation.cause.body_id,
+                            &mut err,
+                            false,
+                            obligation.param_env,
+                        );
+                    }
+                }
+
+                if let ObligationCauseCode::ItemObligation(def_id)
+                | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
+                {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                }
+
+                if let Some(ty::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
+                    && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
+                {
+                    let mut expr_finder = FindExprBySpan::new(span);
+                    expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
+
+                    if let Some(hir::Expr {
+                        kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. }
+                    ) = expr_finder.result
+                        && let [
+                            ..,
+                            trait_path_segment @ hir::PathSegment {
+                                res: Res::Def(DefKind::Trait, trait_id),
+                                ..
+                            },
+                            hir::PathSegment {
+                                ident: assoc_item_name,
+                                res: Res::Def(_, item_id),
+                                ..
+                            }
+                        ] = path.segments
+                        && data.trait_ref.def_id == *trait_id
+                        && self.tcx.trait_of_item(*item_id) == Some(*trait_id)
+                        && let None = self.tainted_by_errors()
+                    {
+                        let (verb, noun) = match self.tcx.associated_item(item_id).kind {
+                            ty::AssocKind::Const => ("refer to the", "constant"),
+                            ty::AssocKind::Fn => ("call", "function"),
+                            // This is already covered by E0223, but this following single match
+                            // arm doesn't hurt here.
+                            ty::AssocKind::Type => ("refer to the", "type"),
+                        };
+
+                        // Replace the more general E0283 with a more specific error
+                        err.cancel();
+                        err = self.tcx.sess.struct_span_err_with_code(
+                            span,
+                            format!(
+                                "cannot {verb} associated {noun} on trait without specifying the \
+                                 corresponding `impl` type",
+                            ),
+                            rustc_errors::error_code!(E0790),
+                        );
+
+                        if let Some(local_def_id) = data.trait_ref.def_id.as_local()
+                            && let Some(hir::Node::Item(hir::Item {
+                                ident: trait_name,
+                                kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs),
+                                ..
+                            })) = self.tcx.hir().find_by_def_id(local_def_id)
+                            && let Some(method_ref) = trait_item_refs
+                                .iter()
+                                .find(|item_ref| item_ref.ident == *assoc_item_name)
+                        {
+                            err.span_label(
+                                method_ref.span,
+                                format!("`{trait_name}::{assoc_item_name}` defined here"),
+                            );
+                        }
+
+                        err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
+
+                        let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
+
+                        if let Some(impl_def_id) =
+                            trait_impls.non_blanket_impls().values().flatten().next()
+                        {
+                            let non_blanket_impl_count =
+                                trait_impls.non_blanket_impls().values().flatten().count();
+                            // If there is only one implementation of the trait, suggest using it.
+                            // Otherwise, use a placeholder comment for the implementation.
+                            let (message, self_type) = if non_blanket_impl_count == 1 {
+                                (
+                                    "use the fully-qualified path to the only available \
+                                     implementation",
+                                    format!(
+                                        "{}",
+                                        self.tcx.type_of(impl_def_id).instantiate_identity()
+                                    ),
+                                )
+                            } else {
+                                (
+                                    "use a fully-qualified path to a specific available \
+                                     implementation",
+                                    "/* self type */".to_string(),
+                                )
+                            };
+                            let mut suggestions = vec![(
+                                path.span.shrink_to_lo(),
+                                format!("<{self_type} as "),
+                            )];
+                            if let Some(generic_arg) = trait_path_segment.args {
+                                let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
+                                // get rid of :: between Trait and <type>
+                                // must be '::' between them, otherwise the parser won't accept the code
+                                suggestions.push((between_span, "".to_string(),));
+                                suggestions.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
+                            } else {
+                                suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), ">".to_string()));
+                            }
+                            err.multipart_suggestion(
+                                message,
+                                suggestions,
+                                Applicability::MaybeIncorrect
+                            );
+                        }
+                    }
+                };
+
+                err
+            }
+
+            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+                // Same hacky approach as above to avoid deluging user
+                // with error messages.
+                if arg.references_error()
+                    || self.tcx.sess.has_errors().is_some()
+                    || self.tainted_by_errors().is_some()
+                {
+                    return;
+                }
+
+                self.emit_inference_failure_err(
+                    obligation.cause.body_id,
+                    span,
+                    arg,
+                    ErrorCode::E0282,
+                    false,
+                )
+            }
+
+            ty::PredicateKind::Subtype(data) => {
+                if data.references_error()
+                    || self.tcx.sess.has_errors().is_some()
+                    || self.tainted_by_errors().is_some()
+                {
+                    // no need to overload user in such cases
+                    return;
+                }
+                let SubtypePredicate { a_is_expected: _, a, b } = data;
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.emit_inference_failure_err(
+                    obligation.cause.body_id,
+                    span,
+                    a.into(),
+                    ErrorCode::E0282,
+                    true,
+                )
+            }
+            ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
+                if predicate.references_error() || self.tainted_by_errors().is_some() {
+                    return;
+                }
+                let subst = data
+                    .projection_ty
+                    .args
+                    .iter()
+                    .chain(Some(data.term.into_arg()))
+                    .find(|g| g.has_non_region_infer());
+                if let Some(subst) = subst {
+                    let mut err = self.emit_inference_failure_err(
+                        obligation.cause.body_id,
+                        span,
+                        subst,
+                        ErrorCode::E0284,
+                        true,
+                    );
+                    err.note(format!("cannot satisfy `{predicate}`"));
+                    err
+                } else {
+                    // If we can't find a substitution, just print a generic error
+                    let mut err = struct_span_err!(
+                        self.tcx.sess,
+                        span,
+                        E0284,
+                        "type annotations needed: cannot satisfy `{}`",
+                        predicate,
+                    );
+                    err.span_label(span, format!("cannot satisfy `{predicate}`"));
+                    err
+                }
+            }
+
+            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
+                if predicate.references_error() || self.tainted_by_errors().is_some() {
+                    return;
+                }
+                let subst = data.walk().find(|g| g.is_non_region_infer());
+                if let Some(subst) = subst {
+                    let err = self.emit_inference_failure_err(
+                        obligation.cause.body_id,
+                        span,
+                        subst,
+                        ErrorCode::E0284,
+                        true,
+                    );
+                    err
+                } else {
+                    // If we can't find a substitution, just print a generic error
+                    let mut err = struct_span_err!(
+                        self.tcx.sess,
+                        span,
+                        E0284,
+                        "type annotations needed: cannot satisfy `{}`",
+                        predicate,
+                    );
+                    err.span_label(span, format!("cannot satisfy `{predicate}`"));
+                    err
+                }
+            }
+            _ => {
+                if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() {
+                    return;
+                }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot satisfy `{}`",
+                    predicate,
+                );
+                err.span_label(span, format!("cannot satisfy `{predicate}`"));
+                err
+            }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
+    }
+
+    fn annotate_source_of_ambiguity(
+        &self,
+        err: &mut Diagnostic,
+        ambiguities: &[ambiguity::Ambiguity],
+        predicate: ty::Predicate<'tcx>,
+    ) {
+        let mut spans = vec![];
+        let mut crates = vec![];
+        let mut post = vec![];
+        let mut has_param_env = false;
+        for ambiguity in ambiguities {
+            match ambiguity {
+                ambiguity::Ambiguity::DefId(impl_def_id) => {
+                    match self.tcx.span_of_impl(*impl_def_id) {
+                        Ok(span) => spans.push(span),
+                        Err(name) => {
+                            crates.push(name);
+                            if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
+                                post.push(header);
+                            }
+                        }
+                    }
+                }
+                ambiguity::Ambiguity::ParamEnv(span) => {
+                    has_param_env = true;
+                    spans.push(*span);
+                }
+            }
+        }
+        let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{n}`")).collect();
+        crate_names.sort();
+        crate_names.dedup();
+        post.sort();
+        post.dedup();
+
+        if self.tainted_by_errors().is_some()
+            && (crate_names.len() == 1
+                && spans.len() == 0
+                && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
+                || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
+        {
+            // Avoid complaining about other inference issues for expressions like
+            // `42 >> 1`, where the types are still `{integer}`, but we want to
+            // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too?
+            // NOTE(eddyb) this was `.cancel()`, but `err`
+            // is borrowed, so we can't fully defuse it.
+            err.downgrade_to_delayed_bug();
+            return;
+        }
+
+        let msg = format!(
+            "multiple `impl`s{} satisfying `{}` found",
+            if has_param_env { " or `where` clauses" } else { "" },
+            predicate
+        );
+        let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
+            format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::<Vec<_>>().join("\n"),)
+        } else if post.len() == 1 {
+            format!(": `{}`", post[0])
+        } else {
+            String::new()
+        };
+
+        match (spans.len(), crates.len(), crate_names.len()) {
+            (0, 0, 0) => {
+                err.note(format!("cannot satisfy `{predicate}`"));
+            }
+            (0, _, 1) => {
+                err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,));
+            }
+            (0, _, _) => {
+                err.note(format!(
+                    "{} in the following crates: {}{}",
+                    msg,
+                    crate_names.join(", "),
+                    post,
+                ));
+            }
+            (_, 0, 0) => {
+                let span: MultiSpan = spans.into();
+                err.span_note(span, msg);
+            }
+            (_, 1, 1) => {
+                let span: MultiSpan = spans.into();
+                err.span_note(span, msg);
+                err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,));
+            }
+            _ => {
+                let span: MultiSpan = spans.into();
+                err.span_note(span, msg);
+                err.note(format!(
+                    "and more `impl`s found in the following crates: {}{}",
+                    crate_names.join(", "),
+                    post,
+                ));
+            }
+        }
+    }
+
+    /// Returns `true` if the trait predicate may apply for *some* assignment
+    /// to the type parameters.
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> bool {
+        struct ParamToVarFolder<'a, 'tcx> {
+            infcx: &'a InferCtxt<'tcx>,
+            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        }
+
+        impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ParamToVarFolder<'a, 'tcx> {
+            fn interner(&self) -> TyCtxt<'tcx> {
+                self.infcx.tcx
+            }
+
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+                if let ty::Param(_) = *ty.kind() {
+                    let infcx = self.infcx;
+                    *self.var_map.entry(ty).or_insert_with(|| {
+                        infcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::MiscVariable,
+                            span: DUMMY_SP,
+                        })
+                    })
+                } else {
+                    ty.super_fold_with(self)
+                }
+            }
+        }
+
+        self.probe(|_| {
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+
+            let InferOk { value: cleaned_pred, .. } =
+                self.infcx.at(&ObligationCause::dummy(), param_env).normalize(cleaned_pred);
+
+            let obligation =
+                Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
+
+            self.predicate_may_hold(&obligation)
+        })
+    }
+
+    fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>) {
+        // First, attempt to add note to this error with an async-await-specific
+        // message, and fall back to regular note otherwise.
+        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            self.note_obligation_cause_code(
+                obligation.cause.body_id,
+                err,
+                obligation.predicate,
+                obligation.param_env,
+                obligation.cause.code(),
+                &mut vec![],
+                &mut Default::default(),
+            );
+            self.suggest_unsized_bound_if_applicable(err, obligation);
+        }
+    }
+
+    #[instrument(level = "debug", skip_all)]
+    fn suggest_unsized_bound_if_applicable(
+        &self,
+        err: &mut Diagnostic,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
+            obligation.predicate.kind().skip_binder()
+        else {
+            return;
+        };
+        let (ObligationCauseCode::BindingObligation(item_def_id, span)
+        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) =
+            *obligation.cause.code().peel_derives()
+        else {
+            return;
+        };
+        debug!(?pred, ?item_def_id, ?span);
+
+        let (Some(node), true) = (
+            self.tcx.hir().get_if_local(item_def_id),
+            Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
+        ) else {
+            return;
+        };
+        self.maybe_suggest_unsized_generics(err, span, node);
+    }
+
+    #[instrument(level = "debug", skip_all)]
+    fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>) {
+        let Some(generics) = node.generics() else {
+            return;
+        };
+        let sized_trait = self.tcx.lang_items().sized_trait();
+        debug!(?generics.params);
+        debug!(?generics.predicates);
+        let Some(param) = generics.params.iter().find(|param| param.span == span) else {
+            return;
+        };
+        // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
+        // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
+        let explicitly_sized = generics
+            .bounds_for_param(param.def_id)
+            .flat_map(|bp| bp.bounds)
+            .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
+        if explicitly_sized {
+            return;
+        }
+        debug!(?param);
+        match node {
+            hir::Node::Item(
+                item @ hir::Item {
+                    // Only suggest indirection for uses of type parameters in ADTs.
+                    kind:
+                        hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
+                    ..
+                },
+            ) => {
+                if self.maybe_indirection_for_unsized(err, item, param) {
+                    return;
+                }
+            }
+            _ => {}
+        };
+        // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
+        let (span, separator) = if let Some(s) = generics.bounds_span_for_suggestions(param.def_id)
+        {
+            (s, " +")
+        } else {
+            (span.shrink_to_hi(), ":")
+        };
+        err.span_suggestion_verbose(
+            span,
+            "consider relaxing the implicit `Sized` restriction",
+            format!("{separator} ?Sized"),
+            Applicability::MachineApplicable,
+        );
+    }
+
+    fn maybe_indirection_for_unsized(
+        &self,
+        err: &mut Diagnostic,
+        item: &Item<'tcx>,
+        param: &GenericParam<'tcx>,
+    ) -> bool {
+        // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
+        // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
+        // is not. Look for invalid "bare" parameter uses, and suggest using indirection.
+        let mut visitor =
+            FindTypeParam { param: param.name.ident().name, invalid_spans: vec![], nested: false };
+        visitor.visit_item(item);
+        if visitor.invalid_spans.is_empty() {
+            return false;
+        }
+        let mut multispan: MultiSpan = param.span.into();
+        multispan.push_span_label(
+            param.span,
+            format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
+        );
+        for sp in visitor.invalid_spans {
+            multispan.push_span_label(
+                sp,
+                format!("...if indirection were used here: `Box<{}>`", param.name.ident()),
+            );
+        }
+        err.span_help(
+            multispan,
+            format!(
+                "you could relax the implicit `Sized` bound on `{T}` if it were \
+                used through indirection like `&{T}` or `Box<{T}>`",
+                T = param.name.ident(),
+            ),
+        );
+        true
+    }
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<Ty<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool {
+        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+            let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
+            let self_ty = parent_trait_ref.skip_binder().self_ty();
+            if obligated_types.iter().any(|ot| ot == &self_ty) {
+                return true;
+            }
+            if let ty::Adt(def, args) = self_ty.kind()
+                && let [arg] = &args[..]
+                && let ty::GenericArgKind::Type(ty) = arg.unpack()
+                && let ty::Adt(inner_def, _) = ty.kind()
+                && inner_def == def
+            {
+                return true;
+            }
+        }
+        false
+    }
+
+    fn get_standard_error_message(
+        &self,
+        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        message: Option<String>,
+        predicate_is_const: bool,
+        append_const_msg: Option<AppendConstMessage>,
+        post_message: String,
+    ) -> String {
+        message
+            .and_then(|cannot_do_this| {
+                match (predicate_is_const, append_const_msg) {
+                    // do nothing if predicate is not const
+                    (false, _) => Some(cannot_do_this),
+                    // suggested using default post message
+                    (true, Some(AppendConstMessage::Default)) => {
+                        Some(format!("{cannot_do_this} in const contexts"))
+                    }
+                    // overridden post message
+                    (true, Some(AppendConstMessage::Custom(custom_msg))) => {
+                        Some(format!("{cannot_do_this}{custom_msg}"))
+                    }
+                    // fallback to generic message
+                    (true, None) => None,
+                }
+            })
+            .unwrap_or_else(|| {
+                format!("the trait bound `{trait_predicate}` is not satisfied{post_message}")
+            })
+    }
+
+    fn get_safe_transmute_error_and_reason(
+        &self,
+        obligation: PredicateObligation<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        span: Span,
+    ) -> GetSafeTransmuteErrorAndReason {
+        use rustc_transmute::Answer;
+
+        // Erase regions because layout code doesn't particularly care about regions.
+        let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
+
+        let src_and_dst = rustc_transmute::Types {
+            dst: trait_ref.args.type_at(0),
+            src: trait_ref.args.type_at(1),
+        };
+        let scope = trait_ref.args.type_at(2);
+        let Some(assume) = rustc_transmute::Assume::from_const(
+            self.infcx.tcx,
+            obligation.param_env,
+            trait_ref.args.const_at(3),
+        ) else {
+            span_bug!(
+                span,
+                "Unable to construct rustc_transmute::Assume where it was previously possible"
+            );
+        };
+
+        match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
+            obligation.cause,
+            src_and_dst,
+            scope,
+            assume,
+        ) {
+            Answer::No(reason) => {
+                let dst = trait_ref.args.type_at(0);
+                let src = trait_ref.args.type_at(1);
+                let err_msg = format!(
+                    "`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
+                );
+                let safe_transmute_explanation = match reason {
+                    rustc_transmute::Reason::SrcIsUnspecified => {
+                        format!("`{src}` does not have a well-specified layout")
+                    }
+
+                    rustc_transmute::Reason::DstIsUnspecified => {
+                        format!("`{dst}` does not have a well-specified layout")
+                    }
+
+                    rustc_transmute::Reason::DstIsBitIncompatible => {
+                        format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`")
+                    }
+
+                    rustc_transmute::Reason::DstIsPrivate => format!(
+                        "`{dst}` is or contains a type or field that is not visible in that scope"
+                    ),
+                    rustc_transmute::Reason::DstIsTooBig => {
+                        format!("The size of `{src}` is smaller than the size of `{dst}`")
+                    }
+                    rustc_transmute::Reason::SrcSizeOverflow => {
+                        format!(
+                            "values of the type `{src}` are too big for the current architecture"
+                        )
+                    }
+                    rustc_transmute::Reason::DstSizeOverflow => {
+                        format!(
+                            "values of the type `{dst}` are too big for the current architecture"
+                        )
+                    }
+                    rustc_transmute::Reason::DstHasStricterAlignment {
+                        src_min_align,
+                        dst_min_align,
+                    } => {
+                        format!(
+                            "The minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})"
+                        )
+                    }
+                    rustc_transmute::Reason::DstIsMoreUnique => {
+                        format!("`{src}` is a shared reference, but `{dst}` is a unique reference")
+                    }
+                    // Already reported by rustc
+                    rustc_transmute::Reason::TypeError => {
+                        return GetSafeTransmuteErrorAndReason::Silent;
+                    }
+                    rustc_transmute::Reason::SrcLayoutUnknown => {
+                        format!("`{src}` has an unknown layout")
+                    }
+                    rustc_transmute::Reason::DstLayoutUnknown => {
+                        format!("`{dst}` has an unknown layout")
+                    }
+                };
+                GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation }
+            }
+            // Should never get a Yes at this point! We already ran it before, and did not get a Yes.
+            Answer::Yes => span_bug!(
+                span,
+                "Inconsistent rustc_transmute::is_transmutable(...) result, got Yes",
+            ),
+            other => span_bug!(span, "Unsupported rustc_transmute::Answer variant: `{other:?}`"),
+        }
+    }
+
+    fn add_tuple_trait_message(
+        &self,
+        obligation_cause_code: &ObligationCauseCode<'tcx>,
+        err: &mut Diagnostic,
+    ) {
+        match obligation_cause_code {
+            ObligationCauseCode::RustCall => {
+                err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
+            }
+            ObligationCauseCode::BindingObligation(def_id, _)
+            | ObligationCauseCode::ItemObligation(def_id)
+                if self.tcx.is_fn_trait(*def_id) =>
+            {
+                err.code(rustc_errors::error_code!(E0059));
+                err.set_primary_message(format!(
+                    "type parameter to bare `{}` trait must be a tuple",
+                    self.tcx.def_path_str(*def_id)
+                ));
+            }
+            _ => {}
+        }
+    }
+
+    fn try_to_add_help_message(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        err: &mut Diagnostic,
+        span: Span,
+        is_fn_trait: bool,
+        suggested: bool,
+        unsatisfied_const: bool,
+    ) {
+        let body_def_id = obligation.cause.body_id;
+        let span = if let ObligationCauseCode::BinOp { rhs_span: Some(rhs_span), .. } =
+            obligation.cause.code()
+        {
+            *rhs_span
+        } else {
+            span
+        };
+
+        // Try to report a help message
+        if is_fn_trait
+            && let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
+                obligation.param_env,
+                trait_ref.self_ty(),
+                trait_predicate.skip_binder().polarity,
+            )
+        {
+            self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params);
+        } else if !trait_ref.has_non_region_infer()
+            && self.predicate_can_apply(obligation.param_env, *trait_predicate)
+        {
+            // If a where-clause may be useful, remind the
+            // user that they can add it.
+            //
+            // don't display an on-unimplemented note, as
+            // these notes will often be of the form
+            //     "the type `T` can't be frobnicated"
+            // which is somewhat confusing.
+            self.suggest_restricting_param_bound(
+                err,
+                *trait_predicate,
+                None,
+                obligation.cause.body_id,
+            );
+        } else if trait_ref.def_id().is_local()
+            && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty()
+            && !self.tcx.trait_is_auto(trait_ref.def_id())
+            && !self.tcx.trait_is_alias(trait_ref.def_id())
+        {
+            err.span_help(
+                self.tcx.def_span(trait_ref.def_id()),
+                crate::fluent_generated::trait_selection_trait_has_no_impls,
+            );
+        } else if !suggested && !unsatisfied_const {
+            // Can't show anything else useful, try to find similar impls.
+            let impl_candidates = self.find_similar_impl_candidates(*trait_predicate);
+            if !self.report_similar_impl_candidates(
+                &impl_candidates,
+                trait_ref,
+                body_def_id,
+                err,
+                true,
+                obligation.param_env,
+            ) {
+                self.report_similar_impl_candidates_for_root_obligation(
+                    &obligation,
+                    *trait_predicate,
+                    body_def_id,
+                    err,
+                );
+            }
+
+            self.suggest_convert_to_slice(
+                err,
+                obligation,
+                trait_ref,
+                impl_candidates.as_slice(),
+                span,
+            );
+        }
+    }
+
+    fn add_help_message_for_fn_trait(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        err: &mut Diagnostic,
+        implemented_kind: ty::ClosureKind,
+        params: ty::Binder<'tcx, Ty<'tcx>>,
+    ) {
+        // If the type implements `Fn`, `FnMut`, or `FnOnce`, suppress the following
+        // suggestion to add trait bounds for the type, since we only typically implement
+        // these traits once.
+
+        // Note if the `FnMut` or `FnOnce` is less general than the trait we're trying
+        // to implement.
+        let selected_kind = self
+            .tcx
+            .fn_trait_kind_from_def_id(trait_ref.def_id())
+            .expect("expected to map DefId to ClosureKind");
+        if !implemented_kind.extends(selected_kind) {
+            err.note(format!(
+                "`{}` implements `{}`, but it must implement `{}`, which is more general",
+                trait_ref.skip_binder().self_ty(),
+                implemented_kind,
+                selected_kind
+            ));
+        }
+
+        // Note any argument mismatches
+        let given_ty = params.skip_binder();
+        let expected_ty = trait_ref.skip_binder().args.type_at(1);
+        if let ty::Tuple(given) = given_ty.kind()
+            && let ty::Tuple(expected) = expected_ty.kind()
+        {
+            if expected.len() != given.len() {
+                // Note number of types that were expected and given
+                err.note(
+                    format!(
+                        "expected a closure taking {} argument{}, but one taking {} argument{} was given",
+                        given.len(),
+                        pluralize!(given.len()),
+                        expected.len(),
+                        pluralize!(expected.len()),
+                    )
+                );
+            } else if !self.same_type_modulo_infer(given_ty, expected_ty) {
+                // Print type mismatch
+                let (expected_args, given_args) =
+                    self.cmp(given_ty, expected_ty);
+                err.note_expected_found(
+                    &"a closure with arguments",
+                    expected_args,
+                    &"a closure with arguments",
+                    given_args,
+                );
+            }
+        }
+    }
+
+    fn maybe_add_note_for_unsatisfied_const(
+        &self,
+        _obligation: &PredicateObligation<'tcx>,
+        _trait_ref: ty::PolyTraitRef<'tcx>,
+        _trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        _err: &mut Diagnostic,
+        _span: Span,
+    ) -> UnsatisfiedConst {
+        let unsatisfied_const = UnsatisfiedConst(false);
+        // FIXME(effects)
+        unsatisfied_const
+    }
+
+    fn report_closure_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        closure_def_id: DefId,
+        found_kind: ty::ClosureKind,
+        kind: ty::ClosureKind,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        let closure_span = self.tcx.def_span(closure_def_id);
+
+        let mut err = ClosureKindMismatch {
+            closure_span,
+            expected: kind,
+            found: found_kind,
+            cause_span: obligation.cause.span,
+            fn_once_label: None,
+            fn_mut_label: None,
+        };
+
+        // Additional context information explaining why the closure only implements
+        // a particular trait.
+        if let Some(typeck_results) = &self.typeck_results {
+            let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+            match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
+                (ty::ClosureKind::FnOnce, Some((span, place))) => {
+                    err.fn_once_label = Some(ClosureFnOnceLabel {
+                        span: *span,
+                        place: ty::place_to_string_for_capture(self.tcx, &place),
+                    })
+                }
+                (ty::ClosureKind::FnMut, Some((span, place))) => {
+                    err.fn_mut_label = Some(ClosureFnMutLabel {
+                        span: *span,
+                        place: ty::place_to_string_for_capture(self.tcx, &place),
+                    })
+                }
+                _ => {}
+            }
+        }
+
+        self.tcx.sess.create_err(err)
+    }
+
+    fn report_type_parameter_mismatch_cyclic_type_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        terr: TypeError<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        let self_ty = found_trait_ref.self_ty().skip_binder();
+        let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() {
+            (
+                ObligationCause::dummy_with_span(self.tcx.def_span(def_id)),
+                TypeError::CyclicTy(self_ty),
+            )
+        } else {
+            (obligation.cause.clone(), terr)
+        };
+        self.report_and_explain_type_error(
+            TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
+            terr,
+        )
+    }
+
+    fn report_opaque_type_auto_trait_leakage(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        def_id: DefId,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
+            hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
+                "opaque type".to_string()
+            }
+            hir::OpaqueTyOrigin::TyAlias { .. } => {
+                format!("`{}`", self.tcx.def_path_debug_str(def_id))
+            }
+        };
+        let mut err = self.tcx.sess.struct_span_err(
+            obligation.cause.span,
+            format!("cannot check whether the hidden type of {name} satisfies auto traits"),
+        );
+        err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
+        match self.defining_use_anchor {
+            DefiningAnchor::Bubble | DefiningAnchor::Error => {}
+            DefiningAnchor::Bind(bind) => {
+                err.span_note(
+                    self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
+                    "this item depends on auto traits of the hidden type, \
+                    but may also be registering the hidden type. \
+                    This is not supported right now. \
+                    You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
+                );
+            }
+        };
+        err
+    }
+
+    fn report_type_parameter_mismatch_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        span: Span,
+        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref);
+        let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref);
+
+        if expected_trait_ref.self_ty().references_error() {
+            return None;
+        }
+
+        let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else {
+            return None;
+        };
+
+        let found_did = match *found_trait_ty.kind() {
+            ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Generator(did, ..) => {
+                Some(did)
+            }
+            ty::Adt(def, _) => Some(def.did()),
+            _ => None,
+        };
+
+        let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
+        let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
+
+        if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
+            // We check closures twice, with obligations flowing in different directions,
+            // but we want to complain about them only once.
+            return None;
+        }
+
+        self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
+
+        let mut not_tupled = false;
+
+        let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
+            ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
+            _ => {
+                not_tupled = true;
+                vec![ArgKind::empty()]
+            }
+        };
+
+        let expected_ty = expected_trait_ref.skip_binder().args.type_at(1);
+        let expected = match expected_ty.kind() {
+            ty::Tuple(ref tys) => {
+                tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect()
+            }
+            _ => {
+                not_tupled = true;
+                vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())]
+            }
+        };
+
+        // If this is a `Fn` family trait and either the expected or found
+        // is not tupled, then fall back to just a regular mismatch error.
+        // This shouldn't be common unless manually implementing one of the
+        // traits manually, but don't make it more confusing when it does
+        // happen.
+        Some(
+            if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().gen_trait() && not_tupled
+            {
+                self.report_and_explain_type_error(
+                    TypeTrace::poly_trait_refs(
+                        &obligation.cause,
+                        true,
+                        expected_trait_ref,
+                        found_trait_ref,
+                    ),
+                    ty::error::TypeError::Mismatch,
+                )
+            } else if found.len() == expected.len() {
+                self.report_closure_arg_mismatch(
+                    span,
+                    found_span,
+                    found_trait_ref,
+                    expected_trait_ref,
+                    obligation.cause.code(),
+                    found_node,
+                    obligation.param_env,
+                )
+            } else {
+                let (closure_span, closure_arg_span, found) = found_did
+                    .and_then(|did| {
+                        let node = self.tcx.hir().get_if_local(did)?;
+                        let (found_span, closure_arg_span, found) =
+                            self.get_fn_like_arguments(node)?;
+                        Some((Some(found_span), closure_arg_span, found))
+                    })
+                    .unwrap_or((found_span, None, found));
+
+                self.report_arg_count_mismatch(
+                    span,
+                    closure_span,
+                    expected,
+                    found,
+                    found_trait_ty.is_closure(),
+                    closure_arg_span,
+                )
+            },
+        )
+    }
+
+    fn report_not_const_evaluatable_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        span: Span,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        if !self.tcx.features().generic_const_exprs {
+            let mut err = self
+                .tcx
+                .sess
+                .struct_span_err(span, "constant expression depends on a generic parameter");
+            // FIXME(const_generics): we should suggest to the user how they can resolve this
+            // issue. However, this is currently not actually possible
+            // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
+            //
+            // Note that with `feature(generic_const_exprs)` this case should not
+            // be reachable.
+            err.note("this may fail depending on what value the parameter takes");
+            err.emit();
+            return None;
+        }
+
+        match obligation.predicate.kind().skip_binder() {
+            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
+                let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
+                    bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
+                };
+                let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
+                let const_span = self.tcx.def_span(uv.def);
+                match self.tcx.sess.source_map().span_to_snippet(const_span) {
+                    Ok(snippet) => err.help(format!(
+                        "try adding a `where` bound using this expression: `where [(); {snippet}]:`"
+                    )),
+                    _ => err.help("consider adding a `where` bound using this expression"),
+                };
+                Some(err)
+            }
+            _ => {
+                span_bug!(
+                    span,
+                    "unexpected non-ConstEvaluatable predicate, this should not be reachable"
+                )
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 956f8e047d7..ab81d77a268 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -204,7 +204,7 @@ fn do_normalize_predicates<'tcx>(
     let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
         Ok(predicates) => predicates,
         Err(errors) => {
-            let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+            let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
             return Err(reported);
         }
     };
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 6c49e94dc31..4b559632017 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -9,7 +9,7 @@ extern crate tracing;
 pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
 
 pub mod layout;
-pub(crate) mod maybe_transmutable;
+mod maybe_transmutable;
 
 #[derive(Default)]
 pub struct Assume {
@@ -19,7 +19,7 @@ pub struct Assume {
     pub validity: bool,
 }
 
-/// Either we have an error, transmutation is allowed, or we have an optional
+/// Either transmutation is allowed, we have an error, or we have an optional
 /// Condition that must hold.
 #[derive(Debug, Hash, Eq, PartialEq, Clone)]
 pub enum Answer<R> {
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
index c0141f1f841..bf3c390c800 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
@@ -32,26 +32,6 @@ where
     ) -> Self {
         Self { src, dst, scope, assume, context }
     }
-
-    // FIXME(bryangarza): Delete this when all usages are removed
-    pub(crate) fn map_layouts<F, M>(
-        self,
-        f: F,
-    ) -> Result<MaybeTransmutableQuery<M, C>, Answer<<C as QueryContext>::Ref>>
-    where
-        F: FnOnce(
-            L,
-            L,
-            <C as QueryContext>::Scope,
-            &C,
-        ) -> Result<(M, M), Answer<<C as QueryContext>::Ref>>,
-    {
-        let Self { src, dst, scope, assume, context } = self;
-
-        let (src, dst) = f(src, dst, scope, &context)?;
-
-        Ok(MaybeTransmutableQuery { src, dst, scope, assume, context })
-    }
 }
 
 // FIXME: Nix this cfg, so we can write unit tests independently of rustc
@@ -107,42 +87,42 @@ where
     #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))]
     pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
         let assume_visibility = self.assume.safety;
-        // FIXME(bryangarza): Refactor this code to get rid of `map_layouts`
-        let query_or_answer = self.map_layouts(|src, dst, scope, context| {
-            // Remove all `Def` nodes from `src`, without checking their visibility.
-            let src = src.prune(&|def| true);
 
-            trace!(?src, "pruned src");
+        let Self { src, dst, scope, assume, context } = self;
 
-            // Remove all `Def` nodes from `dst`, additionally...
-            let dst = if assume_visibility {
-                // ...if visibility is assumed, don't check their visibility.
-                dst.prune(&|def| true)
-            } else {
-                // ...otherwise, prune away all unreachable paths through the `Dst` layout.
-                dst.prune(&|def| context.is_accessible_from(def, scope))
-            };
+        // Remove all `Def` nodes from `src`, without checking their visibility.
+        let src = src.prune(&|def| true);
 
-            trace!(?dst, "pruned dst");
+        trace!(?src, "pruned src");
 
-            // Convert `src` from a tree-based representation to an NFA-based representation.
-            // If the conversion fails because `src` is uninhabited, conclude that the transmutation
-            // is acceptable, because instances of the `src` type do not exist.
-            let src = Nfa::from_tree(src).map_err(|Uninhabited| Answer::Yes)?;
+        // Remove all `Def` nodes from `dst`, additionally...
+        let dst = if assume_visibility {
+            // ...if visibility is assumed, don't check their visibility.
+            dst.prune(&|def| true)
+        } else {
+            // ...otherwise, prune away all unreachable paths through the `Dst` layout.
+            dst.prune(&|def| context.is_accessible_from(def, scope))
+        };
 
-            // Convert `dst` from a tree-based representation to an NFA-based representation.
-            // If the conversion fails because `src` is uninhabited, conclude that the transmutation
-            // is unacceptable, because instances of the `dst` type do not exist.
-            let dst =
-                Nfa::from_tree(dst).map_err(|Uninhabited| Answer::No(Reason::DstIsPrivate))?;
+        trace!(?dst, "pruned dst");
 
-            Ok((src, dst))
-        });
+        // Convert `src` from a tree-based representation to an NFA-based representation.
+        // If the conversion fails because `src` is uninhabited, conclude that the transmutation
+        // is acceptable, because instances of the `src` type do not exist.
+        let src = match Nfa::from_tree(src) {
+            Ok(src) => src,
+            Err(Uninhabited) => return Answer::Yes,
+        };
 
-        match query_or_answer {
-            Ok(query) => query.answer(),
-            Err(answer) => answer,
-        }
+        // Convert `dst` from a tree-based representation to an NFA-based representation.
+        // If the conversion fails because `src` is uninhabited, conclude that the transmutation
+        // is unacceptable, because instances of the `dst` type do not exist.
+        let dst = match Nfa::from_tree(dst) {
+            Ok(dst) => dst,
+            Err(Uninhabited) => return Answer::No(Reason::DstIsPrivate),
+        };
+
+        MaybeTransmutableQuery { src, dst, scope, assume, context }.answer()
     }
 }
 
@@ -156,14 +136,10 @@ where
     #[inline(always)]
     #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))]
     pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
-        // FIXME(bryangarza): Refactor this code to get rid of `map_layouts`
-        let query_or_answer = self
-            .map_layouts(|src, dst, scope, context| Ok((Dfa::from_nfa(src), Dfa::from_nfa(dst))));
-
-        match query_or_answer {
-            Ok(query) => query.answer(),
-            Err(answer) => answer,
-        }
+        let Self { src, dst, scope, assume, context } = self;
+        let src = Dfa::from_nfa(src);
+        let dst = Dfa::from_nfa(dst);
+        MaybeTransmutableQuery { src, dst, scope, assume, context }.answer()
     }
 }
 
@@ -171,26 +147,8 @@ impl<C> MaybeTransmutableQuery<Dfa<<C as QueryContext>::Ref>, C>
 where
     C: QueryContext,
 {
-    /// Answers whether a `Nfa` is transmutable into another `Nfa`.
-    ///
-    /// This method converts `src` and `dst` to DFAs, then computes an answer using those DFAs.
+    /// Answers whether a `Dfa` is transmutable into another `Dfa`.
     pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
-        MaybeTransmutableQuery {
-            src: &self.src,
-            dst: &self.dst,
-            scope: self.scope,
-            assume: self.assume,
-            context: self.context,
-        }
-        .answer()
-    }
-}
-
-impl<'l, C> MaybeTransmutableQuery<&'l Dfa<<C as QueryContext>::Ref>, C>
-where
-    C: QueryContext,
-{
-    pub(crate) fn answer(&mut self) -> Answer<<C as QueryContext>::Ref> {
         self.answer_memo(&mut Map::default(), self.src.start, self.dst.start)
     }
 
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 9e4fdcda06e..fc8d19d1a58 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -479,6 +479,46 @@ pub trait Into<T>: Sized {
 /// - `From<T> for U` implies [`Into`]`<U> for T`
 /// - `From` is reflexive, which means that `From<T> for T` is implemented
 ///
+/// # When to implement `From`
+///
+/// While there's no technical restrictions on which conversions can be done using
+/// a `From` implementation, the general expectation is that the conversions
+/// should typically be restricted as follows:
+///
+/// * The conversion is *infallible*: if the conversion can fail, use [`TryFrom`]
+///   instead; don't provide a `From` impl that panics.
+///
+/// * The conversion is *lossless*: semantically, it should not lose or discard
+///   information. For example, `i32: From<u16>` exists, where the original
+///   value can be recovered using `u16: TryFrom<i32>`.  And `String: From<&str>`
+///   exists, where you can get something equivalent to the original value via
+///   `Deref`.  But `From` cannot be used to convert from `u32` to `u16`, since
+///   that cannot succeed in a lossless way.  (There's some wiggle room here for
+///   information not considered semantically relevant.  For example,
+///   `Box<[T]>: From<Vec<T>>` exists even though it might not preserve capacity,
+///   like how two vectors can be equal despite differing capacities.)
+///
+/// * The conversion is *value-preserving*: the conceptual kind and meaning of
+///   the resulting value is the same, even though the Rust type and technical
+///   representation might be different.  For example `-1_i8 as u8` is *lossless*,
+///   since `as` casting back can recover the original value, but that conversion
+///   is *not* available via `From` because `-1` and `255` are different conceptual
+///   values (despite being identical bit patterns technically).  But
+///   `f32: From<i16>` *is* available because `1_i16` and `1.0_f32` are conceptually
+///   the same real number (despite having very different bit patterns technically).
+///   `String: From<char>` is available because they're both *text*, but
+///   `String: From<u32>` is *not* available, since `1` (a number) and `"1"`
+///   (text) are too different.  (Converting values to text is instead covered
+///   by the [`Display`](crate::fmt::Display) trait.)
+///
+/// * The conversion is *obvious*: it's the only reasonable conversion between
+///   the two types.  Otherwise it's better to have it be a named method or
+///   constructor, like how [`str::as_bytes`] is a method and how integers have
+///   methods like [`u32::from_ne_bytes`], [`u32::from_le_bytes`], and
+///   [`u32::from_be_bytes`], none of which are `From` implementations.  Whereas
+///   there's only one reasonable way to wrap an [`Ipv6Addr`](crate::net::Ipv6Addr)
+///   into an [`IpAddr`](crate::net::IpAddr), thus `IpAddr: From<Ipv6Addr>` exists.
+///
 /// # Examples
 ///
 /// [`String`] implements `From<&str>`:
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 9899014e85a..bdaeea66622 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1475,7 +1475,7 @@ impl<T> Option<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or(self, optb: Option<T>) -> Option<T> {
         match self {
-            Some(x) => Some(x),
+            x @ Some(_) => x,
             None => optb,
         }
     }
@@ -1500,7 +1500,7 @@ impl<T> Option<T> {
         F: FnOnce() -> Option<T>,
     {
         match self {
-            Some(x) => Some(x),
+            x @ Some(_) => x,
             None => f(),
         }
     }
@@ -1530,8 +1530,8 @@ impl<T> Option<T> {
     #[stable(feature = "option_xor", since = "1.37.0")]
     pub fn xor(self, optb: Option<T>) -> Option<T> {
         match (self, optb) {
-            (Some(a), None) => Some(a),
-            (None, Some(b)) => Some(b),
+            (a @ Some(_), None) => a,
+            (None, b @ Some(_)) => b,
             _ => None,
         }
     }
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 965132bdedb..feb6274d029 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -36,6 +36,10 @@ object = { version = "0.32.0", default-features = false, optional = true, featur
 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
 rand_xorshift = "0.3.0"
 
+[build-dependencies]
+# Dependency of the `backtrace` crate's build script
+cc = "1.0.67"
+
 [target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
 
diff --git a/library/std/build.rs b/library/std/build.rs
index 36516978b7a..164bca7c436 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -1,5 +1,11 @@
 use std::env;
 
+// backtrace-rs requires a feature check on Android targets, so
+// we need to run its build.rs as well.
+#[allow(unused_extern_crates)]
+#[path = "../backtrace/build.rs"]
+mod backtrace_build_rs;
+
 fn main() {
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
@@ -58,4 +64,6 @@ fn main() {
     }
     println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
     println!("cargo:rustc-cfg=backtrace_in_libstd");
+
+    backtrace_build_rs::main();
 }
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 8c46080e43b..2bb4f3f9e03 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -125,7 +125,7 @@ impl Once {
     ///
     /// # Panics
     ///
-    /// The closure `f` will only be executed once if this is called
+    /// The closure `f` will only be executed once even if this is called
     /// concurrently amongst many threads. If that closure panics, however, then
     /// it will *poison* this [`Once`] instance, causing all future invocations of
     /// `call_once` to also panic.
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index e9d19766592..4a732a2cabd 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -67,7 +67,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
 // workaround below is to register, via _tlv_atexit, a custom DTOR list once per
 // thread. thread_local dtors are pushed to the DTOR list without calling
 // _tlv_atexit.
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     use crate::cell::Cell;
     use crate::mem;
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 8c9ab1e2402..fef25ad8635 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,101 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[37f4c172...master](https://github.com/rust-lang/rust-clippy/compare/37f4c172...master)
+[1e8fdf49...master](https://github.com/rust-lang/rust-clippy/compare/1e8fdf49...master)
+
+## Rust 1.73
+
+Current stable, released 2023-10-05
+
+[View all 103 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-07-02T12%3A24%3A40Z..2023-08-11T11%3A09%3A56Z+base%3Amaster)
+
+### New Lints
+
+* [`impossible_comparisons`]
+  [#10843](https://github.com/rust-lang/rust-clippy/pull/10843)
+* [`redundant_comparisons`]
+  [#10843](https://github.com/rust-lang/rust-clippy/pull/10843)
+* [`ignored_unit_patterns`]
+  [#11242](https://github.com/rust-lang/rust-clippy/pull/11242)
+* [`readonly_write_lock`]
+  [#11210](https://github.com/rust-lang/rust-clippy/pull/11210)
+* [`filter_map_bool_then`]
+  [#11115](https://github.com/rust-lang/rust-clippy/pull/11115)
+* [`needless_return_with_question_mark`]
+  [#11031](https://github.com/rust-lang/rust-clippy/pull/11031)
+* [`redundant_guards`]
+  [#10955](https://github.com/rust-lang/rust-clippy/pull/10955)
+* [`redundant_locals`]
+  [#10885](https://github.com/rust-lang/rust-clippy/pull/10885)
+* [`absolute_paths`]
+  [#11003](https://github.com/rust-lang/rust-clippy/pull/11003)
+* [`error_impl_error`]
+  [#11107](https://github.com/rust-lang/rust-clippy/pull/11107)
+* [`iter_skip_zero`]
+  [#11046](https://github.com/rust-lang/rust-clippy/pull/11046)
+* [`string_lit_chars_any`]
+  [#11052](https://github.com/rust-lang/rust-clippy/pull/11052)
+* [`four_forward_slashes`]
+  [#11140](https://github.com/rust-lang/rust-clippy/pull/11140)
+* [`format_collect`]
+  [#11116](https://github.com/rust-lang/rust-clippy/pull/11116)
+* [`needless_pass_by_ref_mut`]
+  [#10900](https://github.com/rust-lang/rust-clippy/pull/10900)
+* [`manual_is_infinite`]
+  [#11049](https://github.com/rust-lang/rust-clippy/pull/11049)
+* [`manual_is_finite`]
+  [#11049](https://github.com/rust-lang/rust-clippy/pull/11049)
+* [`incorrect_partial_ord_impl_on_ord_type`]
+  [#10788](https://github.com/rust-lang/rust-clippy/pull/10788)
+* [`read_line_without_trim`]
+  [#10970](https://github.com/rust-lang/rust-clippy/pull/10970)
+* [`type_id_on_box`]
+  [#10987](https://github.com/rust-lang/rust-clippy/pull/10987)
+
+### Moves and Deprecations
+
+* Renamed `unwrap_or_else_default` to [`unwrap_or_default`]
+  [#10120](https://github.com/rust-lang/rust-clippy/pull/10120)
+* Moved [`tuple_array_conversions`] to `pedantic` (Now allow-by-default)
+  [#11146](https://github.com/rust-lang/rust-clippy/pull/11146)
+* Moved [`arc_with_non_send_sync`] to `suspicious` (Now warn-by-default)
+  [#11104](https://github.com/rust-lang/rust-clippy/pull/11104)
+* Moved [`needless_raw_string_hashes`] to `pedantic` (Now allow-by-default)
+  [#11415](https://github.com/rust-lang/rust-clippy/pull/11415)
+
+### Enhancements
+
+* [`unwrap_used`]: No longer lints on the never-type or never-like enums
+  [#11252](https://github.com/rust-lang/rust-clippy/pull/11252)
+* [`expect_used`]: No longer lints on the never-type or never-like enums
+  [#11252](https://github.com/rust-lang/rust-clippy/pull/11252)
+
+### False Positive Fixes
+
+* [`panic_in_result_fn`]: No longer triggers on `todo!`, `unimplemented!`, `unreachable!`
+  [#11123](https://github.com/rust-lang/rust-clippy/pull/11123)
+
+### Suggestion Fixes/Improvements
+
+* [`semicolon_if_nothing_returned`]: The suggestion is now machine-applicable with rustfix
+  [#11083](https://github.com/rust-lang/rust-clippy/pull/11083)
+
+### ICE Fixes
+
+* [`filter_map_bool_then`]: No longer crashes on late-bound regions
+  [#11318](https://github.com/rust-lang/rust-clippy/pull/11318)
+* [`unwrap_or_default`]: No longer crashes on alias types for local items
+  [#11258](https://github.com/rust-lang/rust-clippy/pull/11258)
+* [`unnecessary_literal_unwrap`]: No longer crashes on `None.unwrap_or_default()`
+  [#11106](https://github.com/rust-lang/rust-clippy/pull/11106)
+* Fixed MIR-related ICE
+  [#11130](https://github.com/rust-lang/rust-clippy/pull/11130)
+* [`missing_fields_in_debug`]: No longer crashes on non-ADT self types
+  [#11069](https://github.com/rust-lang/rust-clippy/pull/11069)
 
 ## Rust 1.72
 
-Current stable, released 2023-08-24
+Released 2023-08-24
 
 [View all 131 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-05-22T14%3A53%3A59Z..2023-07-01T22%3A57%3A20Z+base%3Amaster)
 
@@ -5011,6 +5101,7 @@ Released 2018-09-13
 [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
 [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
 [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
+[`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_without_iter
 [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering
 [`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage
 [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref
@@ -5036,6 +5127,7 @@ Released 2018-09-13
 [`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
 [`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero
 [`iter_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_with_drain
+[`iter_without_into_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_without_into_iter
 [`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero
 [`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits
 [`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays
@@ -5072,6 +5164,7 @@ Released 2018-09-13
 [`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
 [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
 [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten
+[`manual_hash_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one
 [`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed
 [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
 [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 66786004f6e..cbcb42dad79 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.74"
+version = "0.1.75"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -25,6 +25,8 @@ clippy_lints = { path = "clippy_lints" }
 rustc_tools_util = "0.3.0"
 tempfile = { version = "3.2", optional = true }
 termize = "0.1"
+color-print = "0.3.4" # Sync version with Cargo
+anstream = "0.5.0"
 
 [dev-dependencies]
 ui_test = "0.20"
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index f6f0c95c729..e001197842b 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -261,7 +261,7 @@ impl EarlyLintPass for FooFunctions {}
 [declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
 [example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
 [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
-[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+[category_level_mapping]: ../index.html
 
 ## Lint registration
 
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index b980083f1f5..2c958ccbbc2 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -151,6 +151,7 @@ The minimum rust version that the project supports
 * [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
 * [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions)
 * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold)
+* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one)
 
 
 ## `cognitive-complexity-threshold`
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index e64cf2c8749..be2386bb1d2 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -58,7 +58,7 @@ pub fn create(
     };
 
     create_lint(&lint, msrv).context("Unable to create lint implementation")?;
-    create_test(&lint).context("Unable to create a test for the new lint")?;
+    create_test(&lint, msrv).context("Unable to create a test for the new lint")?;
 
     if lint.ty.is_none() {
         add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?;
@@ -88,15 +88,21 @@ fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
     }
 }
 
-fn create_test(lint: &LintData<'_>) -> io::Result<()> {
-    fn create_project_layout<P: Into<PathBuf>>(lint_name: &str, location: P, case: &str, hint: &str) -> io::Result<()> {
+fn create_test(lint: &LintData<'_>, msrv: bool) -> io::Result<()> {
+    fn create_project_layout<P: Into<PathBuf>>(
+        lint_name: &str,
+        location: P,
+        case: &str,
+        hint: &str,
+        msrv: bool,
+    ) -> io::Result<()> {
         let mut path = location.into().join(case);
         fs::create_dir(&path)?;
         write_file(path.join("Cargo.toml"), get_manifest_contents(lint_name, hint))?;
 
         path.push("src");
         fs::create_dir(&path)?;
-        write_file(path.join("main.rs"), get_test_file_contents(lint_name))?;
+        write_file(path.join("main.rs"), get_test_file_contents(lint_name, msrv))?;
 
         Ok(())
     }
@@ -106,13 +112,25 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
         let test_dir = lint.project_root.join(&relative_test_dir);
         fs::create_dir(&test_dir)?;
 
-        create_project_layout(lint.name, &test_dir, "fail", "Content that triggers the lint goes here")?;
-        create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint")?;
+        create_project_layout(
+            lint.name,
+            &test_dir,
+            "fail",
+            "Content that triggers the lint goes here",
+            msrv,
+        )?;
+        create_project_layout(
+            lint.name,
+            &test_dir,
+            "pass",
+            "This file should not trigger the lint",
+            false,
+        )?;
 
         println!("Generated test directories: `{relative_test_dir}/pass`, `{relative_test_dir}/fail`");
     } else {
         let test_path = format!("tests/ui/{}.rs", lint.name);
-        let test_contents = get_test_file_contents(lint.name);
+        let test_contents = get_test_file_contents(lint.name, msrv);
         write_file(lint.project_root.join(&test_path), test_contents)?;
 
         println!("Generated test file: `{test_path}`");
@@ -194,8 +212,8 @@ pub(crate) fn get_stabilization_version() -> String {
     parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`")
 }
 
-fn get_test_file_contents(lint_name: &str) -> String {
-    formatdoc!(
+fn get_test_file_contents(lint_name: &str, msrv: bool) -> String {
+    let mut test = formatdoc!(
         r#"
         #![warn(clippy::{lint_name})]
 
@@ -203,7 +221,29 @@ fn get_test_file_contents(lint_name: &str) -> String {
             // test code goes here
         }}
     "#
-    )
+    );
+
+    if msrv {
+        let _ = writedoc!(
+            test,
+            r#"
+
+                // TODO: set xx to the version one below the MSRV used by the lint, and yy to
+                // the version used by the lint
+                #[clippy::msrv = "1.xx"]
+                fn msrv_1_xx() {{
+                    // a simple example that would trigger the lint if the MSRV were met
+                }}
+
+                #[clippy::msrv = "1.yy"]
+                fn msrv_1_yy() {{
+                    // the same example as above
+                }}
+            "#
+        );
+    }
+
+    test
 }
 
 fn get_manifest_contents(lint_name: &str, hint: &str) -> String {
@@ -258,7 +298,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
         )
     });
 
-    let _: fmt::Result = write!(result, "{}", get_lint_declaration(&name_upper, category));
+    let _: fmt::Result = writeln!(result, "{}", get_lint_declaration(&name_upper, category));
 
     result.push_str(&if enable_msrv {
         formatdoc!(
@@ -281,7 +321,6 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
             }}
 
             // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
-            // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
             // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
         "#
         )
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index dcd9a4adcbd..4d5b3bf8a94 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.74"
+version = "0.1.75"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -28,6 +28,9 @@ semver = "1.0"
 rustc-semver = "1.1"
 url = "2.2"
 
+[dev-dependencies]
+walkdir = "2.3"
+
 [features]
 deny-warnings = ["clippy_utils/deny-warnings"]
 # build clippy with internal lints enabled, off by default
diff --git a/src/tools/clippy/clippy_lints/src/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/allow_attributes.rs
index e1ef514edfd..e3f4cf79d31 100644
--- a/src/tools/clippy/clippy_lints/src/allow_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/allow_attributes.rs
@@ -8,6 +8,7 @@ use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
+    /// ### What it does
     /// Checks for usage of the `#[allow]` attribute and suggests replacing it with
     /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
     ///
@@ -19,7 +20,6 @@ declare_clippy_lint! {
     /// (`#![allow]`) are usually used to enable or disable lints on a global scale.
     ///
     /// ### Why is this bad?
-    ///
     /// `#[expect]` attributes suppress the lint emission, but emit a warning, if
     /// the expectation is unfulfilled. This can be useful to be notified when the
     /// lint is no longer triggered.
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 0546807bac4..db01ddbde04 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -183,7 +183,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for empty lines after documenation comments.
+    /// Checks for empty lines after documentation comments.
     ///
     /// ### Why is this bad?
     /// The documentation comment was most likely meant to be an inner attribute or regular comment.
@@ -795,7 +795,7 @@ impl EarlyLintPass for EarlyAttributes {
 
 /// Check for empty lines after outer attributes.
 ///
-/// Attributes and documenation comments are both considered outer attributes
+/// Attributes and documentation comments are both considered outer attributes
 /// by the AST. However, the average user likely considers them to be different.
 /// Checking for empty lines after each of these attributes is split into two different
 /// lints but can share the same logic.
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 4d1281ec1e7..481c44031cf 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -229,6 +229,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
     crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
     crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
+    crate::iter_without_into_iter::INTO_ITER_WITHOUT_ITER_INFO,
+    crate::iter_without_into_iter::ITER_WITHOUT_INTO_ITER_INFO,
     crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO,
     crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO,
     crate::large_futures::LARGE_FUTURES_INFO,
@@ -280,6 +282,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::manual_clamp::MANUAL_CLAMP_INFO,
     crate::manual_float_methods::MANUAL_IS_FINITE_INFO,
     crate::manual_float_methods::MANUAL_IS_INFINITE_INFO,
+    crate::manual_hash_one::MANUAL_HASH_ONE_INFO,
     crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO,
     crate::manual_let_else::MANUAL_LET_ELSE_INFO,
     crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index 3f60e5a7c4d..646767868e2 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -1,7 +1,7 @@
 //! lint on C-like enums that are `repr(isize/usize)` and have values that
 //! don't fit into an `i32`
 
-use clippy_utils::consts::{miri_to_const, Constant};
+use clippy_utils::consts::{mir_to_const, Constant};
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
                         .const_eval_poly(def_id.to_def_id())
                         .ok()
                         .map(|val| rustc_middle::mir::Const::from_value(val, ty));
-                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
+                    if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx, c)) {
                         if let ty::Adt(adt, _) = ty.kind() {
                             if adt.is_enum() {
                                 ty = adt.repr().discr_type().to_ty(cx.tcx);
diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs
index f24577c7382..6d429fbd035 100644
--- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs
+++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs
@@ -27,7 +27,7 @@ declare_clippy_lint! {
     ///
     /// impl std::error::Error for Error { ... }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub ERROR_IMPL_ERROR,
     restriction,
     "exported types named `Error` that implement `Error`"
diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
index 419c7734344..0ec52f89e71 100644
--- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
+++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
@@ -28,7 +28,7 @@ declare_clippy_lint! {
     ///     // ...
     /// }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub FOUR_FORWARD_SLASHES,
     suspicious,
     "comments with 4 forward slashes (`////`) likely intended to be doc comments (`///`)"
diff --git a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
index d8ead1c9d9f..ef2a66d4a20 100644
--- a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
@@ -37,6 +37,10 @@ declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]);
 
 impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
+        if pat.span.from_expansion() {
+            return;
+        }
+
         match cx.tcx.hir().get_parent(pat.hir_id) {
             Node::Param(param) if matches!(cx.tcx.hir().get_parent(param.hir_id), Node::Item(_)) => {
                 // Ignore function parameters
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 64a4a3fa741..2b2ea156cd4 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -6,9 +6,8 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
 use rustc_hir_analysis::hir_ty_to_ty;
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{Ty, TypeckResults};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -162,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                     vis.visit_ty(ty);
 
                     for target in &vis.found {
-                        if in_external_macro(cx.sess(), generics.span) {
+                        if generics.span.from_expansion() {
                             continue;
                         }
                         let generics_suggestion_span = generics.span.substitute_dummy({
diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
index 55a43e91562..41477242bcc 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
@@ -1,10 +1,12 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{is_from_proc_macro, is_in_cfg_test};
-use rustc_hir::{HirId, ItemId, ItemKind, Mod};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
+use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro};
+use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_hir::{HirId, Item, ItemKind, Mod};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{sym, Span};
+use rustc_span::hygiene::AstPass;
+use rustc_span::{sym, ExpnKind};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -41,46 +43,72 @@ declare_clippy_lint! {
 
 declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]);
 
-impl LateLintPass<'_> for ItemsAfterTestModule {
-    fn check_mod(&mut self, cx: &LateContext<'_>, _: &Mod<'_>, _: HirId) {
-        let mut was_test_mod_visited = false;
-        let mut test_mod_span: Option<Span> = None;
+fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
+    if let ItemKind::Mod(test_mod) = item.kind
+        && item.span.hi() == test_mod.spans.inner_span.hi()
+        && is_cfg_test(cx.tcx, item.hir_id())
+        && !item.span.from_expansion()
+        && !is_from_proc_macro(cx, item)
+    {
+        true
+    } else {
+        false
+    }
+}
 
-        let hir = cx.tcx.hir();
-        let items = hir.items().collect::<Vec<ItemId>>();
+impl LateLintPass<'_> for ItemsAfterTestModule {
+    fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: HirId) {
+        let mut items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id));
 
-        for (i, itid) in items.iter().enumerate() {
-            let item = hir.item(*itid);
+        let Some((mod_pos, test_mod)) = items.by_ref().enumerate().find(|(_, item)| cfg_test_module(cx, item)) else {
+            return;
+        };
 
-            if_chain! {
-            if was_test_mod_visited;
-            if i == (items.len() - 3 /* Weird magic number (HIR-translation behaviour) */);
-            if cx.sess().source_map().lookup_char_pos(item.span.lo()).file.name_hash
-            == cx.sess().source_map().lookup_char_pos(test_mod_span.unwrap().lo()).file.name_hash; // Will never fail
-            if !matches!(item.kind, ItemKind::Mod(_));
-            if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself
-            if !in_external_macro(cx.sess(), item.span);
-            if !is_from_proc_macro(cx, item);
+        let after: Vec<_> = items
+            .filter(|item| {
+                // Ignore the generated test main function
+                !(item.ident.name == sym::main
+                    && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness))
+            })
+            .collect();
 
-            then {
-                span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined");
-            }};
+        if let Some(last) = after.last()
+            && after.iter().all(|&item| {
+                !matches!(item.kind, ItemKind::Mod(_))
+                    && !item.span.from_expansion()
+                    && !is_from_proc_macro(cx, item)
+            })
+            && !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id()))
+        {
+            let def_spans: Vec<_> = std::iter::once(test_mod.owner_id)
+                .chain(after.iter().map(|item| item.owner_id))
+                .map(|id| cx.tcx.def_span(id))
+                .collect();
 
-            if let ItemKind::Mod(module) = item.kind && item.span.hi() == module.spans.inner_span.hi() {
-			// Check that it works the same way, the only I way I've found for #10713
-				for attr in cx.tcx.get_attrs(item.owner_id.to_def_id(), sym::cfg) {
-					if_chain! {
-						if attr.has_name(sym::cfg);
-                        if let Some(mitems) = attr.meta_item_list();
-                        if let [mitem] = &*mitems;
-                        if mitem.has_name(sym::test);
-                        then {
-							was_test_mod_visited = true;
-                            test_mod_span = Some(item.span);
-                        }
+            span_lint_hir_and_then(
+                cx,
+                ITEMS_AFTER_TEST_MODULE,
+                test_mod.hir_id(),
+                def_spans,
+                "items after a test module",
+                |diag| {
+                    if let Some(prev) = mod_pos.checked_sub(1)
+                        && let prev = cx.tcx.hir().item(module.item_ids[prev])
+                        && let items_span = last.span.with_lo(test_mod.span.hi())
+                        && let Some(items) = snippet_opt(cx, items_span)
+                    {
+                        diag.multipart_suggestion_with_style(
+                            "move the items to before the test module was defined",
+                            vec![
+                                (prev.span.shrink_to_hi(), items),
+                                (items_span, String::new())
+                            ],
+                            Applicability::MachineApplicable,
+                            SuggestionStyle::HideCodeAlways,
+                        );
                     }
-                }
-			}
+                },
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
new file mode 100644
index 00000000000..43e1b92c9b9
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -0,0 +1,249 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::get_parent_as_impl;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::{implements_trait, make_normalized_projection};
+use rustc_ast::Mutability;
+use rustc_errors::Applicability;
+use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{sym, Symbol};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Looks for `iter` and `iter_mut` methods without an associated `IntoIterator for (&|&mut) Type` implementation.
+    ///
+    /// ### Why is this bad?
+    /// It's not bad, but having them is idiomatic and allows the type to be used in for loops directly
+    /// (`for val in &iter {}`), without having to first call `iter()` or `iter_mut()`.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct MySlice<'a>(&'a [u8]);
+    /// impl<'a> MySlice<'a> {
+    ///     pub fn iter(&self) -> std::slice::Iter<'a, u8> {
+    ///         self.0.iter()
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct MySlice<'a>(&'a [u8]);
+    /// impl<'a> MySlice<'a> {
+    ///     pub fn iter(&self) -> std::slice::Iter<'a, u8> {
+    ///         self.0.iter()
+    ///     }
+    /// }
+    /// impl<'a> IntoIterator for &MySlice<'a> {
+    ///     type Item = &'a u8;
+    ///     type IntoIter = std::slice::Iter<'a, u8>;
+    ///     fn into_iter(self) -> Self::IntoIter {
+    ///         self.iter()
+    ///     }
+    /// }
+    /// ```
+    #[clippy::version = "1.74.0"]
+    pub ITER_WITHOUT_INTO_ITER,
+    pedantic,
+    "implementing `iter(_mut)` without an associated `IntoIterator for (&|&mut) Type` impl"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// This is the opposite of the `iter_without_into_iter` lint.
+    /// It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method.
+    ///
+    /// ### Why is this bad?
+    /// It's not bad, but having them is idiomatic and allows the type to be used in iterator chains
+    /// by just calling `.iter()`, instead of the more awkward `<&Type>::into_iter` or `(&val).iter()` syntax
+    /// in case of ambiguity with another `Intoiterator` impl.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct MySlice<'a>(&'a [u8]);
+    /// impl<'a> IntoIterator for &MySlice<'a> {
+    ///     type Item = &'a u8;
+    ///     type IntoIter = std::slice::Iter<'a, u8>;
+    ///     fn into_iter(self) -> Self::IntoIter {
+    ///         self.0.iter()
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct MySlice<'a>(&'a [u8]);
+    /// impl<'a> MySlice<'a> {
+    ///     pub fn iter(&self) -> std::slice::Iter<'a, u8> {
+    ///         self.into_iter()
+    ///     }
+    /// }
+    /// impl<'a> IntoIterator for &MySlice<'a> {
+    ///     type Item = &'a u8;
+    ///     type IntoIter = std::slice::Iter<'a, u8>;
+    ///     fn into_iter(self) -> Self::IntoIter {
+    ///         self.0.iter()
+    ///     }
+    /// }
+    /// ```
+    #[clippy::version = "1.74.0"]
+    pub INTO_ITER_WITHOUT_ITER,
+    pedantic,
+    "implementing `IntoIterator for (&|&mut) Type` without an inherent `iter(_mut)` method"
+}
+
+declare_lint_pass!(IterWithoutIntoIter => [ITER_WITHOUT_INTO_ITER, INTO_ITER_WITHOUT_ITER]);
+
+/// Checks if a given type is nameable in a trait (impl).
+/// RPIT is stable, but impl Trait in traits is not (yet), so when we have
+/// a function such as `fn iter(&self) -> impl IntoIterator`, we can't
+/// suggest `type IntoIter = impl IntoIterator`.
+fn is_nameable_in_impl_trait(ty: &rustc_hir::Ty<'_>) -> bool {
+    !matches!(ty.kind, TyKind::OpaqueDef(..))
+}
+
+fn type_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
+    if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
+        cx.tcx.inherent_impls(ty_did).iter().any(|&did| {
+            cx.tcx
+                .associated_items(did)
+                .filter_by_name_unhygienic(method_name)
+                .next()
+                .is_some_and(|item| item.kind == ty::AssocKind::Fn)
+        })
+    } else {
+        false
+    }
+}
+
+impl LateLintPass<'_> for IterWithoutIntoIter {
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
+        if let ItemKind::Impl(imp) = item.kind
+            && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind
+            && let Some(trait_ref) = imp.of_trait
+            && trait_ref.trait_def_id().is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did))
+            && let &ty::Ref(_, ty, mtbl) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
+            && let expected_method_name = match mtbl {
+                Mutability::Mut => sym::iter_mut,
+                Mutability::Not => sym::iter,
+            }
+            && !type_has_inherent_method(cx, ty, expected_method_name)
+            && let Some(iter_assoc_span) = imp.items.iter().find_map(|item| {
+                if item.ident.name == sym!(IntoIter) {
+                    Some(cx.tcx.hir().impl_item(item.id).expect_type().span)
+                } else {
+                    None
+                }
+            })
+        {
+            span_lint_and_then(
+                cx,
+                INTO_ITER_WITHOUT_ITER,
+                item.span,
+                &format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"),
+                |diag| {
+                    // The suggestion forwards to the `IntoIterator` impl and uses a form of UFCS
+                    // to avoid name ambiguities, as there might be an inherent into_iter method
+                    // that we don't want to call.
+                    let sugg = format!(
+"
+impl {self_ty_without_ref} {{
+    fn {expected_method_name}({ref_self}self) -> {iter_ty} {{
+        <{ref_self}Self as IntoIterator>::into_iter(self)
+    }}
+}}
+",
+                        self_ty_without_ref = snippet(cx, self_ty_without_ref.ty.span, ".."),
+                        ref_self = mtbl.ref_prefix_str(),
+                        iter_ty = snippet(cx, iter_assoc_span, ".."),
+                    );
+
+                    diag.span_suggestion_verbose(
+                        item.span.shrink_to_lo(),
+                        format!("consider implementing `{expected_method_name}`"),
+                        sugg,
+                        // Just like iter_without_into_iter, this suggestion is on a best effort basis
+                        // and requires potentially adding lifetimes or moving them around.
+                        Applicability::Unspecified
+                    );
+                }
+            );
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) {
+        let item_did = item.owner_id.to_def_id();
+        let (borrow_prefix, expected_implicit_self) = match item.ident.name {
+            sym::iter => ("&", ImplicitSelfKind::ImmRef),
+            sym::iter_mut => ("&mut ", ImplicitSelfKind::MutRef),
+            _ => return,
+        };
+
+        if let ImplItemKind::Fn(sig, _) = item.kind
+            && let FnRetTy::Return(ret) = sig.decl.output
+            && is_nameable_in_impl_trait(ret)
+            && cx.tcx.generics_of(item_did).params.is_empty()
+            && sig.decl.implicit_self == expected_implicit_self
+            && sig.decl.inputs.len() == 1
+            && let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id())
+            && imp.of_trait.is_none()
+            && let sig = cx.tcx.liberate_late_bound_regions(
+                item_did,
+                cx.tcx.fn_sig(item_did).instantiate_identity()
+            )
+            && let ref_ty = sig.inputs()[0]
+            && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
+            && let Some(iterator_did) = cx.tcx.get_diagnostic_item(sym::Iterator)
+            && let ret_ty = sig.output()
+            // Order is important here, we need to check that the `fn iter` return type actually implements `IntoIterator`
+            // *before* normalizing `<_ as IntoIterator>::Item` (otherwise make_normalized_projection ICEs)
+            && implements_trait(cx, ret_ty, iterator_did, &[])
+            && let Some(iter_ty) = make_normalized_projection(
+                cx.tcx,
+                cx.param_env,
+                iterator_did,
+                sym!(Item),
+                [ret_ty],
+            )
+            // Only lint if the `IntoIterator` impl doesn't actually exist
+            && !implements_trait(cx, ref_ty, into_iter_did, &[])
+        {
+            let self_ty_snippet = format!("{borrow_prefix}{}", snippet(cx, imp.self_ty.span, ".."));
+
+            span_lint_and_then(
+                cx,
+                ITER_WITHOUT_INTO_ITER,
+                item.span,
+                &format!("`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`", item.ident),
+                |diag| {
+                    // Get the lower span of the `impl` block, and insert the suggestion right before it:
+                    // impl X {
+                    // ^   fn iter(&self) -> impl IntoIterator { ... }
+                    // }
+                    let span_behind_impl = cx.tcx
+                        .def_span(cx.tcx.hir().parent_id(item.hir_id()).owner.def_id)
+                        .shrink_to_lo();
+
+                    let sugg = format!(
+"
+impl IntoIterator for {self_ty_snippet} {{
+    type IntoIter = {ret_ty};
+    type Iter = {iter_ty};
+    fn into_iter() -> Self::IntoIter {{
+        self.iter()
+    }}
+}}
+"
+                    );
+                    diag.span_suggestion_verbose(
+                        span_behind_impl,
+                        format!("consider implementing `IntoIterator` for `{self_ty_snippet}`"),
+                        sugg,
+                        // Suggestion is on a best effort basis, might need some adjustments by the user
+                        // such as adding some lifetimes in the associated types, or importing types.
+                        Applicability::Unspecified,
+                    );
+            });
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 1271be2fd93..0f35ec27665 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -169,6 +169,7 @@ mod invalid_upcast_comparisons;
 mod items_after_statements;
 mod items_after_test_module;
 mod iter_not_returning_iterator;
+mod iter_without_into_iter;
 mod large_const_arrays;
 mod large_enum_variant;
 mod large_futures;
@@ -190,6 +191,7 @@ mod manual_async_fn;
 mod manual_bits;
 mod manual_clamp;
 mod manual_float_methods;
+mod manual_hash_one;
 mod manual_is_ascii_check;
 mod manual_let_else;
 mod manual_main_separator_str;
@@ -1119,6 +1121,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             msrv(),
         ))
     });
+    store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv())));
+    store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
index 88db7ae6aec..ed9189a1804 100644
--- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
@@ -26,7 +26,7 @@ declare_clippy_lint! {
     /// # let x = 1.0f32;
     /// if x.is_infinite() {}
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub MANUAL_IS_INFINITE,
     style,
     "use dedicated method to check if a float is infinite"
@@ -51,7 +51,7 @@ declare_clippy_lint! {
     /// if x.is_finite() {}
     /// if x.is_finite() {}
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub MANUAL_IS_FINITE,
     style,
     "use dedicated method to check if a float is finite"
diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
new file mode 100644
index 00000000000..ea911335450
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
@@ -0,0 +1,133 @@
+use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::visitors::{is_local_used, local_used_once};
+use clippy_utils::{is_trait_method, path_to_local_id};
+use rustc_errors::Applicability;
+use rustc_hir::{BindingAnnotation, ExprKind, Local, Node, PatKind, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for cases where [`BuildHasher::hash_one`] can be used.
+    ///
+    /// [`BuildHasher::hash_one`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html#method.hash_one
+    ///
+    /// ### Why is this bad?
+    /// It is more concise to use the `hash_one` method.
+    ///
+    /// ### Example
+    /// ```rust
+    /// use std::hash::{BuildHasher, Hash, Hasher};
+    /// use std::collections::hash_map::RandomState;
+    ///
+    /// let s = RandomState::new();
+    /// let value = vec![1, 2, 3];
+    ///
+    /// let mut hasher = s.build_hasher();
+    /// value.hash(&mut hasher);
+    /// let hash = hasher.finish();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// use std::hash::BuildHasher;
+    /// use std::collections::hash_map::RandomState;
+    ///
+    /// let s = RandomState::new();
+    /// let value = vec![1, 2, 3];
+    ///
+    /// let hash = s.hash_one(&value);
+    /// ```
+    #[clippy::version = "1.74.0"]
+    pub MANUAL_HASH_ONE,
+    complexity,
+    "manual implementations of `BuildHasher::hash_one`"
+}
+
+pub struct ManualHashOne {
+    msrv: Msrv,
+}
+
+impl ManualHashOne {
+    #[must_use]
+    pub fn new(msrv: Msrv) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(ManualHashOne => [MANUAL_HASH_ONE]);
+
+impl LateLintPass<'_> for ManualHashOne {
+    fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
+        // `let mut hasher = seg.build_hasher();`
+        if let PatKind::Binding(BindingAnnotation::MUT, hasher, _, None) = local.pat.kind
+            && let Some(init) = local.init
+            && !init.span.from_expansion()
+            && let ExprKind::MethodCall(seg, build_hasher, [], _) = init.kind
+            && seg.ident.name == sym!(build_hasher)
+
+            && let Node::Stmt(local_stmt) = cx.tcx.hir().get_parent(local.hir_id)
+            && let Node::Block(block) = cx.tcx.hir().get_parent(local_stmt.hir_id)
+
+            && let mut stmts = block.stmts.iter()
+                .skip_while(|stmt| stmt.hir_id != local_stmt.hir_id)
+                .skip(1)
+                .filter(|&stmt| is_local_used(cx, stmt, hasher))
+
+            // `hashed_value.hash(&mut hasher);`
+            && let Some(hash_stmt) = stmts.next()
+            && let StmtKind::Semi(hash_expr) = hash_stmt.kind
+            && !hash_expr.span.from_expansion()
+            && let ExprKind::MethodCall(seg, hashed_value, [ref_to_hasher], _) = hash_expr.kind
+            && seg.ident.name == sym::hash
+            && is_trait_method(cx, hash_expr, sym::Hash)
+            && path_to_local_id(ref_to_hasher.peel_borrows(), hasher)
+
+            && let maybe_finish_stmt = stmts.next()
+            // There should be no more statements referencing `hasher`
+            && stmts.next().is_none()
+
+            // `hasher.finish()`, may be anywhere in a statement or the trailing expr of the block
+            && let Some(path_expr) = local_used_once(cx, (maybe_finish_stmt, block.expr), hasher)
+            && let Node::Expr(finish_expr) = cx.tcx.hir().get_parent(path_expr.hir_id)
+            && !finish_expr.span.from_expansion()
+            && let ExprKind::MethodCall(seg, _, [], _) = finish_expr.kind
+            && seg.ident.name == sym!(finish)
+
+            && self.msrv.meets(msrvs::BUILD_HASHER_HASH_ONE)
+        {
+            span_lint_hir_and_then(
+                cx,
+                MANUAL_HASH_ONE,
+                finish_expr.hir_id,
+                finish_expr.span,
+                "manual implementation of `BuildHasher::hash_one`",
+                |diag| {
+                    if let Some(build_hasher) = snippet_opt(cx, build_hasher.span)
+                        && let Some(hashed_value) = snippet_opt(cx, hashed_value.span)
+                    {
+                        diag.multipart_suggestion(
+                            "try",
+                            vec![
+                                (local_stmt.span, String::new()),
+                                (hash_stmt.span, String::new()),
+                                (
+                                    finish_expr.span,
+                                    // `needless_borrows_for_generic_args` will take care of
+                                    // removing the `&` when it isn't needed
+                                    format!("{build_hasher}.hash_one(&{hashed_value})")
+                                )
+                            ],
+                            Applicability::MachineApplicable,
+                        );
+
+                    }
+                },
+            );
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index c531137b785..2117308cd40 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -136,9 +136,9 @@ fn emit_manual_let_else(
             // for this to be machine applicable.
             let mut app = Applicability::HasPlaceholders;
             let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
-            let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
+            let (sn_else, else_is_mac_call) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
 
-            let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) {
+            let else_bl = if matches!(else_body.kind, ExprKind::Block(..)) && !else_is_mac_call {
                 sn_else.into_owned()
             } else {
                 format!("{{ {sn_else} }}")
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 0e22485db2c..c12727c4a28 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -3,6 +3,7 @@ use clippy_utils::is_doc_hidden;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{self, VisibilityKind};
+use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -158,7 +159,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
             let mut iter = def.variants.iter().filter_map(|v| {
                 (matches!(v.data, hir::VariantData::Unit(_, _))
                     && v.ident.as_str().starts_with('_')
-                    && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
+                    && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id))
+                    && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive))
                 .then_some((v.def_id, v.span))
             });
             if let Some((id, span)) = iter.next()
@@ -198,16 +200,14 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
                 enum_span,
                 "this seems like a manual implementation of the non-exhaustive pattern",
                 |diag| {
-                    if !cx.tcx.adt_def(enum_id).is_variant_list_non_exhaustive()
-                        && let header_span = cx.sess().source_map().span_until_char(enum_span, '{')
-                        && let Some(snippet) = snippet_opt(cx, header_span)
-                    {
-                            diag.span_suggestion(
-                                header_span,
-                                "add the attribute",
-                                format!("#[non_exhaustive] {snippet}"),
-                                Applicability::Unspecified,
-                            );
+                    let header_span = cx.sess().source_map().span_until_char(enum_span, '{');
+                    if let Some(snippet) = snippet_opt(cx, header_span) {
+                        diag.span_suggestion(
+                            header_span,
+                            "add the attribute",
+                            format!("#[non_exhaustive] {snippet}"),
+                            Applicability::Unspecified,
+                        );
                     }
                     diag.span_help(variant_span, "remove this variant");
                 },
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 930386a60aa..a23000e5fe1 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -961,7 +961,7 @@ declare_clippy_lint! {
     ///     _ => todo!(),
     /// }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub REDUNDANT_GUARDS,
     complexity,
     "checks for unnecessary guards in match expressions"
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 7c0485914b8..8f0083f812c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt};
+use clippy_utils::consts::{constant, constant_full_int, mir_to_const, FullInt};
 use clippy_utils::diagnostics::span_lint_and_note;
 use core::cmp::Ordering;
 use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
@@ -37,14 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
-                            miri_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
+                            mir_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
                         },
                     };
                     let rhs_const = match rhs {
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
-                            miri_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
+                            mir_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
                         },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index e7fcef9e9de..a935aea5075 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -2970,7 +2970,7 @@ declare_clippy_lint! {
     /// assert_eq!((*any_box).type_id(), TypeId::of::<i32>());
     /// //          ^ dereference first, to call `type_id` on `dyn Any`
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub TYPE_ID_ON_BOX,
     suspicious,
     "calling `.type_id()` on `Box<dyn Any>`"
@@ -3368,6 +3368,7 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
+    /// ### What it does
     /// Looks for calls to [`Stdin::read_line`] to read a line from the standard input
     /// into a string, then later attempting to parse this string into a type without first trimming it, which will
     /// always fail because the string has a trailing newline in it.
@@ -3390,7 +3391,7 @@ declare_clippy_lint! {
     /// //                  ^^^^^^^^^^^ remove the trailing newline
     /// assert_eq!(num, 42);
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub READ_LINE_WITHOUT_TRIM,
     correctness,
     "calling `Stdin::read_line`, then trying to parse it without first trimming"
@@ -3418,7 +3419,7 @@ declare_clippy_lint! {
     /// # let c = 'c';
     /// matches!(c, '\\' | '.' | '+' | '*' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~');
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub STRING_LIT_CHARS_ANY,
     restriction,
     "checks for `<string_lit>.chars().any(|i| i == c)`"
@@ -3453,7 +3454,7 @@ declare_clippy_lint! {
     ///     })
     /// }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub FORMAT_COLLECT,
     perf,
     "`format!`ing every element in a collection, then collecting the strings into a new `String`"
@@ -3474,7 +3475,7 @@ declare_clippy_lint! {
     /// let y = v.iter().collect::<Vec<_>>();
     /// assert_eq!(x, y);
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub ITER_SKIP_ZERO,
     correctness,
     "disallows `.skip(0)`"
@@ -3505,7 +3506,7 @@ declare_clippy_lint! {
     /// # let v = vec![];
     /// _ = v.into_iter().filter(|i| i % 2 == 0).map(|i| really_expensive_fn(i));
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub FILTER_MAP_BOOL_THEN,
     style,
     "checks for usage of `bool::then` in `Iterator::filter_map`"
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
index 24c0ea3f60a..3e19d72ec91 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -24,7 +24,6 @@ fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -
     }
 }
 
-#[expect(clippy::too_many_lines)]
 pub(super) fn check(
     cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
@@ -101,11 +100,11 @@ pub(super) fn check(
                 (expr.span.with_lo(args[0].span.hi()), String::new()),
             ]),
             ("None", "unwrap_or_else", _) => match args[0].kind {
-                hir::ExprKind::Closure(hir::Closure {
-                    body,
-                    ..
-                }) => Some(vec![
-                    (expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()), String::new()),
+                hir::ExprKind::Closure(hir::Closure { body, .. }) => Some(vec![
+                    (
+                        expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()),
+                        String::new(),
+                    ),
                     (expr.span.with_lo(args[0].span.hi()), String::new()),
                 ]),
                 _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
index c17f00c4275..136947a2c8c 100644
--- a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
@@ -15,6 +15,10 @@ declare_clippy_lint! {
     /// A good custom message should be more about why the failure of the assertion is problematic
     /// and not what is failed because the assertion already conveys that.
     ///
+    /// Although the same reasoning applies to testing functions, this lint ignores them as they would be too noisy.
+    /// Also, in most cases understanding the test failure would be easier
+    /// compared to understanding a complex invariant distributed around the codebase.
+    ///
     /// ### Known problems
     /// This lint cannot check the quality of the custom panic messages.
     /// Hence, you can suppress this lint simply by adding placeholder messages
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index ea6a9bc5657..e87aea263d4 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -135,10 +135,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
 }
 
 fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool {
-    match stmt.kind {
-        StmtKind::Item(..) => false,
-        _ => true,
-    }
+    !matches!(stmt.kind, StmtKind::Item(..))
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
@@ -148,7 +145,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
             ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
                 (stmts, Some(e)) => {
                     if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) {
-                        self.visit_expr(e)
+                        self.visit_expr(e);
                     }
                 },
                 ([first @ .., stmt], None) => {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 57652e5ff54..212d6234bdb 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -47,9 +47,9 @@ declare_clippy_lint! {
     ///     12 + *y
     /// }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub NEEDLESS_PASS_BY_REF_MUT,
-    suspicious,
+    nursery,
     "using a `&mut` argument when it's not mutated"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
index 4be140647fc..0e4b6aa1b7d 100644
--- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
@@ -102,7 +102,7 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub NON_CANONICAL_PARTIAL_ORD_IMPL,
     suspicious,
     "non-canonical implementation of `PartialOrd` on an `Ord` type"
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 4635e1164cd..6b247cf5f6a 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -312,7 +312,7 @@ declare_clippy_lint! {
     /// # let status_code = 200;
     /// if status_code <= 400 && status_code > 500 {}
     /// ```
-    #[clippy::version = "1.71.0"]
+    #[clippy::version = "1.73.0"]
     pub IMPOSSIBLE_COMPARISONS,
     correctness,
     "double comparisons that will never evaluate to `true`"
@@ -332,7 +332,7 @@ declare_clippy_lint! {
     /// # let status_code = 200;
     /// if status_code <= 400 && status_code < 500 {}
     /// ```
-    #[clippy::version = "1.71.0"]
+    #[clippy::version = "1.73.0"]
     pub REDUNDANT_COMPARISONS,
     correctness,
     "double comparisons where one of them can be removed"
diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs
index 8a7e4874666..c951d9a4a09 100644
--- a/src/tools/clippy/clippy_lints/src/raw_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs
@@ -75,6 +75,7 @@ impl EarlyLintPass for RawStrings {
             if !snippet(cx, expr.span, prefix).trim().starts_with(prefix) {
                 return;
             }
+            let descr = lit.kind.descr();
 
             if !str.contains(['\\', '"']) {
                 span_lint_and_then(
@@ -89,20 +90,17 @@ impl EarlyLintPass for RawStrings {
                         let r_pos = expr.span.lo() + BytePos::from_usize(prefix.len() - 1);
                         let start = start.with_lo(r_pos);
 
-                        if end.is_empty() {
-                            diag.span_suggestion(
-                                start,
-                                "use a string literal instead",
-                                format!("\"{str}\""),
-                                Applicability::MachineApplicable,
-                            );
-                        } else {
-                            diag.multipart_suggestion(
-                                "try",
-                                vec![(start, String::new()), (end, String::new())],
-                                Applicability::MachineApplicable,
-                            );
+                        let mut remove = vec![(start, String::new())];
+                        // avoid debug ICE from empty suggestions
+                        if !end.is_empty() {
+                            remove.push((end, String::new()));
                         }
+
+                        diag.multipart_suggestion_verbose(
+                            format!("use a plain {descr} literal instead"),
+                            remove,
+                            Applicability::MachineApplicable,
+                        );
                     },
                 );
                 if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS), rustc_lint::Allow) {
@@ -149,9 +147,9 @@ impl EarlyLintPass for RawStrings {
                         let (start, end) = hash_spans(expr.span, prefix, req, max);
 
                         let message = match max - req {
-                            _ if req == 0 => "remove all the hashes around the literal".to_string(),
-                            1 => "remove one hash from both sides of the literal".to_string(),
-                            n => format!("remove {n} hashes from both sides of the literal"),
+                            _ if req == 0 => format!("remove all the hashes around the {descr} literal"),
+                            1 => format!("remove one hash from both sides of the {descr} literal"),
+                            n => format!("remove {n} hashes from both sides of the {descr} literal"),
                         };
 
                         diag.multipart_suggestion(
diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
index 0c89c7ee47d..197742b5dd4 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
@@ -3,11 +3,9 @@ use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::needs_ordered_drop;
 use rustc_ast::Mutability;
 use rustc_hir::def::Res;
-use rustc_hir::{
-    BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath,
-};
+use rustc_hir::{BindingAnnotation, ByRef, ExprKind, HirId, Local, Node, Pat, PatKind, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::lint::{in_external_macro, is_from_async_await};
+use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Ident;
 use rustc_span::DesugaringKind;
@@ -39,7 +37,7 @@ declare_clippy_lint! {
     ///   // no redefinition with the same name
     /// }
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.73.0"]
     pub REDUNDANT_LOCALS,
     correctness,
     "redundant redefinition of a local binding"
@@ -68,21 +66,18 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
             // the local does not change the effect of assignments to the binding. see #11290
             if !affects_assignments(cx, mutability, binding_id, local.hir_id);
             // the local does not affect the code's drop behavior
-            if !affects_drop_behavior(cx, binding_id, local.hir_id, expr);
+            if !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr));
             // the local is user-controlled
             if !in_external_macro(cx.sess(), local.span);
             if !is_from_proc_macro(cx, expr);
-            // Async function parameters are lowered into the closure body, so we can't lint them.
-            // see `lower_maybe_async_body` in `rust_ast_lowering`
-            if !is_from_async_await(local.span);
             then {
                 span_lint_and_help(
                     cx,
                     REDUNDANT_LOCALS,
-                    vec![binding_pat.span, local.span],
-                    "redundant redefinition of a binding",
-                    None,
-                    &format!("remove the redefinition of `{ident}`"),
+                    local.span,
+                    &format!("redundant redefinition of a binding `{ident}`"),
+                    Some(binding_pat.span),
+                    &format!("`{ident}` is initially defined here"),
                 );
             }
         }
@@ -109,18 +104,3 @@ fn affects_assignments(cx: &LateContext<'_>, mutability: Mutability, bind: HirId
     // the binding is mutable and the rebinding is in a different scope than the original binding
     mutability == Mutability::Mut && hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind)
 }
-
-/// Check if a rebinding of a local affects the code's drop behavior.
-fn affects_drop_behavior<'tcx>(
-    cx: &LateContext<'tcx>,
-    bind: HirId,
-    rebind: HirId,
-    rebind_expr: &Expr<'tcx>,
-) -> bool {
-    let hir = cx.tcx.hir();
-
-    // the rebinding is in a different scope than the original binding
-    // and the type of the binding cares about drop order
-    hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind)
-        && needs_ordered_drop(cx, cx.typeck_results().expr_ty(rebind_expr))
-}
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index 5f54a10d1c4..b7396535eed 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -1,9 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_from_proc_macro;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{HirId, Path, PathSegment};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::kw;
 use rustc_span::{sym, Span};
@@ -99,6 +101,8 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
         if let Res::Def(_, def_id) = path.res
             && let Some(first_segment) = get_first_segment(path)
             && is_stable(cx, def_id)
+            && !in_external_macro(cx.sess(), path.span)
+            && !is_from_proc_macro(cx, &first_segment.ident)
         {
             let (lint, used_mod, replace_with) = match first_segment.ident.name {
                 sym::std => match cx.tcx.crate_name(def_id.krate) {
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 75c3c7a958a..23da1de7730 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -294,7 +294,7 @@ define_Conf! {
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE.
     ///
     /// The minimum rust version that the project supports
     (msrv: Option<String> = None),
@@ -744,3 +744,44 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) {
 
     (rows, column_widths)
 }
+
+#[cfg(test)]
+mod tests {
+    use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+    use serde::de::IgnoredAny;
+    use std::fs;
+    use walkdir::WalkDir;
+
+    #[test]
+    fn configs_are_tested() {
+        let mut names: FxHashSet<String> = super::metadata::get_configuration_metadata()
+            .into_iter()
+            .map(|meta| meta.name.replace('_', "-"))
+            .collect();
+
+        let toml_files = WalkDir::new("../tests")
+            .into_iter()
+            .map(Result::unwrap)
+            .filter(|entry| entry.file_name() == "clippy.toml");
+
+        for entry in toml_files {
+            let file = fs::read_to_string(entry.path()).unwrap();
+            #[allow(clippy::zero_sized_map_values)]
+            if let Ok(map) = toml::from_str::<FxHashMap<String, IgnoredAny>>(&file) {
+                for name in map.keys() {
+                    names.remove(name.as_str());
+                }
+            }
+        }
+
+        assert!(
+            names.remove("allow-one-hash-in-raw-strings"),
+            "remove this when #11481 is fixed"
+        );
+
+        assert!(
+            names.is_empty(),
+            "Configuration variable lacks test: {names:?}\nAdd a test to `tests/ui-toml`"
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index d09d02a7dfd..70b83149ce1 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -132,6 +132,7 @@ impl LateLintPass<'_> for WildcardImports {
             if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
             let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id);
             if !used_imports.is_empty(); // Already handled by `unused_imports`
+            if !used_imports.contains(&kw::Underscore);
             then {
                 let mut applicability = Applicability::MachineApplicable;
                 let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index da083fb14aa..855aefa70cb 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -3,12 +3,15 @@ use clippy_utils::macros::{find_format_args, format_arg_removal_span, root_macro
 use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
 use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_ast::token::LitKind;
-use rustc_ast::{FormatArgPosition, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder, FormatTrait};
+use rustc_ast::{
+    FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
+    FormatTrait,
+};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{sym, BytePos};
+use rustc_span::{sym, BytePos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -450,6 +453,12 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call
 fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
     let arg_index = |argument: &FormatArgPosition| argument.index.unwrap_or_else(|pos| pos);
 
+    let lint_name = if name.starts_with("write") {
+        WRITE_LITERAL
+    } else {
+        PRINT_LITERAL
+    };
+
     let mut counts = vec![0u32; format_args.arguments.all_args().len()];
     for piece in &format_args.template {
         if let FormatArgsPiece::Placeholder(placeholder) = piece {
@@ -457,6 +466,12 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
         }
     }
 
+    let mut suggestion: Vec<(Span, String)> = vec![];
+    // holds index of replaced positional arguments; used to decrement the index of the remaining
+    // positional arguments.
+    let mut replaced_position: Vec<usize> = vec![];
+    let mut sug_span: Option<Span> = None;
+
     for piece in &format_args.template {
         if let FormatArgsPiece::Placeholder(FormatPlaceholder {
             argument,
@@ -471,9 +486,9 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
             && let rustc_ast::ExprKind::Lit(lit) = &arg.expr.kind
             && !arg.expr.span.from_expansion()
             && let Some(value_string) = snippet_opt(cx, arg.expr.span)
-    {
+        {
             let (replacement, replace_raw) = match lit.kind {
-                LitKind::Str | LitKind::StrRaw(_)  => match extract_str_literal(&value_string) {
+                LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) {
                     Some(extracted) => extracted,
                     None => return,
                 },
@@ -493,12 +508,6 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
                 _ => continue,
             };
 
-            let lint = if name.starts_with("write") {
-                WRITE_LITERAL
-            } else {
-                PRINT_LITERAL
-            };
-
             let Some(format_string_snippet) = snippet_opt(cx, format_args.span) else { continue };
             let format_string_is_raw = format_string_snippet.starts_with('r');
 
@@ -519,29 +528,58 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
                 },
             };
 
-            span_lint_and_then(
-                cx,
-                lint,
-                arg.expr.span,
-                "literal with an empty format string",
-                |diag| {
-                    if let Some(replacement) = replacement
-                        // `format!("{}", "a")`, `format!("{named}", named = "b")
-                        //              ~~~~~                      ~~~~~~~~~~~~~
-                        && let Some(removal_span) = format_arg_removal_span(format_args, index)
-                    {
-                        let replacement = replacement.replace('{', "{{").replace('}', "}}");
-                        diag.multipart_suggestion(
-                            "try",
-                            vec![(*placeholder_span, replacement), (removal_span, String::new())],
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                },
-            );
+            sug_span = Some(sug_span.unwrap_or(arg.expr.span).to(arg.expr.span));
+
+            if let Some((_, index)) = positional_arg_piece_span(piece) {
+                replaced_position.push(index);
+            }
+
+            if let Some(replacement) = replacement
+                // `format!("{}", "a")`, `format!("{named}", named = "b")
+                //              ~~~~~                      ~~~~~~~~~~~~~
+                && let Some(removal_span) = format_arg_removal_span(format_args, index) {
+                let replacement = escape_braces(&replacement, !format_string_is_raw && !replace_raw);
+                suggestion.push((*placeholder_span, replacement));
+                suggestion.push((removal_span, String::new()));
+            }
+        }
+    }
 
+    // Decrement the index of the remaining by the number of replaced positional arguments
+    if !suggestion.is_empty() {
+        for piece in &format_args.template {
+            if let Some((span, index)) = positional_arg_piece_span(piece)
+                && suggestion.iter().all(|(s, _)| *s != span) {
+                let decrement = replaced_position.iter().filter(|i| **i < index).count();
+                suggestion.push((span, format!("{{{}}}", index.saturating_sub(decrement))));
+            }
         }
     }
+
+    if let Some(span) = sug_span {
+        span_lint_and_then(cx, lint_name, span, "literal with an empty format string", |diag| {
+            if !suggestion.is_empty() {
+                diag.multipart_suggestion("try", suggestion, Applicability::MachineApplicable);
+            }
+        });
+    }
+}
+
+/// Extract Span and its index from the given `piece`, iff it's positional argument.
+fn positional_arg_piece_span(piece: &FormatArgsPiece) -> Option<(Span, usize)> {
+    match piece {
+        FormatArgsPiece::Placeholder(FormatPlaceholder {
+            argument:
+                FormatArgPosition {
+                    index: Ok(index),
+                    kind: FormatArgPositionKind::Number,
+                    ..
+                },
+            span: Some(span),
+            ..
+        }) => Some((*span, *index)),
+        _ => None,
+    }
 }
 
 /// Removes the raw marker, `#`s and quotes from a str, and returns if the literal is raw
@@ -593,3 +631,47 @@ fn conservative_unescape(literal: &str) -> Result<String, UnescapeErr> {
 
     if err { Err(UnescapeErr::Lint) } else { Ok(unescaped) }
 }
+
+/// Replaces `{` with `{{` and `}` with `}}`. If `preserve_unicode_escapes` is `true` the braces in
+/// `\u{xxxx}` are left unmodified
+#[expect(clippy::match_same_arms)]
+fn escape_braces(literal: &str, preserve_unicode_escapes: bool) -> String {
+    #[derive(Clone, Copy)]
+    enum State {
+        Normal,
+        Backslash,
+        UnicodeEscape,
+    }
+
+    let mut escaped = String::with_capacity(literal.len());
+    let mut state = State::Normal;
+
+    for ch in literal.chars() {
+        state = match (ch, state) {
+            // Escape braces outside of unicode escapes by doubling them up
+            ('{' | '}', State::Normal) => {
+                escaped.push(ch);
+                State::Normal
+            },
+            // If `preserve_unicode_escapes` isn't enabled stay in `State::Normal`, otherwise:
+            //
+            // \u{aaaa} \\ \x01
+            // ^        ^  ^
+            ('\\', State::Normal) if preserve_unicode_escapes => State::Backslash,
+            // \u{aaaa}
+            //  ^
+            ('u', State::Backslash) => State::UnicodeEscape,
+            // \xAA \\
+            //  ^    ^
+            (_, State::Backslash) => State::Normal,
+            // \u{aaaa}
+            //        ^
+            ('}', State::UnicodeEscape) => State::Normal,
+            _ => state,
+        };
+
+        escaped.push(ch);
+    }
+
+    escaped
+}
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 1596bb77397..8522493f67b 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.74"
+version = "0.1.75"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index d596eed4b7c..0bae7056c4f 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -9,11 +9,12 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::Scalar;
+use rustc_middle::mir::interpret::{alloc_range, Scalar};
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, List, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::SyntaxContext;
+use rustc_target::abi::Size;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -403,7 +404,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     && adt_def.is_struct()
                     && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field)
                 {
-                    miri_to_const(self.lcx, desired_field)
+                    mir_to_const(self.lcx, desired_field)
                 }
                 else {
                     result
@@ -483,7 +484,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None)
                     .ok()
                     .map(|val| rustc_middle::mir::Const::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx, result)?;
+                let result = mir_to_const(self.lcx, result)?;
                 self.source = ConstantSource::Constant;
                 Some(result)
             },
@@ -655,10 +656,14 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 }
 
-pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
+pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
     use rustc_middle::mir::ConstValue;
-    match result {
-        mir::Const::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
+    let mir::Const::Val(val, _) = result else {
+        // We only work on evaluated consts.
+        return None;
+    };
+    match (val, result.ty().kind()) {
+        (ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
             ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
             ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
             ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
@@ -671,42 +676,28 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
             ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
             _ => None,
         },
-        mir::Const::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) =>
-        {
-            let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
+        (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
+            let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
             String::from_utf8(data.to_owned()).ok().map(Constant::Str)
         },
-        mir::Const::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => {
-            let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
-            match result.ty().kind() {
-                ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
-                ty::Array(sub_type, len) => match sub_type.kind() {
-                    ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
-                        Some(len) => alloc
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
-                            .to_owned()
-                            .array_chunks::<4>()
-                            .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
-                            .collect::<Option<Vec<Constant<'tcx>>>>()
-                            .map(Constant::Vec),
-                        _ => None,
-                    },
-                    ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
-                        Some(len) => alloc
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
-                            .to_owned()
-                            .array_chunks::<8>()
-                            .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
-                            .collect::<Option<Vec<Constant<'tcx>>>>()
-                            .map(Constant::Vec),
-                        _ => None,
-                    },
-                    _ => None,
-                },
-                _ => None,
+        (_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)),
+        (ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => {
+            let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
+            let len = len.try_to_target_usize(lcx.tcx)?;
+            let ty::Float(flt) = sub_type.kind() else {
+                return None;
+            };
+            let size = Size::from_bits(flt.bit_width());
+            let mut res = Vec::new();
+            for idx in 0..len {
+                let range = alloc_range(offset + size * idx, size);
+                let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?;
+                res.push(match flt {
+                    FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)),
+                    FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().ok()?)),
+                });
             }
+            Some(Constant::Vec(res))
         },
         _ => None,
     }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 64ca2ff7873..c2c97259d38 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -80,7 +80,6 @@ use std::sync::{Mutex, MutexGuard, OnceLock};
 use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
-use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir::def::{DefKind, Res};
@@ -113,7 +112,7 @@ use rustc_span::{sym, Span};
 use rustc_target::abi::Integer;
 use visitors::Visitable;
 
-use crate::consts::{constant, miri_to_const, Constant};
+use crate::consts::{constant, mir_to_const, Constant};
 use crate::higher::Range;
 use crate::ty::{
     adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type,
@@ -1509,9 +1508,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
             if let rustc_ty::Adt(_, subst) = ty.kind()
                 && let bnd_ty = subst.type_at(0)
                 && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
-                && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
-                && let min_const_kind = Const::from_value(const_val, bnd_ty)
-                && let Some(min_const) = miri_to_const(cx, min_const_kind)
+                && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, cx.tcx))
                 && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
@@ -1525,9 +1522,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                     if let rustc_ty::Adt(_, subst) = ty.kind()
                         && let bnd_ty = subst.type_at(0)
                         && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
-                        && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
-                        && let max_const_kind = Const::from_value(const_val, bnd_ty)
-                        && let Some(max_const) = miri_to_const(cx, max_const_kind)
+                        && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, cx.tcx))
                         && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const
@@ -2456,11 +2451,12 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     })
 }
 
-/// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied
+/// Checks if `id` has a `#[cfg(test)]` attribute applied
 ///
-/// Note: Add `//@compile-flags: --test` to UI tests with a `#[cfg(test)]` function
-pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
-    fn is_cfg_test(attr: &Attribute) -> bool {
+/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
+/// use [`is_in_cfg_test`]
+pub fn is_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
+    tcx.hir().attrs(id).iter().any(|attr| {
         if attr.has_name(sym::cfg)
             && let Some(items) = attr.meta_item_list()
             && let [item] = &*items
@@ -2470,11 +2466,14 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
         } else {
             false
         }
-    }
+    })
+}
+
+/// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied
+pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     tcx.hir()
-        .parent_iter(id)
-        .flat_map(|(parent_id, _)| tcx.hir().attrs(parent_id))
-        .any(is_cfg_test)
+        .parent_id_iter(id)
+        .any(|parent_id| is_cfg_test(tcx, parent_id))
 }
 
 /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 0faff05eb23..df839c2106f 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -19,7 +19,7 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
-    1,71,0 { TUPLE_ARRAY_CONVERSIONS }
+    1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
     1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN }
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 3b47a451345..d752fe7d97e 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -62,6 +62,27 @@ where
         }
     }
 }
+impl<'tcx, A, B> Visitable<'tcx> for (A, B)
+where
+    A: Visitable<'tcx>,
+    B: Visitable<'tcx>,
+{
+    fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+        let (a, b) = self;
+        a.visit(visitor);
+        b.visit(visitor);
+    }
+}
+impl<'tcx, T> Visitable<'tcx> for Option<T>
+where
+    T: Visitable<'tcx>,
+{
+    fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+        if let Some(x) = self {
+            x.visit(visitor);
+        }
+    }
+}
 macro_rules! visitable_ref {
     ($t:ident, $f:ident) => {
         impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
@@ -748,3 +769,26 @@ pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool {
     })
     .is_some()
 }
+
+/// If the local is only used once in `visitable` returns the path expression referencing the given
+/// local
+pub fn local_used_once<'tcx>(
+    cx: &LateContext<'tcx>,
+    visitable: impl Visitable<'tcx>,
+    id: HirId,
+) -> Option<&'tcx Expr<'tcx>> {
+    let mut expr = None;
+
+    let cf = for_each_expr_with_closures(cx, visitable, |e| {
+        if path_to_local_id(e, id) && expr.replace(e).is_some() {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
+        }
+    });
+    if cf.is_some() {
+        return None;
+    }
+
+    expr
+}
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 1470da61fac..beea9fd00e7 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.74"
+version = "0.1.75"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 5ce22b65f00..fe2c77ab47f 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-09-25"
+channel = "nightly-2023-10-06"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 1d89477dcc1..d47767faed9 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -26,6 +26,8 @@ use std::ops::Deref;
 use std::path::Path;
 use std::process::exit;
 
+use anstream::println;
+
 /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
 /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
 fn arg_value<'a, T: Deref<Target = str>>(
@@ -162,39 +164,15 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
     }
 }
 
+#[allow(clippy::ignored_unit_patterns)]
 fn display_help() {
-    println!(
-        "\
-Checks a package to catch common mistakes and improve your Rust code.
-
-Usage:
-    cargo clippy [options] [--] [<opts>...]
-
-Common options:
-    -h, --help               Print this message
-        --rustc              Pass all args to rustc
-    -V, --version            Print version info and exit
-
-For the other options see `cargo check --help`.
-
-To allow or deny a lint from the command line you can use `cargo clippy --`
-with:
-
-    -W --warn OPT       Set lint warnings
-    -A --allow OPT      Set lint allowed
-    -D --deny OPT       Set lint denied
-    -F --forbid OPT     Set lint forbidden
-
-You can use tool lints to allow or deny lints from your code, eg.:
-
-    #[allow(clippy::needless_lifetimes)]
-"
-    );
+    println!("{}", help_message());
 }
 
 const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml";
 
 #[allow(clippy::too_many_lines)]
+#[allow(clippy::ignored_unit_patterns)]
 pub fn main() {
     let handler = EarlyErrorHandler::new(ErrorOutputType::default());
 
@@ -236,6 +214,7 @@ pub fn main() {
 
         if orig_args.iter().any(|a| a == "--version" || a == "-V") {
             let version_info = rustc_tools_util::get_version_info!();
+
             println!("{version_info}");
             exit(0);
         }
@@ -292,3 +271,25 @@ pub fn main() {
         }
     }))
 }
+
+#[must_use]
+fn help_message() -> &'static str {
+    color_print::cstr!(
+        "Checks a file to catch common mistakes and improve your Rust code.
+Run <cyan>clippy-driver</> with the same arguments you use for <cyan>rustc</>
+
+<green,bold>Usage</>:
+    <cyan,bold>clippy-driver</> <cyan>[OPTIONS] INPUT</>
+
+<green,bold>Common options:</>
+    <cyan,bold>-h</>, <cyan,bold>--help</>               Print this message
+    <cyan,bold>-V</>, <cyan,bold>--version</>            Print version info and exit
+    <cyan,bold>--rustc</>                  Pass all arguments to <cyan>rustc</>
+
+<green,bold>Allowing / Denying lints</>
+You can use tool lints to allow or deny lints from your code, e.g.:
+
+    <yellow,bold>#[allow(clippy::needless_lifetimes)]</>
+"
+    )
+}
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index 26b655076cf..bbf7d22c850 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -6,37 +6,14 @@ use std::env;
 use std::path::PathBuf;
 use std::process::{self, Command};
 
-const CARGO_CLIPPY_HELP: &str = "Checks a package to catch common mistakes and improve your Rust code.
-
-Usage:
-    cargo clippy [options] [--] [<opts>...]
-
-Common options:
-    --no-deps                Run Clippy only on the given crate, without linting the dependencies
-    --fix                    Automatically apply lint suggestions. This flag implies `--no-deps` and `--all-targets`
-    -h, --help               Print this message
-    -V, --version            Print version info and exit
-    --explain LINT           Print the documentation for a given lint
-
-For the other options see `cargo check --help`.
-
-To allow or deny a lint from the command line you can use `cargo clippy --`
-with:
-
-    -W --warn OPT       Set lint warnings
-    -A --allow OPT      Set lint allowed
-    -D --deny OPT       Set lint denied
-    -F --forbid OPT     Set lint forbidden
-
-You can use tool lints to allow or deny lints from your code, e.g.:
-
-    #[allow(clippy::needless_lifetimes)]
-";
+use anstream::println;
 
+#[allow(clippy::ignored_unit_patterns)]
 fn show_help() {
-    println!("{CARGO_CLIPPY_HELP}");
+    println!("{}", help_message());
 }
 
+#[allow(clippy::ignored_unit_patterns)]
 fn show_version() {
     let version_info = rustc_tools_util::get_version_info!();
     println!("{version_info}");
@@ -168,6 +145,38 @@ where
     }
 }
 
+#[must_use]
+pub fn help_message() -> &'static str {
+    color_print::cstr!(
+"Checks a package to catch common mistakes and improve your Rust code.
+
+<green,bold>Usage</>:
+    <cyan,bold>cargo clippy</> <cyan>[OPTIONS] [--] [<<ARGS>>...]</>
+
+<green,bold>Common options:</>
+    <cyan,bold>--no-deps</>                Run Clippy only on the given crate, without linting the dependencies
+    <cyan,bold>--fix</>                    Automatically apply lint suggestions. This flag implies <cyan>--no-deps</> and <cyan>--all-targets</>
+    <cyan,bold>-h</>, <cyan,bold>--help</>               Print this message
+    <cyan,bold>-V</>, <cyan,bold>--version</>            Print version info and exit
+    <cyan,bold>--explain [LINT]</>         Print the documentation for a given lint
+
+See all options with <cyan,bold>cargo check --help</>.
+
+<green,bold>Allowing / Denying lints</>
+
+To allow or deny a lint from the command line you can use <cyan,bold>cargo clippy --</> with:
+
+    <cyan,bold>-W</> / <cyan,bold>--warn</> <cyan>[LINT]</>       Set lint warnings
+    <cyan,bold>-A</> / <cyan,bold>--allow</> <cyan>[LINT]</>      Set lint allowed
+    <cyan,bold>-D</> / <cyan,bold>--deny</> <cyan>[LINT]</>       Set lint denied
+    <cyan,bold>-F</> / <cyan,bold>--forbid</> <cyan>[LINT]</>     Set lint forbidden
+
+You can use tool lints to allow or deny lints from your code, e.g.:
+
+    <yellow,bold>#[allow(clippy::needless_lifetimes)]</>
+"
+    )
+}
 #[cfg(test)]
 mod tests {
     use super::ClippyCmd;
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index 37f0ec2b37d..79a95d775b1 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -21,6 +21,18 @@ pub fn derive(_: TokenStream) -> TokenStream {
     output
 }
 
+#[proc_macro_derive(ImplStructWithStdDisplay)]
+pub fn derive_std(_: TokenStream) -> TokenStream {
+    quote! {
+        struct A {}
+        impl ::std::fmt::Display for A {
+            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+                write!(f, "A")
+            }
+        }
+    }
+}
+
 #[proc_macro_derive(FieldReassignWithDefault)]
 pub fn derive_foo(_input: TokenStream) -> TokenStream {
     quote! {
@@ -141,3 +153,19 @@ pub fn shadow_derive(_: TokenStream) -> TokenStream {
         .into(),
     ])
 }
+
+#[proc_macro_derive(StructIgnoredUnitPattern)]
+pub fn derive_ignored_unit_pattern(_: TokenStream) -> TokenStream {
+    quote! {
+        struct A;
+        impl A {
+            fn a(&self) -> Result<(), ()> {
+                unimplemented!()
+            }
+
+            pub fn b(&self) {
+                let _ = self.a().unwrap();
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
index 6c6f21fee16..15eaf1f659a 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
@@ -1,3 +1,4 @@
+//@aux-build:proc_macro_derive.rs
 #![warn(clippy::ignored_unit_patterns)]
 #![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)]
 
@@ -14,8 +15,22 @@ fn main() {
     //~^ ERROR: matching over `()` is more explicit
     let _ = foo().map_err(|()| todo!());
     //~^ ERROR: matching over `()` is more explicit
+
+    println!(
+        "{:?}",
+        match foo() {
+            Ok(()) => {},
+            //~^ ERROR: matching over `()` is more explicit
+            Err(()) => {},
+            //~^ ERROR: matching over `()` is more explicit
+        }
+    );
 }
 
+// ignored_unit_patterns in derive macro should be ok
+#[derive(proc_macro_derive::StructIgnoredUnitPattern)]
+pub struct B;
+
 #[allow(unused)]
 pub fn moo(_: ()) {
     let () = foo().unwrap();
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
index 5e8c2e03ba2..9cac3a440ab 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
@@ -1,3 +1,4 @@
+//@aux-build:proc_macro_derive.rs
 #![warn(clippy::ignored_unit_patterns)]
 #![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)]
 
@@ -14,8 +15,22 @@ fn main() {
     //~^ ERROR: matching over `()` is more explicit
     let _ = foo().map_err(|_| todo!());
     //~^ ERROR: matching over `()` is more explicit
+
+    println!(
+        "{:?}",
+        match foo() {
+            Ok(_) => {},
+            //~^ ERROR: matching over `()` is more explicit
+            Err(_) => {},
+            //~^ ERROR: matching over `()` is more explicit
+        }
+    );
 }
 
+// ignored_unit_patterns in derive macro should be ok
+#[derive(proc_macro_derive::StructIgnoredUnitPattern)]
+pub struct B;
+
 #[allow(unused)]
 pub fn moo(_: ()) {
     let _ = foo().unwrap();
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
index df5e1d89e90..cac01a87dba 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
@@ -1,5 +1,5 @@
 error: matching over `()` is more explicit
-  --> $DIR/ignored_unit_patterns.rs:10:12
+  --> $DIR/ignored_unit_patterns.rs:11:12
    |
 LL |         Ok(_) => {},
    |            ^ help: use `()` instead of `_`: `()`
@@ -8,28 +8,40 @@ LL |         Ok(_) => {},
    = help: to override `-D warnings` add `#[allow(clippy::ignored_unit_patterns)]`
 
 error: matching over `()` is more explicit
-  --> $DIR/ignored_unit_patterns.rs:11:13
+  --> $DIR/ignored_unit_patterns.rs:12:13
    |
 LL |         Err(_) => {},
    |             ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> $DIR/ignored_unit_patterns.rs:13:15
+  --> $DIR/ignored_unit_patterns.rs:14:15
    |
 LL |     if let Ok(_) = foo() {}
    |               ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> $DIR/ignored_unit_patterns.rs:15:28
+  --> $DIR/ignored_unit_patterns.rs:16:28
    |
 LL |     let _ = foo().map_err(|_| todo!());
    |                            ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> $DIR/ignored_unit_patterns.rs:21:9
+  --> $DIR/ignored_unit_patterns.rs:22:16
+   |
+LL |             Ok(_) => {},
+   |                ^ help: use `()` instead of `_`: `()`
+
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:24:17
+   |
+LL |             Err(_) => {},
+   |                 ^ help: use `()` instead of `_`: `()`
+
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:36:9
    |
 LL |     let _ = foo().unwrap();
    |         ^ help: use `()` instead of `_`: `()`
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/infinite_loop.rs b/src/tools/clippy/tests/ui/infinite_loop.rs
index 281e12c7b93..765c6701147 100644
--- a/src/tools/clippy/tests/ui/infinite_loop.rs
+++ b/src/tools/clippy/tests/ui/infinite_loop.rs
@@ -7,8 +7,6 @@ fn fn_constref(i: &i32) -> i32 {
     unimplemented!()
 }
 fn fn_mutref(i: &mut i32) {
-    //~^ ERROR: this argument is a mutable reference, but not used mutably
-    //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
     unimplemented!()
 }
 fn fooi() -> i32 {
diff --git a/src/tools/clippy/tests/ui/infinite_loop.stderr b/src/tools/clippy/tests/ui/infinite_loop.stderr
index c32b5e323c0..a78e47d0229 100644
--- a/src/tools/clippy/tests/ui/infinite_loop.stderr
+++ b/src/tools/clippy/tests/ui/infinite_loop.stderr
@@ -1,5 +1,5 @@
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:24:11
+  --> $DIR/infinite_loop.rs:22:11
    |
 LL |     while y < 10 {
    |           ^^^^^^
@@ -8,7 +8,7 @@ LL |     while y < 10 {
    = note: `#[deny(clippy::while_immutable_condition)]` on by default
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:31:11
+  --> $DIR/infinite_loop.rs:29:11
    |
 LL |     while y < 10 && x < 3 {
    |           ^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     while y < 10 && x < 3 {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:40:11
+  --> $DIR/infinite_loop.rs:38:11
    |
 LL |     while !cond {
    |           ^^^^^
@@ -24,7 +24,7 @@ LL |     while !cond {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:86:11
+  --> $DIR/infinite_loop.rs:84:11
    |
 LL |     while i < 3 {
    |           ^^^^^
@@ -32,7 +32,7 @@ LL |     while i < 3 {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:93:11
+  --> $DIR/infinite_loop.rs:91:11
    |
 LL |     while i < 3 && j > 0 {
    |           ^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     while i < 3 && j > 0 {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:99:11
+  --> $DIR/infinite_loop.rs:97:11
    |
 LL |     while i < 3 {
    |           ^^^^^
@@ -48,7 +48,7 @@ LL |     while i < 3 {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:116:11
+  --> $DIR/infinite_loop.rs:114:11
    |
 LL |     while i < 3 {
    |           ^^^^^
@@ -56,7 +56,7 @@ LL |     while i < 3 {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:123:11
+  --> $DIR/infinite_loop.rs:121:11
    |
 LL |     while i < 3 {
    |           ^^^^^
@@ -64,7 +64,7 @@ LL |     while i < 3 {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:191:15
+  --> $DIR/infinite_loop.rs:189:15
    |
 LL |         while self.count < n {
    |               ^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL |         while self.count < n {
    = note: this may lead to an infinite or to a never running loop
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:201:11
+  --> $DIR/infinite_loop.rs:199:11
    |
 LL |     while y < 10 {
    |           ^^^^^^
@@ -82,7 +82,7 @@ LL |     while y < 10 {
    = help: rewrite it as `if cond { loop { } }`
 
 error: variables in the condition are not mutated in the loop body
-  --> $DIR/infinite_loop.rs:210:11
+  --> $DIR/infinite_loop.rs:208:11
    |
 LL |     while y < 10 {
    |           ^^^^^^
@@ -91,14 +91,5 @@ LL |     while y < 10 {
    = note: this loop contains `return`s or `break`s
    = help: rewrite it as `if cond { loop { } }`
 
-error: this argument is a mutable reference, but not used mutably
-  --> $DIR/infinite_loop.rs:9:17
-   |
-LL | fn fn_mutref(i: &mut i32) {
-   |                 ^^^^^^^^ help: consider changing to: `&i32`
-   |
-   = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
-
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.rs b/src/tools/clippy/tests/ui/into_iter_without_iter.rs
new file mode 100644
index 00000000000..6be3bb8abdd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/into_iter_without_iter.rs
@@ -0,0 +1,124 @@
+//@no-rustfix
+#![warn(clippy::into_iter_without_iter)]
+
+use std::iter::IntoIterator;
+
+fn main() {
+    {
+        struct S;
+
+        impl<'a> IntoIterator for &'a S {
+            //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
+            type IntoIter = std::slice::Iter<'a, u8>;
+            type Item = &'a u8;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+        impl<'a> IntoIterator for &'a mut S {
+            //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
+            type IntoIter = std::slice::IterMut<'a, u8>;
+            type Item = &'a mut u8;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+    {
+        struct S<T>(T);
+        impl<'a, T> IntoIterator for &'a S<T> {
+            //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
+            type IntoIter = std::slice::Iter<'a, T>;
+            type Item = &'a T;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+        impl<'a, T> IntoIterator for &'a mut S<T> {
+            //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
+            type IntoIter = std::slice::IterMut<'a, T>;
+            type Item = &'a mut T;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+    {
+        // Both iter and iter_mut methods exist, don't lint
+        struct S<'a, T>(&'a T);
+
+        impl<'a, T> S<'a, T> {
+            fn iter(&self) -> std::slice::Iter<'a, T> {
+                todo!()
+            }
+            fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
+                todo!()
+            }
+        }
+
+        impl<'a, T> IntoIterator for &S<'a, T> {
+            type IntoIter = std::slice::Iter<'a, T>;
+            type Item = &'a T;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+
+        impl<'a, T> IntoIterator for &mut S<'a, T> {
+            type IntoIter = std::slice::IterMut<'a, T>;
+            type Item = &'a mut T;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+    {
+        // Only `iter` exists, no `iter_mut`
+        struct S<'a, T>(&'a T);
+
+        impl<'a, T> S<'a, T> {
+            fn iter(&self) -> std::slice::Iter<'a, T> {
+                todo!()
+            }
+        }
+
+        impl<'a, T> IntoIterator for &S<'a, T> {
+            type IntoIter = std::slice::Iter<'a, T>;
+            type Item = &'a T;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+
+        impl<'a, T> IntoIterator for &mut S<'a, T> {
+            //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
+            type IntoIter = std::slice::IterMut<'a, T>;
+            type Item = &'a mut T;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+    {
+        // `iter` exists, but `IntoIterator` is implemented for an alias. inherent_impls doesn't "normalize"
+        // aliases so that `inherent_impls(Alias)` where `type Alias = S` returns nothing, so this can lead
+        // to fun FPs. Make sure it doesn't happen here (we're using type_of, which should skip the alias).
+        struct S;
+
+        impl S {
+            fn iter(&self) -> std::slice::Iter<'static, u8> {
+                todo!()
+            }
+        }
+
+        type Alias = S;
+
+        impl IntoIterator for &Alias {
+            type IntoIter = std::slice::Iter<'static, u8>;
+            type Item = &'static u8;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
new file mode 100644
index 00000000000..f543d1d8e86
--- /dev/null
+++ b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
@@ -0,0 +1,114 @@
+error: `IntoIterator` implemented for a reference type without an `iter` method
+  --> $DIR/into_iter_without_iter.rs:10:9
+   |
+LL | /         impl<'a> IntoIterator for &'a S {
+LL | |
+LL | |             type IntoIter = std::slice::Iter<'a, u8>;
+LL | |             type Item = &'a u8;
+...  |
+LL | |             }
+LL | |         }
+   | |_________^
+   |
+   = note: `-D clippy::into-iter-without-iter` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::into_iter_without_iter)]`
+help: consider implementing `iter`
+   |
+LL ~         
+LL + impl S {
+LL +     fn iter(&self) -> std::slice::Iter<'a, u8> {
+LL +         <&Self as IntoIterator>::into_iter(self)
+LL +     }
+LL + }
+   |
+
+error: `IntoIterator` implemented for a reference type without an `iter_mut` method
+  --> $DIR/into_iter_without_iter.rs:18:9
+   |
+LL | /         impl<'a> IntoIterator for &'a mut S {
+LL | |
+LL | |             type IntoIter = std::slice::IterMut<'a, u8>;
+LL | |             type Item = &'a mut u8;
+...  |
+LL | |             }
+LL | |         }
+   | |_________^
+   |
+help: consider implementing `iter_mut`
+   |
+LL ~         
+LL + impl S {
+LL +     fn iter_mut(&mut self) -> std::slice::IterMut<'a, u8> {
+LL +         <&mut Self as IntoIterator>::into_iter(self)
+LL +     }
+LL + }
+   |
+
+error: `IntoIterator` implemented for a reference type without an `iter` method
+  --> $DIR/into_iter_without_iter.rs:29:9
+   |
+LL | /         impl<'a, T> IntoIterator for &'a S<T> {
+LL | |
+LL | |             type IntoIter = std::slice::Iter<'a, T>;
+LL | |             type Item = &'a T;
+...  |
+LL | |             }
+LL | |         }
+   | |_________^
+   |
+help: consider implementing `iter`
+   |
+LL ~         
+LL + impl S<T> {
+LL +     fn iter(&self) -> std::slice::Iter<'a, T> {
+LL +         <&Self as IntoIterator>::into_iter(self)
+LL +     }
+LL + }
+   |
+
+error: `IntoIterator` implemented for a reference type without an `iter_mut` method
+  --> $DIR/into_iter_without_iter.rs:37:9
+   |
+LL | /         impl<'a, T> IntoIterator for &'a mut S<T> {
+LL | |
+LL | |             type IntoIter = std::slice::IterMut<'a, T>;
+LL | |             type Item = &'a mut T;
+...  |
+LL | |             }
+LL | |         }
+   | |_________^
+   |
+help: consider implementing `iter_mut`
+   |
+LL ~         
+LL + impl S<T> {
+LL +     fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
+LL +         <&mut Self as IntoIterator>::into_iter(self)
+LL +     }
+LL + }
+   |
+
+error: `IntoIterator` implemented for a reference type without an `iter_mut` method
+  --> $DIR/into_iter_without_iter.rs:93:9
+   |
+LL | /         impl<'a, T> IntoIterator for &mut S<'a, T> {
+LL | |
+LL | |             type IntoIter = std::slice::IterMut<'a, T>;
+LL | |             type Item = &'a mut T;
+...  |
+LL | |             }
+LL | |         }
+   | |_________^
+   |
+help: consider implementing `iter_mut`
+   |
+LL ~         
+LL + impl S<'a, T> {
+LL +     fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
+LL +         <&mut Self as IntoIterator>::into_iter(self)
+LL +     }
+LL + }
+   |
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs b/src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs
new file mode 100644
index 00000000000..d9c0aef88c8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/after_proc_macros.rs
@@ -0,0 +1,11 @@
+//@aux-build:../auxiliary/proc_macros.rs
+extern crate proc_macros;
+
+proc_macros::with_span! {
+    span
+    #[cfg(test)]
+    mod tests {}
+}
+
+#[test]
+fn f() {}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs b/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs
new file mode 100644
index 00000000000..69d61790121
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/submodule.rs
@@ -0,0 +1,4 @@
+#[cfg(test)]
+mod tests {}
+
+fn in_submodule() {}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
deleted file mode 100644
index 1b625747161..00000000000
--- a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: Option 'test' given more than once
-
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs
new file mode 100644
index 00000000000..7132e71764e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.rs
@@ -0,0 +1,8 @@
+#[path = "auxiliary/submodule.rs"]
+mod submodule;
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn t() {}
+}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr
new file mode 100644
index 00000000000..4e99876365c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr
@@ -0,0 +1,14 @@
+error: items after a test module
+  --> $DIR/auxiliary/submodule.rs:2:1
+   |
+LL | mod tests {}
+   | ^^^^^^^^^
+LL |
+LL | fn in_submodule() {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::items-after-test-module` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs b/src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs
new file mode 100644
index 00000000000..8ab9e8200f1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/multiple_modules.rs
@@ -0,0 +1,11 @@
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn f() {}
+}
+
+#[cfg(test)]
+mod more_tests {
+    #[test]
+    fn g() {}
+}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed
index 5136b2557ec..d444100a76b 100644
--- a/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs
+++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed
@@ -1,4 +1,3 @@
-//@compile-flags: --test
 #![allow(unused)]
 #![warn(clippy::items_after_test_module)]
 
@@ -6,6 +5,13 @@ fn main() {}
 
 fn should_not_lint() {}
 
+fn should_lint() {}
+
+const SHOULD_ALSO_LINT: usize = 1;
+macro_rules! should_lint {
+    () => {};
+}
+
 #[allow(dead_code)]
 #[allow(unused)] // Some attributes to check that span replacement is good enough
 #[allow(clippy::allow_attributes)]
@@ -14,10 +20,3 @@ mod tests {
     #[test]
     fn hi() {}
 }
-
-fn should_lint() {}
-
-const SHOULD_ALSO_LINT: usize = 1;
-macro_rules! should_not_lint {
-    () => {};
-}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs
new file mode 100644
index 00000000000..57da01639cc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs
@@ -0,0 +1,22 @@
+#![allow(unused)]
+#![warn(clippy::items_after_test_module)]
+
+fn main() {}
+
+fn should_not_lint() {}
+
+#[allow(dead_code)]
+#[allow(unused)] // Some attributes to check that span replacement is good enough
+#[allow(clippy::allow_attributes)]
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn hi() {}
+}
+
+fn should_lint() {}
+
+const SHOULD_ALSO_LINT: usize = 1;
+macro_rules! should_lint {
+    () => {};
+}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr
new file mode 100644
index 00000000000..67bc82ebff9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr
@@ -0,0 +1,20 @@
+error: items after a test module
+  --> $DIR/root_module.rs:12:1
+   |
+LL | mod tests {
+   | ^^^^^^^^^
+...
+LL | fn should_lint() {}
+   | ^^^^^^^^^^^^^^^^
+LL |
+LL | const SHOULD_ALSO_LINT: usize = 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | macro_rules! should_lint {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::items-after-test-module` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]`
+   = help: move the items to before the test module was defined
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.rs b/src/tools/clippy/tests/ui/iter_without_into_iter.rs
new file mode 100644
index 00000000000..cedb756c79d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_without_into_iter.rs
@@ -0,0 +1,120 @@
+//@no-rustfix
+#![warn(clippy::iter_without_into_iter)]
+
+fn main() {
+    {
+        struct S;
+        impl S {
+            pub fn iter(&self) -> std::slice::Iter<'_, u8> {
+                //~^ ERROR: `iter` method without an `IntoIterator` impl
+                [].iter()
+            }
+            pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
+                //~^ ERROR: `iter_mut` method without an `IntoIterator` impl
+                [].iter_mut()
+            }
+        }
+    }
+    {
+        struct S;
+        impl S {
+            pub fn iter(&self) -> impl Iterator<Item = &u8> {
+                // RPITIT is not stable, so we can't generally suggest it here yet
+                [].iter()
+            }
+        }
+    }
+    {
+        struct S<'a>(&'a mut [u8]);
+        impl<'a> S<'a> {
+            pub fn iter(&self) -> std::slice::Iter<'_, u8> {
+                //~^ ERROR: `iter` method without an `IntoIterator` impl
+                self.0.iter()
+            }
+            pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
+                //~^ ERROR: `iter_mut` method without an `IntoIterator` impl
+                self.0.iter_mut()
+            }
+        }
+    }
+    {
+        // Incompatible signatures
+        struct S;
+        impl S {
+            pub fn iter(self) -> std::slice::Iter<'static, u8> {
+                todo!()
+            }
+        }
+        struct S2;
+        impl S2 {
+            pub async fn iter(&self) -> std::slice::Iter<'static, u8> {
+                todo!()
+            }
+        }
+        struct S3;
+        impl S3 {
+            pub fn iter(&self, _additional_param: ()) -> std::slice::Iter<'static, u8> {
+                todo!()
+            }
+        }
+        struct S4<T>(T);
+        impl<T> S4<T> {
+            pub fn iter<U>(&self) -> std::slice::Iter<'static, (T, U)> {
+                todo!()
+            }
+        }
+        struct S5<T>(T);
+        impl<T> S5<T> {
+            pub fn iter(&self) -> std::slice::Iter<'static, T> {
+                todo!()
+            }
+        }
+    }
+    {
+        struct S<T>(T);
+        impl<T> S<T> {
+            pub fn iter(&self) -> std::slice::Iter<'_, T> {
+                //~^ ERROR: `iter` method without an `IntoIterator` impl
+                todo!()
+            }
+            pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
+                //~^ ERROR: `iter_mut` method without an `IntoIterator` impl
+                todo!()
+            }
+        }
+    }
+    {
+        struct S<T>(T);
+        impl<T> S<T> {
+            pub fn iter(&self) -> std::slice::Iter<'_, T> {
+                // Don't lint, there's an existing (wrong) IntoIterator impl
+                todo!()
+            }
+        }
+
+        impl<'a, T> IntoIterator for &'a S<T> {
+            type Item = &'a String;
+            type IntoIter = std::slice::Iter<'a, String>;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+    {
+        struct S<T>(T);
+        impl<T> S<T> {
+            pub fn iter_mut(&self) -> std::slice::IterMut<'_, T> {
+                // Don't lint, there's an existing (wrong) IntoIterator impl
+                todo!()
+            }
+        }
+
+        impl<'a, T> IntoIterator for &'a mut S<T> {
+            type Item = &'a mut String;
+            type IntoIter = std::slice::IterMut<'a, String>;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr
new file mode 100644
index 00000000000..9d0b99415a5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr
@@ -0,0 +1,150 @@
+error: `iter` method without an `IntoIterator` impl for `&S`
+  --> $DIR/iter_without_into_iter.rs:8:13
+   |
+LL | /             pub fn iter(&self) -> std::slice::Iter<'_, u8> {
+LL | |
+LL | |                 [].iter()
+LL | |             }
+   | |_____________^
+   |
+   = note: `-D clippy::iter-without-into-iter` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::iter_without_into_iter)]`
+help: consider implementing `IntoIterator` for `&S`
+   |
+LL ~         
+LL + impl IntoIterator for &S {
+LL +     type IntoIter = std::slice::Iter<'_, u8>;
+LL +     type Iter = &u8;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: `iter_mut` method without an `IntoIterator` impl for `&mut S`
+  --> $DIR/iter_without_into_iter.rs:12:13
+   |
+LL | /             pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
+LL | |
+LL | |                 [].iter_mut()
+LL | |             }
+   | |_____________^
+   |
+help: consider implementing `IntoIterator` for `&mut S`
+   |
+LL ~         
+LL + impl IntoIterator for &mut S {
+LL +     type IntoIter = std::slice::IterMut<'_, u8>;
+LL +     type Iter = &mut u8;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: `iter` method without an `IntoIterator` impl for `&S<'a>`
+  --> $DIR/iter_without_into_iter.rs:30:13
+   |
+LL | /             pub fn iter(&self) -> std::slice::Iter<'_, u8> {
+LL | |
+LL | |                 self.0.iter()
+LL | |             }
+   | |_____________^
+   |
+help: consider implementing `IntoIterator` for `&S<'a>`
+   |
+LL ~         
+LL + impl IntoIterator for &S<'a> {
+LL +     type IntoIter = std::slice::Iter<'_, u8>;
+LL +     type Iter = &u8;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: `iter_mut` method without an `IntoIterator` impl for `&mut S<'a>`
+  --> $DIR/iter_without_into_iter.rs:34:13
+   |
+LL | /             pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
+LL | |
+LL | |                 self.0.iter_mut()
+LL | |             }
+   | |_____________^
+   |
+help: consider implementing `IntoIterator` for `&mut S<'a>`
+   |
+LL ~         
+LL + impl IntoIterator for &mut S<'a> {
+LL +     type IntoIter = std::slice::IterMut<'_, u8>;
+LL +     type Iter = &mut u8;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: `iter` method without an `IntoIterator` impl for `&S5<T>`
+  --> $DIR/iter_without_into_iter.rs:68:13
+   |
+LL | /             pub fn iter(&self) -> std::slice::Iter<'static, T> {
+LL | |                 todo!()
+LL | |             }
+   | |_____________^
+   |
+help: consider implementing `IntoIterator` for `&S5<T>`
+   |
+LL ~         
+LL + impl IntoIterator for &S5<T> {
+LL +     type IntoIter = std::slice::Iter<'static, T>;
+LL +     type Iter = &T;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: `iter` method without an `IntoIterator` impl for `&S<T>`
+  --> $DIR/iter_without_into_iter.rs:76:13
+   |
+LL | /             pub fn iter(&self) -> std::slice::Iter<'_, T> {
+LL | |
+LL | |                 todo!()
+LL | |             }
+   | |_____________^
+   |
+help: consider implementing `IntoIterator` for `&S<T>`
+   |
+LL ~         
+LL + impl IntoIterator for &S<T> {
+LL +     type IntoIter = std::slice::Iter<'_, T>;
+LL +     type Iter = &T;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: `iter_mut` method without an `IntoIterator` impl for `&mut S<T>`
+  --> $DIR/iter_without_into_iter.rs:80:13
+   |
+LL | /             pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
+LL | |
+LL | |                 todo!()
+LL | |             }
+   | |_____________^
+   |
+help: consider implementing `IntoIterator` for `&mut S<T>`
+   |
+LL ~         
+LL + impl IntoIterator for &mut S<T> {
+LL +     type IntoIter = std::slice::IterMut<'_, T>;
+LL +     type Iter = &mut T;
+LL +     fn into_iter() -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/let_underscore_future.rs b/src/tools/clippy/tests/ui/let_underscore_future.rs
index 873ae667ab7..c2185e9785d 100644
--- a/src/tools/clippy/tests/ui/let_underscore_future.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_future.rs
@@ -9,8 +9,6 @@ fn custom() -> impl Future<Output = ()> {
 }
 
 fn do_something_to_future(future: &mut impl Future<Output = ()>) {}
-//~^ ERROR: this argument is a mutable reference, but not used mutably
-//~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
 
 fn main() {
     let _ = some_async_fn();
diff --git a/src/tools/clippy/tests/ui/let_underscore_future.stderr b/src/tools/clippy/tests/ui/let_underscore_future.stderr
index 3ba99c6377b..ef927a8083b 100644
--- a/src/tools/clippy/tests/ui/let_underscore_future.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_future.stderr
@@ -1,5 +1,5 @@
 error: non-binding `let` on a future
-  --> $DIR/let_underscore_future.rs:16:5
+  --> $DIR/let_underscore_future.rs:14:5
    |
 LL |     let _ = some_async_fn();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     let _ = some_async_fn();
    = help: to override `-D warnings` add `#[allow(clippy::let_underscore_future)]`
 
 error: non-binding `let` on a future
-  --> $DIR/let_underscore_future.rs:18:5
+  --> $DIR/let_underscore_future.rs:16:5
    |
 LL |     let _ = custom();
    |     ^^^^^^^^^^^^^^^^^
@@ -17,21 +17,12 @@ LL |     let _ = custom();
    = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
 
 error: non-binding `let` on a future
-  --> $DIR/let_underscore_future.rs:23:5
+  --> $DIR/let_underscore_future.rs:21:5
    |
 LL |     let _ = future;
    |     ^^^^^^^^^^^^^^^
    |
    = help: consider awaiting the future or dropping explicitly with `std::mem::drop`
 
-error: this argument is a mutable reference, but not used mutably
-  --> $DIR/let_underscore_future.rs:11:35
-   |
-LL | fn do_something_to_future(future: &mut impl Future<Output = ()>) {}
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&impl Future<Output = ()>`
-   |
-   = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_hash_one.fixed b/src/tools/clippy/tests/ui/manual_hash_one.fixed
new file mode 100644
index 00000000000..edfd9c4a47b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_hash_one.fixed
@@ -0,0 +1,89 @@
+#![warn(clippy::manual_hash_one)]
+#![allow(clippy::needless_borrows_for_generic_args)]
+
+use std::hash::{BuildHasher, Hash, Hasher};
+
+fn returned(b: impl BuildHasher) -> u64 {
+    
+    
+    b.hash_one(&true)
+}
+
+fn unsized_receiver(b: impl BuildHasher, s: &str) {
+    
+    
+    let _ = b.hash_one(&s[4..10]);
+}
+
+fn owned_value(b: impl BuildHasher, v: Vec<u32>) -> Vec<u32> {
+    
+    
+    let _ = b.hash_one(&v);
+    v
+}
+
+fn reused_hasher(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    let _ = hasher.finish();
+    let _ = hasher.finish();
+}
+
+fn reused_hasher_in_return(b: impl BuildHasher) -> u64 {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    let _ = hasher.finish();
+    hasher.finish()
+}
+
+fn no_hash(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    let _ = hasher.finish();
+}
+
+fn hash_twice(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    true.hash(&mut hasher);
+    let _ = hasher.finish();
+}
+
+fn other_hasher(b: impl BuildHasher) {
+    let mut other_hasher = b.build_hasher();
+
+    let mut hasher = b.build_hasher();
+    true.hash(&mut other_hasher);
+    let _ = hasher.finish();
+}
+
+fn finish_then_hash(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    let _ = hasher.finish();
+    true.hash(&mut hasher);
+}
+
+fn in_macro(b: impl BuildHasher) {
+    macro_rules! m {
+        ($b:expr) => {{
+            let mut hasher = $b.build_hasher();
+            true.hash(&mut hasher);
+            let _ = hasher.finish();
+        }};
+    }
+
+    m!(b);
+}
+
+#[clippy::msrv = "1.70"]
+fn msrv_1_70(b: impl BuildHasher, v: impl Hash) {
+    let mut hasher = b.build_hasher();
+    v.hash(&mut hasher);
+    let _ = hasher.finish();
+}
+
+#[clippy::msrv = "1.71"]
+fn msrv_1_71(b: impl BuildHasher, v: impl Hash) {
+    
+    
+    let _ = b.hash_one(&v);
+}
diff --git a/src/tools/clippy/tests/ui/manual_hash_one.rs b/src/tools/clippy/tests/ui/manual_hash_one.rs
new file mode 100644
index 00000000000..ee61522853f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_hash_one.rs
@@ -0,0 +1,89 @@
+#![warn(clippy::manual_hash_one)]
+#![allow(clippy::needless_borrows_for_generic_args)]
+
+use std::hash::{BuildHasher, Hash, Hasher};
+
+fn returned(b: impl BuildHasher) -> u64 {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    hasher.finish()
+}
+
+fn unsized_receiver(b: impl BuildHasher, s: &str) {
+    let mut hasher = b.build_hasher();
+    s[4..10].hash(&mut hasher);
+    let _ = hasher.finish();
+}
+
+fn owned_value(b: impl BuildHasher, v: Vec<u32>) -> Vec<u32> {
+    let mut hasher = b.build_hasher();
+    v.hash(&mut hasher);
+    let _ = hasher.finish();
+    v
+}
+
+fn reused_hasher(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    let _ = hasher.finish();
+    let _ = hasher.finish();
+}
+
+fn reused_hasher_in_return(b: impl BuildHasher) -> u64 {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    let _ = hasher.finish();
+    hasher.finish()
+}
+
+fn no_hash(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    let _ = hasher.finish();
+}
+
+fn hash_twice(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    true.hash(&mut hasher);
+    true.hash(&mut hasher);
+    let _ = hasher.finish();
+}
+
+fn other_hasher(b: impl BuildHasher) {
+    let mut other_hasher = b.build_hasher();
+
+    let mut hasher = b.build_hasher();
+    true.hash(&mut other_hasher);
+    let _ = hasher.finish();
+}
+
+fn finish_then_hash(b: impl BuildHasher) {
+    let mut hasher = b.build_hasher();
+    let _ = hasher.finish();
+    true.hash(&mut hasher);
+}
+
+fn in_macro(b: impl BuildHasher) {
+    macro_rules! m {
+        ($b:expr) => {{
+            let mut hasher = $b.build_hasher();
+            true.hash(&mut hasher);
+            let _ = hasher.finish();
+        }};
+    }
+
+    m!(b);
+}
+
+#[clippy::msrv = "1.70"]
+fn msrv_1_70(b: impl BuildHasher, v: impl Hash) {
+    let mut hasher = b.build_hasher();
+    v.hash(&mut hasher);
+    let _ = hasher.finish();
+}
+
+#[clippy::msrv = "1.71"]
+fn msrv_1_71(b: impl BuildHasher, v: impl Hash) {
+    let mut hasher = b.build_hasher();
+    v.hash(&mut hasher);
+    let _ = hasher.finish();
+}
diff --git a/src/tools/clippy/tests/ui/manual_hash_one.stderr b/src/tools/clippy/tests/ui/manual_hash_one.stderr
new file mode 100644
index 00000000000..3ce6f41e1f9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_hash_one.stderr
@@ -0,0 +1,56 @@
+error: manual implementation of `BuildHasher::hash_one`
+  --> $DIR/manual_hash_one.rs:9:5
+   |
+LL |     hasher.finish()
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::manual-hash-one` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_hash_one)]`
+help: try
+   |
+LL ~     
+LL ~     
+LL ~     b.hash_one(&true)
+   |
+
+error: manual implementation of `BuildHasher::hash_one`
+  --> $DIR/manual_hash_one.rs:15:13
+   |
+LL |     let _ = hasher.finish();
+   |             ^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~     
+LL ~     
+LL ~     let _ = b.hash_one(&s[4..10]);
+   |
+
+error: manual implementation of `BuildHasher::hash_one`
+  --> $DIR/manual_hash_one.rs:21:13
+   |
+LL |     let _ = hasher.finish();
+   |             ^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~     
+LL ~     
+LL ~     let _ = b.hash_one(&v);
+   |
+
+error: manual implementation of `BuildHasher::hash_one`
+  --> $DIR/manual_hash_one.rs:88:13
+   |
+LL |     let _ = hasher.finish();
+   |             ^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~     
+LL ~     
+LL ~     let _ = b.hash_one(&v);
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.fixed b/src/tools/clippy/tests/ui/manual_let_else_match.fixed
index 09b713f0410..588ba5edd8f 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.fixed
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.fixed
@@ -133,3 +133,7 @@ fn not_fire() {
         [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data,
     };
 }
+
+fn issue11579() {
+    let Some(msg) = Some("hi") else { unreachable!("can't happen") };
+}
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs
index e6af4738420..c37b5613ff7 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs
@@ -170,3 +170,11 @@ fn not_fire() {
         [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data,
     };
 }
+
+fn issue11579() {
+    let msg = match Some("hi") {
+        //~^ ERROR: this could be rewritten as `let...else`
+        Some(m) => m,
+        _ => unreachable!("can't happen"),
+    };
+}
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 8ca2c84072d..18bfe324ba7 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -92,5 +92,15 @@ LL | |         _ => return,
 LL | |     };
    | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };`
 
-error: aborting due to 9 previous errors
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:175:5
+   |
+LL | /     let msg = match Some("hi") {
+LL | |
+LL | |         Some(m) => m,
+LL | |         _ => unreachable!("can't happen"),
+LL | |     };
+   | |______^ help: consider writing: `let Some(msg) = Some("hi") else { unreachable!("can't happen") };`
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs
index 0e439dabfd6..e32ba863176 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs
@@ -10,10 +10,9 @@ enum E {
     _C,
 }
 
-// user forgot to remove the marker
+// if the user explicitly marks as nonexhaustive we shouldn't warn them
 #[non_exhaustive]
 enum Ep {
-    //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
     A,
     B,
     #[doc(hidden)]
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
index ce7e21c94bb..7361a4a2cbb 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
@@ -22,23 +22,5 @@ LL |     _C,
    = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]`
 
-error: this seems like a manual implementation of the non-exhaustive pattern
-  --> $DIR/manual_non_exhaustive_enum.rs:15:1
-   |
-LL | / enum Ep {
-LL | |
-LL | |     A,
-LL | |     B,
-LL | |     #[doc(hidden)]
-LL | |     _C,
-LL | | }
-   | |_^
-   |
-help: remove this variant
-  --> $DIR/manual_non_exhaustive_enum.rs:20:5
-   |
-LL |     _C,
-   |     ^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/mut_key.rs b/src/tools/clippy/tests/ui/mut_key.rs
index 80692132176..2d70bfd4c77 100644
--- a/src/tools/clippy/tests/ui/mut_key.rs
+++ b/src/tools/clippy/tests/ui/mut_key.rs
@@ -32,8 +32,6 @@ fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> HashSet<K
     //~^ ERROR: mutable key type
     //~| NOTE: `-D clippy::mutable-key-type` implied by `-D warnings`
     //~| ERROR: mutable key type
-    //~| ERROR: this argument is a mutable reference, but not used mutably
-    //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
     let _other: HashMap<Key, bool> = HashMap::new();
     //~^ ERROR: mutable key type
     m.keys().cloned().collect()
diff --git a/src/tools/clippy/tests/ui/mut_key.stderr b/src/tools/clippy/tests/ui/mut_key.stderr
index 3701769a9ca..48eeaff78a7 100644
--- a/src/tools/clippy/tests/ui/mut_key.stderr
+++ b/src/tools/clippy/tests/ui/mut_key.stderr
@@ -14,103 +14,94 @@ LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> Hash
    |                                                                        ^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:37:5
+  --> $DIR/mut_key.rs:35:5
    |
 LL |     let _other: HashMap<Key, bool> = HashMap::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:65:22
+  --> $DIR/mut_key.rs:63:22
    |
 LL | fn tuples_bad<U>(_m: &mut HashMap<(Key, U), bool>) {}
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:78:5
+  --> $DIR/mut_key.rs:76:5
    |
 LL |     let _map = HashMap::<Cell<usize>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:80:5
+  --> $DIR/mut_key.rs:78:5
    |
 LL |     let _map = HashMap::<&mut Cell<usize>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:82:5
+  --> $DIR/mut_key.rs:80:5
    |
 LL |     let _map = HashMap::<&mut usize, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:85:5
+  --> $DIR/mut_key.rs:83:5
    |
 LL |     let _map = HashMap::<Vec<Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:87:5
+  --> $DIR/mut_key.rs:85:5
    |
 LL |     let _map = HashMap::<BTreeMap<Cell<usize>, ()>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:89:5
+  --> $DIR/mut_key.rs:87:5
    |
 LL |     let _map = HashMap::<BTreeMap<(), Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:91:5
+  --> $DIR/mut_key.rs:89:5
    |
 LL |     let _map = HashMap::<BTreeSet<Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:93:5
+  --> $DIR/mut_key.rs:91:5
    |
 LL |     let _map = HashMap::<Option<Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:95:5
+  --> $DIR/mut_key.rs:93:5
    |
 LL |     let _map = HashMap::<Option<Vec<Cell<usize>>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:97:5
+  --> $DIR/mut_key.rs:95:5
    |
 LL |     let _map = HashMap::<Result<&mut usize, ()>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:100:5
+  --> $DIR/mut_key.rs:98:5
    |
 LL |     let _map = HashMap::<Box<Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:102:5
+  --> $DIR/mut_key.rs:100:5
    |
 LL |     let _map = HashMap::<Rc<Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: mutable key type
-  --> $DIR/mut_key.rs:104:5
+  --> $DIR/mut_key.rs:102:5
    |
 LL |     let _map = HashMap::<Arc<Cell<usize>>, usize>::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this argument is a mutable reference, but not used mutably
-  --> $DIR/mut_key.rs:31:32
-   |
-LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> HashSet<Key> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&HashMap<Key, usize>`
-   |
-   = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
-
-error: aborting due to 18 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mut_reference.rs b/src/tools/clippy/tests/ui/mut_reference.rs
index f3db226e4e7..1d7faaa5e75 100644
--- a/src/tools/clippy/tests/ui/mut_reference.rs
+++ b/src/tools/clippy/tests/ui/mut_reference.rs
@@ -22,8 +22,6 @@ impl MyStruct {
     fn takes_an_immutable_reference(&self, a: &i32) {}
 
     fn takes_a_mutable_reference(&self, a: &mut i32) {}
-    //~^ ERROR: this argument is a mutable reference, but not used mutably
-    //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
 }
 
 #[warn(clippy::unnecessary_mut_passed)]
diff --git a/src/tools/clippy/tests/ui/mut_reference.stderr b/src/tools/clippy/tests/ui/mut_reference.stderr
index d7a0d0c2252..87db08e2a74 100644
--- a/src/tools/clippy/tests/ui/mut_reference.stderr
+++ b/src/tools/clippy/tests/ui/mut_reference.stderr
@@ -1,5 +1,5 @@
 error: the function `takes_an_immutable_reference` doesn't need a mutable reference
-  --> $DIR/mut_reference.rs:32:34
+  --> $DIR/mut_reference.rs:30:34
    |
 LL |     takes_an_immutable_reference(&mut 42);
    |                                  ^^^^^^^
@@ -8,25 +8,16 @@ LL |     takes_an_immutable_reference(&mut 42);
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_mut_passed)]`
 
 error: the function `as_ptr` doesn't need a mutable reference
-  --> $DIR/mut_reference.rs:36:12
+  --> $DIR/mut_reference.rs:34:12
    |
 LL |     as_ptr(&mut 42);
    |            ^^^^^^^
 
 error: the method `takes_an_immutable_reference` doesn't need a mutable reference
-  --> $DIR/mut_reference.rs:41:44
+  --> $DIR/mut_reference.rs:39:44
    |
 LL |     my_struct.takes_an_immutable_reference(&mut 42);
    |                                            ^^^^^^^
 
-error: this argument is a mutable reference, but not used mutably
-  --> $DIR/mut_reference.rs:24:44
-   |
-LL |     fn takes_a_mutable_reference(&self, a: &mut i32) {}
-   |                                            ^^^^^^^^ help: consider changing to: `&i32`
-   |
-   = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
index 9cddcb3df23..39d76f99900 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
@@ -1,4 +1,5 @@
 #![allow(clippy::if_same_then_else, clippy::no_effect, clippy::redundant_closure_call)]
+#![warn(clippy::needless_pass_by_ref_mut)]
 #![feature(lint_reasons)]
 //@no-rustfix
 use std::ptr::NonNull;
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
index 0c7fbd5df6d..aa937c3f6af 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
@@ -1,5 +1,5 @@
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:6:11
+  --> $DIR/needless_pass_by_ref_mut.rs:7:11
    |
 LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    |           ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
@@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:31:12
+  --> $DIR/needless_pass_by_ref_mut.rs:32:12
    |
 LL | fn foo6(s: &mut Vec<u32>) {
    |            ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:44:29
+  --> $DIR/needless_pass_by_ref_mut.rs:45:29
    |
 LL |     fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
    |                             ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:49:31
+  --> $DIR/needless_pass_by_ref_mut.rs:50:31
    |
 LL |     fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
    |                               ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:126:16
+  --> $DIR/needless_pass_by_ref_mut.rs:127:16
    |
 LL | async fn a1(x: &mut i32) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:130:16
+  --> $DIR/needless_pass_by_ref_mut.rs:131:16
    |
 LL | async fn a2(x: &mut i32, y: String) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:134:16
+  --> $DIR/needless_pass_by_ref_mut.rs:135:16
    |
 LL | async fn a3(x: &mut i32, y: String, z: String) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:138:16
+  --> $DIR/needless_pass_by_ref_mut.rs:139:16
    |
 LL | async fn a4(x: &mut i32, y: i32) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:142:24
+  --> $DIR/needless_pass_by_ref_mut.rs:143:24
    |
 LL | async fn a5(x: i32, y: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:146:24
+  --> $DIR/needless_pass_by_ref_mut.rs:147:24
    |
 LL | async fn a6(x: i32, y: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:150:32
+  --> $DIR/needless_pass_by_ref_mut.rs:151:32
    |
 LL | async fn a7(x: i32, y: i32, z: &mut i32) {
    |                                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:154:24
+  --> $DIR/needless_pass_by_ref_mut.rs:155:24
    |
 LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:154:45
+  --> $DIR/needless_pass_by_ref_mut.rs:155:45
    |
 LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
    |                                             ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:188:16
+  --> $DIR/needless_pass_by_ref_mut.rs:189:16
    |
 LL | fn cfg_warn(s: &mut u32) {}
    |                ^^^^^^^^ help: consider changing to: `&u32`
@@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {}
    = note: this is cfg-gated and may require further changes
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:194:20
+  --> $DIR/needless_pass_by_ref_mut.rs:195:20
    |
 LL |     fn cfg_warn(s: &mut u32) {}
    |                    ^^^^^^^^ help: consider changing to: `&u32`
@@ -96,19 +96,19 @@ LL |     fn cfg_warn(s: &mut u32) {}
    = note: this is cfg-gated and may require further changes
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:208:39
+  --> $DIR/needless_pass_by_ref_mut.rs:209:39
    |
 LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
    |                                       ^^^^^^^^ help: consider changing to: `&u32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:216:26
+  --> $DIR/needless_pass_by_ref_mut.rs:217:26
    |
 LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
    |                          ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:235:34
+  --> $DIR/needless_pass_by_ref_mut.rs:236:34
    |
 LL | pub async fn call_in_closure1(n: &mut str) {
    |                                  ^^^^^^^^ help: consider changing to: `&str`
@@ -116,7 +116,7 @@ LL | pub async fn call_in_closure1(n: &mut str) {
    = warning: changing this function will impact semver compatibility
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:247:25
+  --> $DIR/needless_pass_by_ref_mut.rs:248:25
    |
 LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() {
    |                         ^^^^^^^^^^ help: consider changing to: `&usize`
@@ -124,7 +124,7 @@ LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() {
    = warning: changing this function will impact semver compatibility
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:254:20
+  --> $DIR/needless_pass_by_ref_mut.rs:255:20
    |
 LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
    |                    ^^^^^^^^^^ help: consider changing to: `&usize`
@@ -132,7 +132,7 @@ LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
    = warning: changing this function will impact semver compatibility
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:265:26
+  --> $DIR/needless_pass_by_ref_mut.rs:266:26
    |
 LL | pub async fn closure4(n: &mut usize) {
    |                          ^^^^^^^^^^ help: consider changing to: `&usize`
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.fixed b/src/tools/clippy/tests/ui/needless_raw_string.fixed
index 85549810513..4ea711fd67a 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string.fixed
+++ b/src/tools/clippy/tests/ui/needless_raw_string.fixed
@@ -18,4 +18,8 @@ fn main() {
         multiline
         string
     ";
+
+    "no hashes";
+    b"no hashes";
+    c"no hashes";
 }
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.rs b/src/tools/clippy/tests/ui/needless_raw_string.rs
index 06d49730387..b6239f9b1f0 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string.rs
+++ b/src/tools/clippy/tests/ui/needless_raw_string.rs
@@ -18,4 +18,8 @@ fn main() {
         multiline
         string
     "#;
+
+    r"no hashes";
+    br"no hashes";
+    cr"no hashes";
 }
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.stderr b/src/tools/clippy/tests/ui/needless_raw_string.stderr
index e6806b31b1d..276bc84c6c3 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string.stderr
+++ b/src/tools/clippy/tests/ui/needless_raw_string.stderr
@@ -6,7 +6,7 @@ LL |     r#"aaa"#;
    |
    = note: `-D clippy::needless-raw-strings` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]`
-help: try
+help: use a plain string literal instead
    |
 LL -     r#"aaa"#;
 LL +     "aaa";
@@ -18,7 +18,7 @@ error: unnecessary raw string literal
 LL |     br#"aaa"#;
    |     ^^^^^^^^^
    |
-help: try
+help: use a plain byte string literal instead
    |
 LL -     br#"aaa"#;
 LL +     b"aaa";
@@ -30,7 +30,7 @@ error: unnecessary raw string literal
 LL |     cr#"aaa"#;
    |     ^^^^^^^^^
    |
-help: try
+help: use a plain C string literal instead
    |
 LL -     cr#"aaa"#;
 LL +     c"aaa";
@@ -46,7 +46,7 @@ LL | |         string
 LL | |     "#;
    | |______^
    |
-help: try
+help: use a plain string literal instead
    |
 LL ~     "
 LL |         a
@@ -55,5 +55,41 @@ LL |         string
 LL ~     ";
    |
 
-error: aborting due to 4 previous errors
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:22:5
+   |
+LL |     r"no hashes";
+   |     ^^^^^^^^^^^^
+   |
+help: use a plain string literal instead
+   |
+LL -     r"no hashes";
+LL +     "no hashes";
+   |
+
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:23:5
+   |
+LL |     br"no hashes";
+   |     ^^^^^^^^^^^^^
+   |
+help: use a plain byte string literal instead
+   |
+LL -     br"no hashes";
+LL +     b"no hashes";
+   |
+
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:24:5
+   |
+LL |     cr"no hashes";
+   |     ^^^^^^^^^^^^^
+   |
+help: use a plain C string literal instead
+   |
+LL -     cr"no hashes";
+LL +     c"no hashes";
+   |
+
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
index 4399c6555c2..017160b1a42 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
@@ -6,7 +6,7 @@ LL |     r#"\aaa"#;
    |
    = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_raw_string_hashes)]`
-help: remove all the hashes around the literal
+help: remove all the hashes around the string literal
    |
 LL -     r#"\aaa"#;
 LL +     r"\aaa";
@@ -18,7 +18,7 @@ error: unnecessary hashes around raw string literal
 LL |     r##"Hello "world"!"##;
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove one hash from both sides of the literal
+help: remove one hash from both sides of the string literal
    |
 LL -     r##"Hello "world"!"##;
 LL +     r#"Hello "world"!"#;
@@ -30,7 +30,7 @@ error: unnecessary hashes around raw string literal
 LL |     r######" "### "## "# "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove 2 hashes from both sides of the literal
+help: remove 2 hashes from both sides of the string literal
    |
 LL -     r######" "### "## "# "######;
 LL +     r####" "### "## "# "####;
@@ -42,7 +42,7 @@ error: unnecessary hashes around raw string literal
 LL |     r######" "aa" "# "## "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove 3 hashes from both sides of the literal
+help: remove 3 hashes from both sides of the string literal
    |
 LL -     r######" "aa" "# "## "######;
 LL +     r###" "aa" "# "## "###;
@@ -54,7 +54,7 @@ error: unnecessary hashes around raw string literal
 LL |     br#"\aaa"#;
    |     ^^^^^^^^^^
    |
-help: remove all the hashes around the literal
+help: remove all the hashes around the byte string literal
    |
 LL -     br#"\aaa"#;
 LL +     br"\aaa";
@@ -66,7 +66,7 @@ error: unnecessary hashes around raw string literal
 LL |     br##"Hello "world"!"##;
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove one hash from both sides of the literal
+help: remove one hash from both sides of the byte string literal
    |
 LL -     br##"Hello "world"!"##;
 LL +     br#"Hello "world"!"#;
@@ -78,7 +78,7 @@ error: unnecessary hashes around raw string literal
 LL |     br######" "### "## "# "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove 2 hashes from both sides of the literal
+help: remove 2 hashes from both sides of the byte string literal
    |
 LL -     br######" "### "## "# "######;
 LL +     br####" "### "## "# "####;
@@ -90,7 +90,7 @@ error: unnecessary hashes around raw string literal
 LL |     br######" "aa" "# "## "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove 3 hashes from both sides of the literal
+help: remove 3 hashes from both sides of the byte string literal
    |
 LL -     br######" "aa" "# "## "######;
 LL +     br###" "aa" "# "## "###;
@@ -102,7 +102,7 @@ error: unnecessary hashes around raw string literal
 LL |     cr#"\aaa"#;
    |     ^^^^^^^^^^
    |
-help: remove all the hashes around the literal
+help: remove all the hashes around the C string literal
    |
 LL -     cr#"\aaa"#;
 LL +     cr"\aaa";
@@ -114,7 +114,7 @@ error: unnecessary hashes around raw string literal
 LL |     cr##"Hello "world"!"##;
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove one hash from both sides of the literal
+help: remove one hash from both sides of the C string literal
    |
 LL -     cr##"Hello "world"!"##;
 LL +     cr#"Hello "world"!"#;
@@ -126,7 +126,7 @@ error: unnecessary hashes around raw string literal
 LL |     cr######" "### "## "# "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove 2 hashes from both sides of the literal
+help: remove 2 hashes from both sides of the C string literal
    |
 LL -     cr######" "### "## "# "######;
 LL +     cr####" "### "## "# "####;
@@ -138,7 +138,7 @@ error: unnecessary hashes around raw string literal
 LL |     cr######" "aa" "# "## "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: remove 3 hashes from both sides of the literal
+help: remove 3 hashes from both sides of the C string literal
    |
 LL -     cr######" "aa" "# "## "######;
 LL +     cr###" "aa" "# "## "###;
@@ -154,7 +154,7 @@ LL | |         string
 LL | |     "#;
    | |______^
    |
-help: remove all the hashes around the literal
+help: remove all the hashes around the string literal
    |
 LL ~     r"
 LL |         \a
@@ -169,7 +169,7 @@ error: unnecessary hashes around raw string literal
 LL |     r###"rust"###;
    |     ^^^^^^^^^^^^^
    |
-help: remove all the hashes around the literal
+help: remove all the hashes around the string literal
    |
 LL -     r###"rust"###;
 LL +     r"rust";
@@ -181,7 +181,7 @@ error: unnecessary hashes around raw string literal
 LL |     r#"hello world"#;
    |     ^^^^^^^^^^^^^^^^
    |
-help: remove all the hashes around the literal
+help: remove all the hashes around the string literal
    |
 LL -     r#"hello world"#;
 LL +     r"hello world";
diff --git a/src/tools/clippy/tests/ui/print_literal.fixed b/src/tools/clippy/tests/ui/print_literal.fixed
index 88cd3a54b41..a7157c07f8a 100644
--- a/src/tools/clippy/tests/ui/print_literal.fixed
+++ b/src/tools/clippy/tests/ui/print_literal.fixed
@@ -39,20 +39,30 @@ fn main() {
     // throw a warning
     println!("hello world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     println!("world hello");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
 
     // named args shouldn't change anything either
     println!("hello world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     println!("world hello");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
 
     // The string literal from `file!()` has a callsite span that isn't marked as coming from an
     // expansion
     println!("file: {}", file!());
+
+    // Braces in unicode escapes should not be escaped
+    println!("{{}} \x00 \u{ab123} \\\u{ab123} {{:?}}");
+    println!("\\\u{1234}");
+    // This does not lint because it would have to suggest unescaping the character
+    println!(r"{}", "\u{ab123}");
+    // These are not unicode escapes
+    println!("\\u{{ab123}} \\u{{{{");
+    println!(r"\u{{ab123}} \u{{{{");
+    println!("\\{{ab123}} \\u{{{{");
+    println!("\\u{{ab123}}");
+    println!("\\\\u{{1234}}");
+
+    println!("mixed: {{hello}} {world}");
 }
diff --git a/src/tools/clippy/tests/ui/print_literal.rs b/src/tools/clippy/tests/ui/print_literal.rs
index bd7444c9606..4b04b42744c 100644
--- a/src/tools/clippy/tests/ui/print_literal.rs
+++ b/src/tools/clippy/tests/ui/print_literal.rs
@@ -39,20 +39,30 @@ fn main() {
     // throw a warning
     println!("{0} {1}", "hello", "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     println!("{1} {0}", "hello", "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
 
     // named args shouldn't change anything either
     println!("{foo} {bar}", foo = "hello", bar = "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     println!("{bar} {foo}", foo = "hello", bar = "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
 
     // The string literal from `file!()` has a callsite span that isn't marked as coming from an
     // expansion
     println!("file: {}", file!());
+
+    // Braces in unicode escapes should not be escaped
+    println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}");
+    println!("{}", "\\\u{1234}");
+    // This does not lint because it would have to suggest unescaping the character
+    println!(r"{}", "\u{ab123}");
+    // These are not unicode escapes
+    println!("{}", r"\u{ab123} \u{{");
+    println!(r"{}", r"\u{ab123} \u{{");
+    println!("{}", r"\{ab123} \u{{");
+    println!("{}", "\\u{ab123}");
+    println!("{}", "\\\\u{1234}");
+
+    println!("mixed: {} {world}", "{hello}");
 }
diff --git a/src/tools/clippy/tests/ui/print_literal.stderr b/src/tools/clippy/tests/ui/print_literal.stderr
index 1d9751b92e9..8c011d7bc0a 100644
--- a/src/tools/clippy/tests/ui/print_literal.stderr
+++ b/src/tools/clippy/tests/ui/print_literal.stderr
@@ -52,97 +52,145 @@ error: literal with an empty format string
   --> $DIR/print_literal.rs:40:25
    |
 LL |     println!("{0} {1}", "hello", "world");
-   |                         ^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^
    |
 help: try
    |
 LL -     println!("{0} {1}", "hello", "world");
-LL +     println!("hello {1}", "world");
+LL +     println!("hello world");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:40:34
+  --> $DIR/print_literal.rs:42:25
    |
-LL |     println!("{0} {1}", "hello", "world");
-   |                                  ^^^^^^^
+LL |     println!("{1} {0}", "hello", "world");
+   |                         ^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{0} {1}", "hello", "world");
-LL +     println!("{0} world", "hello");
+LL -     println!("{1} {0}", "hello", "world");
+LL +     println!("world hello");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:43:34
+  --> $DIR/print_literal.rs:46:35
    |
-LL |     println!("{1} {0}", "hello", "world");
-   |                                  ^^^^^^^
+LL |     println!("{foo} {bar}", foo = "hello", bar = "world");
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{1} {0}", "hello", "world");
-LL +     println!("world {0}", "hello");
+LL -     println!("{foo} {bar}", foo = "hello", bar = "world");
+LL +     println!("hello world");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:43:25
+  --> $DIR/print_literal.rs:48:35
    |
-LL |     println!("{1} {0}", "hello", "world");
-   |                         ^^^^^^^
+LL |     println!("{bar} {foo}", foo = "hello", bar = "world");
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{1} {0}", "hello", "world");
-LL +     println!("{1} hello", "world");
+LL -     println!("{bar} {foo}", foo = "hello", bar = "world");
+LL +     println!("world hello");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:48:35
+  --> $DIR/print_literal.rs:56:20
    |
-LL |     println!("{foo} {bar}", foo = "hello", bar = "world");
-   |                                   ^^^^^^^
+LL |     println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}");
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{foo} {bar}", foo = "hello", bar = "world");
-LL +     println!("hello {bar}", bar = "world");
+LL -     println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}");
+LL +     println!("{{}} \x00 \u{ab123} \\\u{ab123} {{:?}}");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:48:50
+  --> $DIR/print_literal.rs:57:20
    |
-LL |     println!("{foo} {bar}", foo = "hello", bar = "world");
-   |                                                  ^^^^^^^
+LL |     println!("{}", "\\\u{1234}");
+   |                    ^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{foo} {bar}", foo = "hello", bar = "world");
-LL +     println!("{foo} world", foo = "hello");
+LL -     println!("{}", "\\\u{1234}");
+LL +     println!("\\\u{1234}");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:51:50
+  --> $DIR/print_literal.rs:61:20
    |
-LL |     println!("{bar} {foo}", foo = "hello", bar = "world");
-   |                                                  ^^^^^^^
+LL |     println!("{}", r"\u{ab123} \u{{");
+   |                    ^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{bar} {foo}", foo = "hello", bar = "world");
-LL +     println!("world {foo}", foo = "hello");
+LL -     println!("{}", r"\u{ab123} \u{{");
+LL +     println!("\\u{{ab123}} \\u{{{{");
    |
 
 error: literal with an empty format string
-  --> $DIR/print_literal.rs:51:35
+  --> $DIR/print_literal.rs:62:21
    |
-LL |     println!("{bar} {foo}", foo = "hello", bar = "world");
-   |                                   ^^^^^^^
+LL |     println!(r"{}", r"\u{ab123} \u{{");
+   |                     ^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     println!("{bar} {foo}", foo = "hello", bar = "world");
-LL +     println!("{bar} hello", bar = "world");
+LL -     println!(r"{}", r"\u{ab123} \u{{");
+LL +     println!(r"\u{{ab123}} \u{{{{");
+   |
+
+error: literal with an empty format string
+  --> $DIR/print_literal.rs:63:20
+   |
+LL |     println!("{}", r"\{ab123} \u{{");
+   |                    ^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL -     println!("{}", r"\{ab123} \u{{");
+LL +     println!("\\{{ab123}} \\u{{{{");
+   |
+
+error: literal with an empty format string
+  --> $DIR/print_literal.rs:64:20
+   |
+LL |     println!("{}", "\\u{ab123}");
+   |                    ^^^^^^^^^^^^
+   |
+help: try
+   |
+LL -     println!("{}", "\\u{ab123}");
+LL +     println!("\\u{{ab123}}");
+   |
+
+error: literal with an empty format string
+  --> $DIR/print_literal.rs:65:20
+   |
+LL |     println!("{}", "\\\\u{1234}");
+   |                    ^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL -     println!("{}", "\\\\u{1234}");
+LL +     println!("\\\\u{{1234}}");
+   |
+
+error: literal with an empty format string
+  --> $DIR/print_literal.rs:67:35
+   |
+LL |     println!("mixed: {} {world}", "{hello}");
+   |                                   ^^^^^^^^^
+   |
+help: try
+   |
+LL -     println!("mixed: {} {world}", "{hello}");
+LL +     println!("mixed: {{hello}} {world}");
    |
 
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs
index c5d93e4365d..e81db300f15 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.rs
+++ b/src/tools/clippy/tests/ui/redundant_locals.rs
@@ -118,3 +118,40 @@ fn macros() {
         let x = x;
     }
 }
+
+struct WithDrop(usize);
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+struct InnerDrop(WithDrop);
+
+struct ComposeDrop {
+    d: WithDrop,
+}
+
+struct WithoutDrop(usize);
+
+fn drop_trait() {
+    let a = WithDrop(1);
+    let b = WithDrop(2);
+    let a = a;
+}
+
+fn without_drop() {
+    let a = WithoutDrop(1);
+    let b = WithoutDrop(2);
+    let a = a;
+}
+
+fn drop_inner() {
+    let a = InnerDrop(WithDrop(1));
+    let b = InnerDrop(WithDrop(2));
+    let a = a;
+}
+
+fn drop_compose() {
+    let a = ComposeDrop { d: WithDrop(1) };
+    let b = ComposeDrop { d: WithDrop(1) };
+    let a = a;
+}
diff --git a/src/tools/clippy/tests/ui/redundant_locals.stderr b/src/tools/clippy/tests/ui/redundant_locals.stderr
index 13b872e9576..d794a87fe7d 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.stderr
+++ b/src/tools/clippy/tests/ui/redundant_locals.stderr
@@ -1,137 +1,172 @@
-error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:11:9
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:12:5
    |
-LL |     let x = 1;
-   |         ^
 LL |     let x = x;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
+help: `x` is initially defined here
+  --> $DIR/redundant_locals.rs:11:9
+   |
+LL |     let x = 1;
+   |         ^
    = note: `-D clippy::redundant-locals` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::redundant_locals)]`
 
-error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:16:9
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:17:5
    |
-LL |     let mut x = 1;
-   |         ^^^^^
 LL |     let mut x = x;
    |     ^^^^^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
+help: `x` is initially defined here
+  --> $DIR/redundant_locals.rs:16:9
+   |
+LL |     let mut x = 1;
+   |         ^^^^^
 
-error: redundant redefinition of a binding
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:47:5
+   |
+LL |     let x = x;
+   |     ^^^^^^^^^^
+   |
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:46:14
    |
 LL | fn parameter(x: i32) {
    |              ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:52:5
+   |
 LL |     let x = x;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:51:9
    |
 LL |     let x = 1;
    |         ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:53:5
+   |
 LL |     let x = x;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:52:9
    |
 LL |     let x = x;
    |         ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:54:5
+   |
 LL |     let x = x;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:53:9
    |
 LL |     let x = x;
    |         ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:55:5
+   |
 LL |     let x = x;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:54:9
    |
 LL |     let x = x;
    |         ^
-LL |     let x = x;
+
+error: redundant redefinition of a binding `a`
+  --> $DIR/redundant_locals.rs:61:5
+   |
+LL |     let a = a;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `a` is initially defined here
   --> $DIR/redundant_locals.rs:59:9
    |
 LL |     let a = 1;
    |         ^
-LL |     let b = 2;
-LL |     let a = a;
+
+error: redundant redefinition of a binding `b`
+  --> $DIR/redundant_locals.rs:62:5
+   |
+LL |     let b = b;
    |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `a`
-
-error: redundant redefinition of a binding
+help: `b` is initially defined here
   --> $DIR/redundant_locals.rs:60:9
    |
 LL |     let b = 2;
    |         ^
-LL |     let a = a;
-LL |     let b = b;
-   |     ^^^^^^^^^^
-   |
-   = help: remove the redefinition of `b`
 
-error: redundant redefinition of a binding
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:68:9
+   |
+LL |         let x = x;
+   |         ^^^^^^^^^^
+   |
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:67:13
    |
 LL |         let x = 1;
    |             ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:75:9
+   |
 LL |         let x = x;
    |         ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:74:13
    |
 LL |         let x = 1;
    |             ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:78:9
+   |
 LL |         let x = x;
    |         ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:77:6
    |
 LL |     |x: i32| {
    |      ^
+
+error: redundant redefinition of a binding `x`
+  --> $DIR/redundant_locals.rs:97:9
+   |
 LL |         let x = x;
    |         ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
-
-error: redundant redefinition of a binding
+help: `x` is initially defined here
   --> $DIR/redundant_locals.rs:94:9
    |
 LL |     let x = 1;
    |         ^
-...
-LL |         let x = x;
-   |         ^^^^^^^^^^
+
+error: redundant redefinition of a binding `a`
+  --> $DIR/redundant_locals.rs:144:5
+   |
+LL |     let a = a;
+   |     ^^^^^^^^^^
    |
-   = help: remove the redefinition of `x`
+help: `a` is initially defined here
+  --> $DIR/redundant_locals.rs:142:9
+   |
+LL |     let a = WithoutDrop(1);
+   |         ^
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
index 550ec007268..33211b32d74 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
@@ -40,8 +40,6 @@ impl T {
 
     pub fn hash(&self, state: &mut T) {
         //~^ ERROR: method `hash` can be confused for the standard trait method `std::hash::Ha
-        //~| ERROR: this argument is a mutable reference, but not used mutably
-        //~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
         unimplemented!()
     }
 
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
index 79afddea247..c257f411342 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
@@ -38,8 +38,6 @@ error: method `hash` can be confused for the standard trait method `std::hash::H
    |
 LL | /     pub fn hash(&self, state: &mut T) {
 LL | |
-LL | |
-LL | |
 LL | |         unimplemented!()
 LL | |     }
    | |_____^
@@ -47,7 +45,7 @@ LL | |     }
    = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
 
 error: method `index` can be confused for the standard trait method `std::ops::Index::index`
-  --> $DIR/method_list_2.rs:48:5
+  --> $DIR/method_list_2.rs:46:5
    |
 LL | /     pub fn index(&self, index: usize) -> &Self {
 LL | |
@@ -58,7 +56,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
 
 error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
-  --> $DIR/method_list_2.rs:53:5
+  --> $DIR/method_list_2.rs:51:5
    |
 LL | /     pub fn index_mut(&mut self, index: usize) -> &mut Self {
 LL | |
@@ -69,7 +67,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
 
 error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
-  --> $DIR/method_list_2.rs:58:5
+  --> $DIR/method_list_2.rs:56:5
    |
 LL | /     pub fn into_iter(self) -> Self {
 LL | |
@@ -80,7 +78,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
 
 error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
-  --> $DIR/method_list_2.rs:63:5
+  --> $DIR/method_list_2.rs:61:5
    |
 LL | /     pub fn mul(self, rhs: Self) -> Self {
 LL | |
@@ -91,7 +89,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
 
 error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
-  --> $DIR/method_list_2.rs:68:5
+  --> $DIR/method_list_2.rs:66:5
    |
 LL | /     pub fn neg(self) -> Self {
 LL | |
@@ -102,7 +100,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
 
 error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
-  --> $DIR/method_list_2.rs:73:5
+  --> $DIR/method_list_2.rs:71:5
    |
 LL | /     pub fn next(&mut self) -> Option<Self> {
 LL | |
@@ -113,7 +111,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
 
 error: method `not` can be confused for the standard trait method `std::ops::Not::not`
-  --> $DIR/method_list_2.rs:78:5
+  --> $DIR/method_list_2.rs:76:5
    |
 LL | /     pub fn not(self) -> Self {
 LL | |
@@ -124,7 +122,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
 
 error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
-  --> $DIR/method_list_2.rs:83:5
+  --> $DIR/method_list_2.rs:81:5
    |
 LL | /     pub fn rem(self, rhs: Self) -> Self {
 LL | |
@@ -135,7 +133,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
 
 error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
-  --> $DIR/method_list_2.rs:88:5
+  --> $DIR/method_list_2.rs:86:5
    |
 LL | /     pub fn shl(self, rhs: Self) -> Self {
 LL | |
@@ -146,7 +144,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
 
 error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
-  --> $DIR/method_list_2.rs:93:5
+  --> $DIR/method_list_2.rs:91:5
    |
 LL | /     pub fn shr(self, rhs: Self) -> Self {
 LL | |
@@ -157,7 +155,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
 
 error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
-  --> $DIR/method_list_2.rs:98:5
+  --> $DIR/method_list_2.rs:96:5
    |
 LL | /     pub fn sub(self, rhs: Self) -> Self {
 LL | |
@@ -167,15 +165,5 @@ LL | |     }
    |
    = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name
 
-error: this argument is a mutable reference, but not used mutably
-  --> $DIR/method_list_2.rs:41:31
-   |
-LL |     pub fn hash(&self, state: &mut T) {
-   |                               ^^^^^^ help: consider changing to: `&T`
-   |
-   = warning: changing this function will impact semver compatibility
-   = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
-
-error: aborting due to 16 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/slow_vector_initialization.rs b/src/tools/clippy/tests/ui/slow_vector_initialization.rs
index 5c3086c9d69..16f81019574 100644
--- a/src/tools/clippy/tests/ui/slow_vector_initialization.rs
+++ b/src/tools/clippy/tests/ui/slow_vector_initialization.rs
@@ -103,8 +103,6 @@ fn from_empty_vec() {
 }
 
 fn do_stuff(vec: &mut [u8]) {}
-//~^ ERROR: this argument is a mutable reference, but not used mutably
-//~| NOTE: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
 
 fn extend_vector_with_manipulations_between() {
     let len = 300;
diff --git a/src/tools/clippy/tests/ui/slow_vector_initialization.stderr b/src/tools/clippy/tests/ui/slow_vector_initialization.stderr
index 4d24400ecb5..16a7057653c 100644
--- a/src/tools/clippy/tests/ui/slow_vector_initialization.stderr
+++ b/src/tools/clippy/tests/ui/slow_vector_initialization.stderr
@@ -105,14 +105,5 @@ LL |     vec1 = vec![];
 LL |     vec1.resize(10, 0);
    |     ^^^^^^^^^^^^^^^^^^
 
-error: this argument is a mutable reference, but not used mutably
-  --> $DIR/slow_vector_initialization.rs:105:18
-   |
-LL | fn do_stuff(vec: &mut [u8]) {}
-   |                  ^^^^^^^^^ help: consider changing to: `&[u8]`
-   |
-   = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
-
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
index 8027c053fb5..a7555704fbe 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
@@ -1,8 +1,12 @@
+//@aux-build:proc_macro_derive.rs
 #![warn(clippy::std_instead_of_core)]
 #![allow(unused_imports)]
 
 extern crate alloc;
 
+#[macro_use]
+extern crate proc_macro_derive;
+
 #[warn(clippy::std_instead_of_core)]
 fn std_instead_of_core() {
     // Regular import
@@ -55,6 +59,13 @@ fn alloc_instead_of_core() {
     //~^ ERROR: used import from `alloc` instead of `core`
 }
 
+mod std_in_proc_macro_derive {
+    #[warn(clippy::alloc_instead_of_core)]
+    #[allow(unused)]
+    #[derive(ImplStructWithStdDisplay)]
+    struct B {}
+}
+
 fn main() {
     std_instead_of_core();
     std_instead_of_alloc();
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs
index 63a096384d7..af7f3399f49 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.rs
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs
@@ -1,8 +1,12 @@
+//@aux-build:proc_macro_derive.rs
 #![warn(clippy::std_instead_of_core)]
 #![allow(unused_imports)]
 
 extern crate alloc;
 
+#[macro_use]
+extern crate proc_macro_derive;
+
 #[warn(clippy::std_instead_of_core)]
 fn std_instead_of_core() {
     // Regular import
@@ -55,6 +59,13 @@ fn alloc_instead_of_core() {
     //~^ ERROR: used import from `alloc` instead of `core`
 }
 
+mod std_in_proc_macro_derive {
+    #[warn(clippy::alloc_instead_of_core)]
+    #[allow(unused)]
+    #[derive(ImplStructWithStdDisplay)]
+    struct B {}
+}
+
 fn main() {
     std_instead_of_core();
     std_instead_of_alloc();
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
index ca26f77bd37..4f7bdc4045e 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
@@ -1,5 +1,5 @@
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:9:9
+  --> $DIR/std_instead_of_core.rs:13:9
    |
 LL |     use std::hash::Hasher;
    |         ^^^ help: consider importing the item from `core`: `core`
@@ -8,49 +8,49 @@ LL |     use std::hash::Hasher;
    = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:12:11
+  --> $DIR/std_instead_of_core.rs:16:11
    |
 LL |     use ::std::hash::Hash;
    |           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:18:9
+  --> $DIR/std_instead_of_core.rs:22:9
    |
 LL |     use std::fmt::{Debug, Result};
    |         ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:22:15
+  --> $DIR/std_instead_of_core.rs:26:15
    |
 LL |     let ptr = std::ptr::null::<u32>();
    |               ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:24:21
+  --> $DIR/std_instead_of_core.rs:28:21
    |
 LL |     let ptr_mut = ::std::ptr::null_mut::<usize>();
    |                     ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:28:16
+  --> $DIR/std_instead_of_core.rs:32:16
    |
 LL |     let cell = std::cell::Cell::new(8u32);
    |                ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:30:27
+  --> $DIR/std_instead_of_core.rs:34:27
    |
 LL |     let cell_absolute = ::std::cell::Cell::new(8u32);
    |                           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:39:9
+  --> $DIR/std_instead_of_core.rs:43:9
    |
 LL |     use std::iter::Iterator;
    |         ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `alloc`
-  --> $DIR/std_instead_of_core.rs:46:9
+  --> $DIR/std_instead_of_core.rs:50:9
    |
 LL |     use std::vec;
    |         ^^^ help: consider importing the item from `alloc`: `alloc`
@@ -59,13 +59,13 @@ LL |     use std::vec;
    = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]`
 
 error: used import from `std` instead of `alloc`
-  --> $DIR/std_instead_of_core.rs:48:9
+  --> $DIR/std_instead_of_core.rs:52:9
    |
 LL |     use std::vec::Vec;
    |         ^^^ help: consider importing the item from `alloc`: `alloc`
 
 error: used import from `alloc` instead of `core`
-  --> $DIR/std_instead_of_core.rs:54:9
+  --> $DIR/std_instead_of_core.rs:58:9
    |
 LL |     use alloc::slice::from_ref;
    |         ^^^^^ help: consider importing the item from `core`: `core`
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed
index 2828f9d048e..6fdd728b9b7 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed
@@ -69,6 +69,34 @@ mod struct_mod {
     }
 }
 
+// issue 9942
+mod underscore_mod {
+    // allow use of `deref` so that `clippy --fix` includes `Deref`.
+    #![allow(noop_method_call)]
+
+    mod exports_underscore {
+        pub use std::ops::Deref as _;
+        pub fn dummy() {}
+    }
+
+    mod exports_underscore_ish {
+        pub use std::ops::Deref as _Deref;
+        pub fn dummy() {}
+    }
+
+    fn does_not_lint() {
+        use self::exports_underscore::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+
+    fn does_lint() {
+        use self::exports_underscore_ish::{_Deref, dummy};
+        let _ = (&0).deref();
+        dummy();
+    }
+}
+
 fn main() {
     foo();
     multi_foo();
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs
index cbe70e505d8..20e06d4b366 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports.rs
@@ -69,6 +69,34 @@ mod struct_mod {
     }
 }
 
+// issue 9942
+mod underscore_mod {
+    // allow use of `deref` so that `clippy --fix` includes `Deref`.
+    #![allow(noop_method_call)]
+
+    mod exports_underscore {
+        pub use std::ops::Deref as _;
+        pub fn dummy() {}
+    }
+
+    mod exports_underscore_ish {
+        pub use std::ops::Deref as _Deref;
+        pub fn dummy() {}
+    }
+
+    fn does_not_lint() {
+        use self::exports_underscore::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+
+    fn does_lint() {
+        use self::exports_underscore_ish::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+}
+
 fn main() {
     foo();
     multi_foo();
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr
index 3c750815baf..01a5414778c 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr
@@ -38,55 +38,61 @@ LL | use wildcard_imports_helper::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:97:13
+  --> $DIR/wildcard_imports.rs:94:13
+   |
+LL |         use self::exports_underscore_ish::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `self::exports_underscore_ish::{_Deref, dummy}`
+
+error: usage of wildcard import
+  --> $DIR/wildcard_imports.rs:125:13
    |
 LL |         use crate::fn_mod::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:103:75
+  --> $DIR/wildcard_imports.rs:131:75
    |
 LL |         use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
    |                                                                           ^ help: try: `inner_extern_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:104:13
+  --> $DIR/wildcard_imports.rs:132:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:116:20
+  --> $DIR/wildcard_imports.rs:144:20
    |
 LL |         use self::{inner::*, inner2::*};
    |                    ^^^^^^^^ help: try: `inner::inner_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:116:30
+  --> $DIR/wildcard_imports.rs:144:30
    |
 LL |         use self::{inner::*, inner2::*};
    |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:123:13
+  --> $DIR/wildcard_imports.rs:151:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:152:9
+  --> $DIR/wildcard_imports.rs:180:9
    |
 LL |     use crate::in_fn_test::*;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:161:9
+  --> $DIR/wildcard_imports.rs:189:9
    |
 LL |     use crate:: in_fn_test::  * ;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:162:9
+  --> $DIR/wildcard_imports.rs:190:9
    |
 LL |       use crate:: fn_mod::
    |  _________^
@@ -94,40 +100,40 @@ LL | |         *;
    | |_________^ help: try: `crate:: fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:173:13
+  --> $DIR/wildcard_imports.rs:201:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:208:17
+  --> $DIR/wildcard_imports.rs:236:17
    |
 LL |             use super::*;
    |                 ^^^^^^^^ help: try: `super::insidefoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:216:13
+  --> $DIR/wildcard_imports.rs:244:13
    |
 LL |         use crate::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:225:17
+  --> $DIR/wildcard_imports.rs:253:17
    |
 LL |             use super::super::*;
    |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:234:13
+  --> $DIR/wildcard_imports.rs:262:13
    |
 LL |         use super::super::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports.rs:242:13
+  --> $DIR/wildcard_imports.rs:270:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
-error: aborting due to 21 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
index b27281fa25c..6a9fe007d65 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
@@ -64,6 +64,34 @@ mod struct_mod {
     }
 }
 
+// issue 9942
+mod underscore_mod {
+    // allow use of `deref` so that `clippy --fix` includes `Deref`.
+    #![allow(noop_method_call)]
+
+    mod exports_underscore {
+        pub use std::ops::Deref as _;
+        pub fn dummy() {}
+    }
+
+    mod exports_underscore_ish {
+        pub use std::ops::Deref as _Deref;
+        pub fn dummy() {}
+    }
+
+    fn does_not_lint() {
+        use exports_underscore::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+
+    fn does_lint() {
+        use exports_underscore_ish::{_Deref, dummy};
+        let _ = (&0).deref();
+        dummy();
+    }
+}
+
 fn main() {
     foo();
     multi_foo();
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr
index 709a665d65c..e39f240a4aa 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr
@@ -38,55 +38,61 @@ LL | use wildcard_imports_helper::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:91:13
+  --> $DIR/wildcard_imports_2021.rs:89:13
+   |
+LL |         use exports_underscore_ish::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `exports_underscore_ish::{_Deref, dummy}`
+
+error: usage of wildcard import
+  --> $DIR/wildcard_imports_2021.rs:119:13
    |
 LL |         use crate::fn_mod::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:97:75
+  --> $DIR/wildcard_imports_2021.rs:125:75
    |
 LL |         use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
    |                                                                           ^ help: try: `inner_extern_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:98:13
+  --> $DIR/wildcard_imports_2021.rs:126:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:110:20
+  --> $DIR/wildcard_imports_2021.rs:138:20
    |
 LL |         use self::{inner::*, inner2::*};
    |                    ^^^^^^^^ help: try: `inner::inner_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:110:30
+  --> $DIR/wildcard_imports_2021.rs:138:30
    |
 LL |         use self::{inner::*, inner2::*};
    |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:117:13
+  --> $DIR/wildcard_imports_2021.rs:145:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:146:9
+  --> $DIR/wildcard_imports_2021.rs:174:9
    |
 LL |     use crate::in_fn_test::*;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:155:9
+  --> $DIR/wildcard_imports_2021.rs:183:9
    |
 LL |     use crate:: in_fn_test::  * ;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:156:9
+  --> $DIR/wildcard_imports_2021.rs:184:9
    |
 LL |       use crate:: fn_mod::
    |  _________^
@@ -94,40 +100,40 @@ LL | |         *;
    | |_________^ help: try: `crate:: fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:167:13
+  --> $DIR/wildcard_imports_2021.rs:195:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:202:17
+  --> $DIR/wildcard_imports_2021.rs:230:17
    |
 LL |             use super::*;
    |                 ^^^^^^^^ help: try: `super::insidefoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:210:13
+  --> $DIR/wildcard_imports_2021.rs:238:13
    |
 LL |         use crate::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:219:17
+  --> $DIR/wildcard_imports_2021.rs:247:17
    |
 LL |             use super::super::*;
    |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:228:13
+  --> $DIR/wildcard_imports_2021.rs:256:13
    |
 LL |         use super::super::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:236:13
+  --> $DIR/wildcard_imports_2021.rs:264:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
-error: aborting due to 21 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
index b27281fa25c..6a9fe007d65 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
@@ -64,6 +64,34 @@ mod struct_mod {
     }
 }
 
+// issue 9942
+mod underscore_mod {
+    // allow use of `deref` so that `clippy --fix` includes `Deref`.
+    #![allow(noop_method_call)]
+
+    mod exports_underscore {
+        pub use std::ops::Deref as _;
+        pub fn dummy() {}
+    }
+
+    mod exports_underscore_ish {
+        pub use std::ops::Deref as _Deref;
+        pub fn dummy() {}
+    }
+
+    fn does_not_lint() {
+        use exports_underscore::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+
+    fn does_lint() {
+        use exports_underscore_ish::{_Deref, dummy};
+        let _ = (&0).deref();
+        dummy();
+    }
+}
+
 fn main() {
     foo();
     multi_foo();
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr
index 709a665d65c..e39f240a4aa 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr
@@ -38,55 +38,61 @@ LL | use wildcard_imports_helper::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:91:13
+  --> $DIR/wildcard_imports_2021.rs:89:13
+   |
+LL |         use exports_underscore_ish::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `exports_underscore_ish::{_Deref, dummy}`
+
+error: usage of wildcard import
+  --> $DIR/wildcard_imports_2021.rs:119:13
    |
 LL |         use crate::fn_mod::*;
    |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:97:75
+  --> $DIR/wildcard_imports_2021.rs:125:75
    |
 LL |         use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
    |                                                                           ^ help: try: `inner_extern_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:98:13
+  --> $DIR/wildcard_imports_2021.rs:126:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:110:20
+  --> $DIR/wildcard_imports_2021.rs:138:20
    |
 LL |         use self::{inner::*, inner2::*};
    |                    ^^^^^^^^ help: try: `inner::inner_foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:110:30
+  --> $DIR/wildcard_imports_2021.rs:138:30
    |
 LL |         use self::{inner::*, inner2::*};
    |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:117:13
+  --> $DIR/wildcard_imports_2021.rs:145:13
    |
 LL |         use wildcard_imports_helper::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:146:9
+  --> $DIR/wildcard_imports_2021.rs:174:9
    |
 LL |     use crate::in_fn_test::*;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:155:9
+  --> $DIR/wildcard_imports_2021.rs:183:9
    |
 LL |     use crate:: in_fn_test::  * ;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:156:9
+  --> $DIR/wildcard_imports_2021.rs:184:9
    |
 LL |       use crate:: fn_mod::
    |  _________^
@@ -94,40 +100,40 @@ LL | |         *;
    | |_________^ help: try: `crate:: fn_mod::foo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:167:13
+  --> $DIR/wildcard_imports_2021.rs:195:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:202:17
+  --> $DIR/wildcard_imports_2021.rs:230:17
    |
 LL |             use super::*;
    |                 ^^^^^^^^ help: try: `super::insidefoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:210:13
+  --> $DIR/wildcard_imports_2021.rs:238:13
    |
 LL |         use crate::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:219:17
+  --> $DIR/wildcard_imports_2021.rs:247:17
    |
 LL |             use super::super::*;
    |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:228:13
+  --> $DIR/wildcard_imports_2021.rs:256:13
    |
 LL |         use super::super::super_imports::*;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
 
 error: usage of wildcard import
-  --> $DIR/wildcard_imports_2021.rs:236:13
+  --> $DIR/wildcard_imports_2021.rs:264:13
    |
 LL |         use super::*;
    |             ^^^^^^^^ help: try: `super::foofoo`
 
-error: aborting due to 21 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
index 7dd2103eca7..18ebc0f5127 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
@@ -64,6 +64,34 @@ mod struct_mod {
     }
 }
 
+// issue 9942
+mod underscore_mod {
+    // allow use of `deref` so that `clippy --fix` includes `Deref`.
+    #![allow(noop_method_call)]
+
+    mod exports_underscore {
+        pub use std::ops::Deref as _;
+        pub fn dummy() {}
+    }
+
+    mod exports_underscore_ish {
+        pub use std::ops::Deref as _Deref;
+        pub fn dummy() {}
+    }
+
+    fn does_not_lint() {
+        use exports_underscore::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+
+    fn does_lint() {
+        use exports_underscore_ish::*;
+        let _ = (&0).deref();
+        dummy();
+    }
+}
+
 fn main() {
     foo();
     multi_foo();
diff --git a/src/tools/clippy/tests/ui/write_literal.fixed b/src/tools/clippy/tests/ui/write_literal.fixed
index ee577574d28..3d216b76cbf 100644
--- a/src/tools/clippy/tests/ui/write_literal.fixed
+++ b/src/tools/clippy/tests/ui/write_literal.fixed
@@ -43,16 +43,22 @@ fn main() {
     // throw a warning
     writeln!(v, "hello world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     writeln!(v, "world hello");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
 
     // named args shouldn't change anything either
     writeln!(v, "hello world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     writeln!(v, "world hello");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
+
+    // #10128
+    writeln!(v, "hello {0} world", 2);
+    //~^ ERROR: literal with an empty format string
+    writeln!(v, "world {0} hello", 2);
+    //~^ ERROR: literal with an empty format string
+    writeln!(v, "hello {0} {1}, {bar}", 2, 3, bar = 4);
+    //~^ ERROR: literal with an empty format string
+    writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
+    //~^ ERROR: literal with an empty format string
 }
diff --git a/src/tools/clippy/tests/ui/write_literal.rs b/src/tools/clippy/tests/ui/write_literal.rs
index 588e8fd413a..79d6daa2e3b 100644
--- a/src/tools/clippy/tests/ui/write_literal.rs
+++ b/src/tools/clippy/tests/ui/write_literal.rs
@@ -43,16 +43,22 @@ fn main() {
     // throw a warning
     writeln!(v, "{0} {1}", "hello", "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     writeln!(v, "{1} {0}", "hello", "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
 
     // named args shouldn't change anything either
     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
+
+    // #10128
+    writeln!(v, "{0} {1} {2}", "hello", 2, "world");
+    //~^ ERROR: literal with an empty format string
+    writeln!(v, "{2} {1} {0}", "hello", 2, "world");
+    //~^ ERROR: literal with an empty format string
+    writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4);
+    //~^ ERROR: literal with an empty format string
+    writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
+    //~^ ERROR: literal with an empty format string
 }
diff --git a/src/tools/clippy/tests/ui/write_literal.stderr b/src/tools/clippy/tests/ui/write_literal.stderr
index 372a54cf769..ee0d536e954 100644
--- a/src/tools/clippy/tests/ui/write_literal.stderr
+++ b/src/tools/clippy/tests/ui/write_literal.stderr
@@ -52,96 +52,96 @@ error: literal with an empty format string
   --> $DIR/write_literal.rs:44:28
    |
 LL |     writeln!(v, "{0} {1}", "hello", "world");
-   |                            ^^^^^^^
+   |                            ^^^^^^^^^^^^^^^^
    |
 help: try
    |
 LL -     writeln!(v, "{0} {1}", "hello", "world");
-LL +     writeln!(v, "hello {1}", "world");
+LL +     writeln!(v, "hello world");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:44:37
+  --> $DIR/write_literal.rs:46:28
    |
-LL |     writeln!(v, "{0} {1}", "hello", "world");
-   |                                     ^^^^^^^
+LL |     writeln!(v, "{1} {0}", "hello", "world");
+   |                            ^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{0} {1}", "hello", "world");
-LL +     writeln!(v, "{0} world", "hello");
+LL -     writeln!(v, "{1} {0}", "hello", "world");
+LL +     writeln!(v, "world hello");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:47:37
+  --> $DIR/write_literal.rs:50:38
    |
-LL |     writeln!(v, "{1} {0}", "hello", "world");
-   |                                     ^^^^^^^
+LL |     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{1} {0}", "hello", "world");
-LL +     writeln!(v, "world {0}", "hello");
+LL -     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
+LL +     writeln!(v, "hello world");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:47:28
+  --> $DIR/write_literal.rs:52:38
    |
-LL |     writeln!(v, "{1} {0}", "hello", "world");
-   |                            ^^^^^^^
+LL |     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{1} {0}", "hello", "world");
-LL +     writeln!(v, "{1} hello", "world");
+LL -     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
+LL +     writeln!(v, "world hello");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:52:38
+  --> $DIR/write_literal.rs:56:32
    |
-LL |     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
-   |                                      ^^^^^^^
+LL |     writeln!(v, "{0} {1} {2}", "hello", 2, "world");
+   |                                ^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
-LL +     writeln!(v, "hello {bar}", bar = "world");
+LL -     writeln!(v, "{0} {1} {2}", "hello", 2, "world");
+LL +     writeln!(v, "hello {0} world", 2);
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:52:53
+  --> $DIR/write_literal.rs:58:32
    |
-LL |     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
-   |                                                     ^^^^^^^
+LL |     writeln!(v, "{2} {1} {0}", "hello", 2, "world");
+   |                                ^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
-LL +     writeln!(v, "{foo} world", foo = "hello");
+LL -     writeln!(v, "{2} {1} {0}", "hello", 2, "world");
+LL +     writeln!(v, "world {0} hello", 2);
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:55:53
+  --> $DIR/write_literal.rs:60:39
    |
-LL |     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
-   |                                                     ^^^^^^^
+LL |     writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4);
+   |                                       ^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
-LL +     writeln!(v, "world {foo}", foo = "hello");
+LL -     writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4);
+LL +     writeln!(v, "hello {0} {1}, {bar}", 2, 3, bar = 4);
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal.rs:55:38
+  --> $DIR/write_literal.rs:62:41
    |
-LL |     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
-   |                                      ^^^^^^^
+LL |     writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^
    |
 help: try
    |
-LL -     writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
-LL +     writeln!(v, "{bar} hello", bar = "world");
+LL -     writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
+LL +     writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
    |
 
 error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/write_literal_2.rs b/src/tools/clippy/tests/ui/write_literal_2.rs
index aa0c13c1340..b2ed552d46b 100644
--- a/src/tools/clippy/tests/ui/write_literal_2.rs
+++ b/src/tools/clippy/tests/ui/write_literal_2.rs
@@ -1,6 +1,6 @@
 //@no-rustfix: overlapping suggestions
 #![allow(unused_must_use)]
-#![warn(clippy::needless_raw_strings, clippy::write_literal)]
+#![warn(clippy::write_literal)]
 
 use std::io::Write;
 
@@ -11,9 +11,7 @@ fn main() {
     //~^ ERROR: literal with an empty format string
     //~| NOTE: `-D clippy::write-literal` implied by `-D warnings`
     writeln!(v, r"{}", r"{hello}");
-    //~^ ERROR: unnecessary raw string literal
-    //~| NOTE: `-D clippy::needless-raw-strings` implied by `-D warnings`
-    //~| ERROR: literal with an empty format string
+    //~^ ERROR: literal with an empty format string
     writeln!(v, "{}", '\'');
     //~^ ERROR: literal with an empty format string
     writeln!(v, "{}", '"');
@@ -26,17 +24,14 @@ fn main() {
         v,
         "some {}",
         "hello \
-        //~^ ERROR: literal with an empty format string
-        world!"
+        world!",
+        //~^^ ERROR: literal with an empty format string
     );
     writeln!(
         v,
         "some {}\
         {} \\ {}",
-        "1",
-        "2",
-        "3",
-        //~^ ERROR: literal with an empty format string
+        "1", "2", "3",
     );
     writeln!(v, "{}", "\\");
     //~^ ERROR: literal with an empty format string
@@ -51,7 +46,6 @@ fn main() {
     // hard mode
     writeln!(v, r#"{}{}"#, '#', '"');
     //~^ ERROR: literal with an empty format string
-    //~| ERROR: literal with an empty format string
     // should not lint
     writeln!(v, r"{}", "\r");
 }
diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr
index 6d382a267ad..81ef49de082 100644
--- a/src/tools/clippy/tests/ui/write_literal_2.stderr
+++ b/src/tools/clippy/tests/ui/write_literal_2.stderr
@@ -1,14 +1,3 @@
-error: unnecessary raw string literal
-  --> $DIR/write_literal_2.rs:13:24
-   |
-LL |     writeln!(v, r"{}", r"{hello}");
-   |                        -^^^^^^^^^
-   |                        |
-   |                        help: use a string literal instead: `"{hello}"`
-   |
-   = note: `-D clippy::needless-raw-strings` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]`
-
 error: literal with an empty format string
   --> $DIR/write_literal_2.rs:10:23
    |
@@ -36,7 +25,7 @@ LL +     writeln!(v, r"{{hello}}");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:17:23
+  --> $DIR/write_literal_2.rs:15:23
    |
 LL |     writeln!(v, "{}", '\'');
    |                       ^^^^
@@ -48,7 +37,7 @@ LL +     writeln!(v, "'");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:19:23
+  --> $DIR/write_literal_2.rs:17:23
    |
 LL |     writeln!(v, "{}", '"');
    |                       ^^^
@@ -60,13 +49,13 @@ LL +     writeln!(v, "\"");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:21:24
+  --> $DIR/write_literal_2.rs:19:24
    |
 LL |     writeln!(v, r"{}", '"');
    |                        ^^^
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:23:24
+  --> $DIR/write_literal_2.rs:21:24
    |
 LL |     writeln!(v, r"{}", '\'');
    |                        ^^^^
@@ -78,59 +67,32 @@ LL +     writeln!(v, r"'");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:28:9
+  --> $DIR/write_literal_2.rs:26:9
    |
 LL | /         "hello \
-LL | |
-LL | |         world!"
+LL | |         world!",
    | |_______________^
    |
 help: try
    |
 LL ~         "some hello \
-LL +
-LL ~         world!"
+LL ~         world!",
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:36:9
+  --> $DIR/write_literal_2.rs:34:9
    |
-LL |         "1",
-   |         ^^^
+LL |         "1", "2", "3",
+   |         ^^^^^^^^^^^^^
    |
 help: try
    |
 LL ~         "some 1\
-LL ~         {} \\ {}",
+LL ~         2 \\ 3",
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:37:9
-   |
-LL |         "2",
-   |         ^^^
-   |
-help: try
-   |
-LL ~         2 \\ {}",
-LL ~         "1",
-   |
-
-error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:38:9
-   |
-LL |         "3",
-   |         ^^^
-   |
-help: try
-   |
-LL ~         {} \\ 3",
-LL |         "1",
-LL ~         "2",
-   |
-
-error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:41:23
+  --> $DIR/write_literal_2.rs:36:23
    |
 LL |     writeln!(v, "{}", "\\");
    |                       ^^^^
@@ -142,7 +104,7 @@ LL +     writeln!(v, "\\");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:43:24
+  --> $DIR/write_literal_2.rs:38:24
    |
 LL |     writeln!(v, r"{}", "\\");
    |                        ^^^^
@@ -154,7 +116,7 @@ LL +     writeln!(v, r"\");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:45:26
+  --> $DIR/write_literal_2.rs:40:26
    |
 LL |     writeln!(v, r#"{}"#, "\\");
    |                          ^^^^
@@ -166,7 +128,7 @@ LL +     writeln!(v, r#"\"#);
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:47:23
+  --> $DIR/write_literal_2.rs:42:23
    |
 LL |     writeln!(v, "{}", r"\");
    |                       ^^^^
@@ -178,7 +140,7 @@ LL +     writeln!(v, "\\");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:49:23
+  --> $DIR/write_literal_2.rs:44:23
    |
 LL |     writeln!(v, "{}", "\r");
    |                       ^^^^
@@ -190,16 +152,10 @@ LL +     writeln!(v, "\r");
    |
 
 error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:52:28
-   |
-LL |     writeln!(v, r#"{}{}"#, '#', '"');
-   |                            ^^^
-
-error: literal with an empty format string
-  --> $DIR/write_literal_2.rs:52:33
+  --> $DIR/write_literal_2.rs:47:28
    |
 LL |     writeln!(v, r#"{}{}"#, '#', '"');
-   |                                 ^^^
+   |                            ^^^^^^^^
 
-error: aborting due to 18 previous errors
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index dc2601e9e9f..8f0a0a045ab 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-1bc0463b183392ad4e0ae9c5f7a76630d487230d
+4ea5190026dbc1302b644d938e68bc6843cb8b24
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index ef4e7df3aba..9041683fbc4 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -803,8 +803,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             if tcx.is_foreign_item(def_id) {
                 throw_unsup_format!("foreign thread-local statics are not supported");
             }
-            // We don't give a span -- statics don't need that, they cannot be generic or associated.
-            let allocation = this.ctfe_query(None, |tcx| tcx.eval_static_initializer(def_id))?;
+            let allocation = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
             let mut allocation = allocation.inner().clone();
             // This allocation will be deallocated when the thread dies, so it is not in read-only memory.
             allocation.mutability = Mutability::Mut;
diff --git a/tests/run-make/silly-file-names/Makefile b/tests/run-make/silly-file-names/Makefile
new file mode 100644
index 00000000000..a09bdb1c532
--- /dev/null
+++ b/tests/run-make/silly-file-names/Makefile
@@ -0,0 +1,18 @@
+# ignore-cross-compile we need to execute the binary
+# ignore-windows we create files with < and > in their names
+
+include ../tools.mk
+
+ifdef RUSTC_BLESS_TEST
+    RUSTC_TEST_OP = cp
+else
+    RUSTC_TEST_OP = $(DIFF)
+endif
+
+all:
+	echo '"comes from a file with a name that begins with <"' > "$(TMPDIR)/<leading-lt"
+	echo '"comes from a file with a name that ends with >"' > "$(TMPDIR)/trailing-gt>"
+	cp silly-file-names.rs "$(TMPDIR)/silly-file-names.rs"
+	$(RUSTC) "$(TMPDIR)/silly-file-names.rs" -o "$(TMPDIR)/silly-file-names"
+	"$(TMPDIR)/silly-file-names" > "$(TMPDIR)/silly-file-names.run.stdout"
+	$(RUSTC_TEST_OP) "$(TMPDIR)/silly-file-names.run.stdout" silly-file-names.run.stdout
diff --git a/tests/run-make/silly-file-names/silly-file-names.rs b/tests/run-make/silly-file-names/silly-file-names.rs
new file mode 100644
index 00000000000..a2008209141
--- /dev/null
+++ b/tests/run-make/silly-file-names/silly-file-names.rs
@@ -0,0 +1,4 @@
+fn main() {
+    println!(include!("<leading-lt"));
+    println!(include!("trailing-gt>"));
+}
diff --git a/tests/run-make/silly-file-names/silly-file-names.run.stdout b/tests/run-make/silly-file-names/silly-file-names.run.stdout
new file mode 100644
index 00000000000..fbc4c89e0f0
--- /dev/null
+++ b/tests/run-make/silly-file-names/silly-file-names.run.stdout
@@ -0,0 +1,2 @@
+comes from a file with a name that begins with <
+comes from a file with a name that ends with >
diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr
index d2ea08aa474..619417a73c9 100644
--- a/tests/ui/array-slice-vec/vector-no-ann.stderr
+++ b/tests/ui/array-slice-vec/vector-no-ann.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec<T>`
   --> $DIR/vector-no-ann.rs:2:9
    |
 LL |     let _foo = Vec::new();
-   |         ^^^^
+   |         ^^^^   ---------- type must be known at this point
    |
 help: consider giving `_foo` an explicit type, where the type for type parameter `T` is specified
    |
diff --git a/tests/ui/asm/x86_64/issue-96797.rs b/tests/ui/asm/x86_64/issue-96797.rs
index 951dd949b32..6c22c2f6c94 100644
--- a/tests/ui/asm/x86_64/issue-96797.rs
+++ b/tests/ui/asm/x86_64/issue-96797.rs
@@ -11,7 +11,14 @@ use std::arch::global_asm;
 #[no_mangle]
 fn my_func() {}
 
-global_asm!("call_foobar: jmp {}", sym foobar);
+global_asm!("
+.globl call_foobar
+.type call_foobar,@function
+.pushsection .text.call_foobar,\"ax\",@progbits
+call_foobar: jmp {}
+.size call_foobar, .-call_foobar
+.popsection
+", sym foobar);
 
 fn foobar() {}
 
diff --git a/tests/ui/const-generics/const-argument-if-length.full.stderr b/tests/ui/const-generics/const-argument-if-length.full.stderr
index 7997026dfe4..315b0f0a064 100644
--- a/tests/ui/const-generics/const-argument-if-length.full.stderr
+++ b/tests/ui/const-generics/const-argument-if-length.full.stderr
@@ -1,3 +1,11 @@
+error: unconstrained generic constant
+  --> $DIR/const-argument-if-length.rs:17:10
+   |
+LL |     pad: [u8; is_zst::<T>()],
+   |          ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
+
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/const-argument-if-length.rs:15:12
    |
@@ -22,14 +30,6 @@ help: the `Box` type always has a statically known size and allocates its conten
 LL |     value: Box<T>,
    |            ++++ +
 
-error: unconstrained generic constant
-  --> $DIR/const-argument-if-length.rs:17:10
-   |
-LL |     pad: [u8; is_zst::<T>()],
-   |          ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/issues/issue-83249.stderr b/tests/ui/const-generics/issues/issue-83249.stderr
index 7491fdc8a69..5187434ff40 100644
--- a/tests/ui/const-generics/issues/issue-83249.stderr
+++ b/tests/ui/const-generics/issues/issue-83249.stderr
@@ -1,9 +1,18 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/issue-83249.rs:19:9
    |
 LL |     let _ = foo([0; 1]);
-   |         ^
+   |         ^   --- ------ type must be known at this point
+   |             |
+   |             required by a bound introduced by this call
    |
+   = note: cannot satisfy `_: Foo`
+   = help: the trait `Foo` is implemented for `u8`
+note: required by a bound in `foo`
+  --> $DIR/issue-83249.rs:12:11
+   |
+LL | fn foo<T: Foo>(_: [u8; T::N]) -> T {
+   |           ^^^ required by this bound in `foo`
 help: consider giving this pattern a type
    |
 LL |     let _: /* Type */ = foo([0; 1]);
@@ -11,4 +20,4 @@ LL |     let _: /* Type */ = foo([0; 1]);
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/error-codes/E0282.rs b/tests/ui/error-codes/E0282.rs
index f1f93b3aed6..5bc29cda9ea 100644
--- a/tests/ui/error-codes/E0282.rs
+++ b/tests/ui/error-codes/E0282.rs
@@ -1,4 +1,4 @@
 fn main() {
-    let x = "hello".chars().rev().collect();
+    let x;
     //~^ ERROR E0282
 }
diff --git a/tests/ui/error-codes/E0282.stderr b/tests/ui/error-codes/E0282.stderr
index 892d3a81f27..58332454a37 100644
--- a/tests/ui/error-codes/E0282.stderr
+++ b/tests/ui/error-codes/E0282.stderr
@@ -1,13 +1,13 @@
 error[E0282]: type annotations needed
   --> $DIR/E0282.rs:2:9
    |
-LL |     let x = "hello".chars().rev().collect();
+LL |     let x;
    |         ^
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: Vec<_> = "hello".chars().rev().collect();
-   |          ++++++++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr
index 928c8d11d20..0a069e8d350 100644
--- a/tests/ui/error-codes/E0401.stderr
+++ b/tests/ui/error-codes/E0401.stderr
@@ -32,12 +32,18 @@ LL |         fn helper(sel: &Self) -> u8 {
    |                         use of generic parameter from outer item
    |                         refer to the type directly here instead
 
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/E0401.rs:11:5
    |
 LL |     bfnr(x);
-   |     ^^^^ cannot infer type of the type parameter `U` declared on the function `bfnr`
+   |     ^^^^ cannot infer type of the type parameter `V` declared on the function `bfnr`
+   |
+   = note: cannot satisfy `_: Baz<_>`
+note: required by a bound in `bfnr`
+  --> $DIR/E0401.rs:4:19
    |
+LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
+   |                   ^^^^^^ required by this bound in `bfnr`
 help: consider specifying the generic arguments
    |
 LL |     bfnr::<U, V, W>(x);
@@ -66,5 +72,5 @@ LL |     bfnr::<U, V, W>(x);
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0282, E0283, E0401.
-For more information about an error, try `rustc --explain E0282`.
+Some errors have detailed explanations: E0283, E0401.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index 0955efdbb73..28dbdf4c374 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -44,12 +44,6 @@ LL |     for item in *things { *item = 0 }
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 
-error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
-  --> $DIR/issue-20605.rs:5:17
-   |
-LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^
-
 error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
   --> $DIR/issue-20605.rs:5:5
    |
@@ -60,6 +54,12 @@ LL |     for item in *things { *item = 0 }
 note: required by a bound in `None`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
+error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
+  --> $DIR/issue-20605.rs:5:17
+   |
+LL |     for item in *things { *item = 0 }
+   |                 ^^^^^^^
+
 error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
   --> $DIR/issue-20605.rs:5:27
    |
diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.stderr b/tests/ui/generic-associated-types/bugs/issue-91762.stderr
index 1272c8b8ae2..1045e80f046 100644
--- a/tests/ui/generic-associated-types/bugs/issue-91762.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-91762.stderr
@@ -1,9 +1,10 @@
-error[E0282]: type annotations needed
+error[E0284]: type annotations needed
   --> $DIR/issue-91762.rs:24:15
    |
 LL |         ret = <Self::Base as Functor>::fmap(arg);
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `fmap`
    |
+   = note: cannot satisfy `<<Self as FunctorExt<T>>::Base as Functor>::With<_> == Self`
 help: consider specifying the generic arguments
    |
 LL |         ret = <Self::Base as Functor>::fmap::<T, U>(arg);
@@ -11,4 +12,4 @@ LL |         ret = <Self::Base as Functor>::fmap::<T, U>(arg);
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/generic-const-items/inference-failure.stderr b/tests/ui/generic-const-items/inference-failure.stderr
index 22ff1b9ba7f..10ecd83ec53 100644
--- a/tests/ui/generic-const-items/inference-failure.stderr
+++ b/tests/ui/generic-const-items/inference-failure.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Option<T>`
   --> $DIR/inference-failure.rs:8:9
    |
 LL |     let _ = NONE;
-   |         ^
+   |         ^   ---- type must be known at this point
    |
 help: consider giving this pattern a type, where the type for type parameter `T` is specified
    |
diff --git a/tests/ui/impl-trait/cross-return-site-inference.rs b/tests/ui/impl-trait/cross-return-site-inference.rs
index 00aed2ad95a..e1071b08c55 100644
--- a/tests/ui/impl-trait/cross-return-site-inference.rs
+++ b/tests/ui/impl-trait/cross-return-site-inference.rs
@@ -36,13 +36,13 @@ fn muh() -> Result<(), impl std::fmt::Debug> {
 
 fn muh2() -> Result<(), impl std::fmt::Debug> {
     return Err(From::from("foo"));
-    //~^ ERROR type annotations needed
+    //~^ ERROR cannot call associated function on trait
     Ok(())
 }
 
 fn muh3() -> Result<(), impl std::fmt::Debug> {
     Err(From::from("foo"))
-    //~^ ERROR type annotations needed
+    //~^ ERROR cannot call associated function on trait
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/cross-return-site-inference.stderr b/tests/ui/impl-trait/cross-return-site-inference.stderr
index 766614e9e50..8ee3e9abf9c 100644
--- a/tests/ui/impl-trait/cross-return-site-inference.stderr
+++ b/tests/ui/impl-trait/cross-return-site-inference.stderr
@@ -9,28 +9,29 @@ help: consider specifying the generic arguments
 LL |     Ok::<(), E>(())
    |       +++++++++
 
-error[E0282]: type annotations needed
-  --> $DIR/cross-return-site-inference.rs:38:12
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/cross-return-site-inference.rs:38:16
    |
 LL |     return Err(From::from("foo"));
-   |            ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+   |                ^^^^^^^^^^ cannot call associated function of trait
    |
-help: consider specifying the generic arguments
+help: use a fully-qualified path to a specific available implementation
    |
-LL |     return Err::<(), E>(From::from("foo"));
-   |               +++++++++
+LL |     return Err(</* self type */ as From>::from("foo"));
+   |                +++++++++++++++++++     +
 
-error[E0282]: type annotations needed
-  --> $DIR/cross-return-site-inference.rs:44:5
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/cross-return-site-inference.rs:44:9
    |
 LL |     Err(From::from("foo"))
-   |     ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
+   |         ^^^^^^^^^^ cannot call associated function of trait
    |
-help: consider specifying the generic arguments
+help: use a fully-qualified path to a specific available implementation
    |
-LL |     Err::<(), E>(From::from("foo"))
-   |        +++++++++
+LL |     Err(</* self type */ as From>::from("foo"))
+   |         +++++++++++++++++++     +
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0282`.
+Some errors have detailed explanations: E0282, E0790.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr
index 3c39aa6ce5b..b4be16ff042 100644
--- a/tests/ui/impl-trait/issues/issue-84073.stderr
+++ b/tests/ui/impl-trait/issues/issue-84073.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `RaceBuilder<T, Never<T>>`
   --> $DIR/issue-84073.rs:32:16
    |
 LL |     Race::new(|race| race.when());
-   |                ^^^^
+   |                ^^^^  ---- type must be known at this point
    |
 help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified
    |
diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr
index ee4343b110f..2347805343c 100644
--- a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr
+++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr
@@ -1,9 +1,11 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/opaque-cast-field-access-in-future.rs:22:17
    |
 LL | fn run() -> Foo<impl Future<Output = ()>> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+   |
+   = note: cannot satisfy `_: Future`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/where-allowed-2.stderr b/tests/ui/impl-trait/where-allowed-2.stderr
index 2b328c01c87..b3765ac1a54 100644
--- a/tests/ui/impl-trait/where-allowed-2.stderr
+++ b/tests/ui/impl-trait/where-allowed-2.stderr
@@ -1,9 +1,11 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/where-allowed-2.rs:3:30
    |
 LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
    |                              ^^^^^^^^^^ cannot infer type
+   |
+   = note: cannot satisfy `_: Debug`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr
index b706cd2bc36..98639f307fb 100644
--- a/tests/ui/inference/cannot-infer-closure-circular.stderr
+++ b/tests/ui/inference/cannot-infer-closure-circular.stderr
@@ -3,6 +3,9 @@ error[E0282]: type annotations needed for `Result<(), E>`
    |
 LL |     let x = |r| {
    |              ^
+LL |         let v = r?;
+LL |         Ok(v)
+   |         ----- type must be known at this point
    |
 help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified
    |
diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr
index 4962b21f9fd..2819329275d 100644
--- a/tests/ui/inference/issue-104649.stderr
+++ b/tests/ui/inference/issue-104649.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `A<std::result::Result<std::result::Re
   --> $DIR/issue-104649.rs:24:9
    |
 LL |     let a = A(Result::Ok(Result::Ok(())));
-   |         ^
+   |         ^                -------------- type must be known at this point
    |
 help: consider giving `a` an explicit type, where the type for type parameter `E` is specified
    |
diff --git a/tests/ui/inference/issue-71584.rs b/tests/ui/inference/issue-71584.rs
index 7bf3ed60ec1..c96c32d5c0a 100644
--- a/tests/ui/inference/issue-71584.rs
+++ b/tests/ui/inference/issue-71584.rs
@@ -1,3 +1,4 @@
+// ignore-windows different list of satisfying impls
 fn main() {
     let n: u32 = 1;
     let mut d: u64 = 2;
diff --git a/tests/ui/inference/issue-71584.stderr b/tests/ui/inference/issue-71584.stderr
index 6ddb7657301..22c0f113d6a 100644
--- a/tests/ui/inference/issue-71584.stderr
+++ b/tests/ui/inference/issue-71584.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed
-  --> $DIR/issue-71584.rs:4:15
+  --> $DIR/issue-71584.rs:5:15
    |
 LL |     d = d % n.into();
    |           -   ^^^^
diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr
index 225558805e0..6c93241ea07 100644
--- a/tests/ui/inference/issue-72690.stderr
+++ b/tests/ui/inference/issue-72690.stderr
@@ -24,16 +24,15 @@ help: try using a fully qualified path to specify the expected types
 LL |     String::from(<str as AsRef<T>>::as_ref("x"));
    |                  ++++++++++++++++++++++++++   ~
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-72690.rs:12:6
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:12:9
    |
 LL |     |x| String::from("x".as_ref());
-   |      ^
-   |
-help: consider giving this closure parameter an explicit type
+   |         ^^^^^^ cannot infer type for reference `&_`
    |
-LL |     |x: /* Type */| String::from("x".as_ref());
-   |       ++++++++++++
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl From<&String> for String;
+           - impl From<&str> for String;
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:12:26
@@ -225,5 +224,4 @@ LL |     String::from(<str as AsRef<T>>::as_ref("x"));
 
 error: aborting due to 17 previous errors
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/multiple-impl-apply.rs b/tests/ui/inference/multiple-impl-apply.rs
new file mode 100644
index 00000000000..314fe0f2ae5
--- /dev/null
+++ b/tests/ui/inference/multiple-impl-apply.rs
@@ -0,0 +1,48 @@
+struct Foo {
+    inner: u32,
+}
+
+struct Bar {
+    inner: u32,
+}
+
+#[derive(Clone, Copy)]
+struct Baz {
+    inner: u32,
+}
+
+impl From<Baz> for Bar {
+    fn from(other: Baz) -> Self {
+        Self {
+            inner: other.inner,
+        }
+    }
+}
+
+impl From<Baz> for Foo {
+    fn from(other: Baz) -> Self {
+        Self {
+            inner: other.inner,
+        }
+    }
+}
+
+fn main() {
+    let x: Baz = Baz { inner: 42 };
+
+    // DOESN'T Compile: Multiple options!
+    let y = x.into(); //~ ERROR E0283
+
+    let y_1: Foo = x.into();
+    let y_2: Bar = x.into();
+
+    let z_1 = Foo::from(y_1);
+    let z_2 = Bar::from(y_2);
+
+    // No type annotations needed, the compiler KNOWS the type must be `Foo`!
+    let m = magic_foo(x);
+}
+
+fn magic_foo(arg: Baz) -> Foo {
+    arg.into()
+}
diff --git a/tests/ui/inference/multiple-impl-apply.stderr b/tests/ui/inference/multiple-impl-apply.stderr
new file mode 100644
index 00000000000..ec49e15201a
--- /dev/null
+++ b/tests/ui/inference/multiple-impl-apply.stderr
@@ -0,0 +1,23 @@
+error[E0283]: type annotations needed
+  --> $DIR/multiple-impl-apply.rs:34:9
+   |
+LL |     let y = x.into();
+   |         ^     ---- type must be known at this point
+   |
+note: multiple `impl`s satisfying `_: From<Baz>` found
+  --> $DIR/multiple-impl-apply.rs:14:1
+   |
+LL | impl From<Baz> for Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl From<Baz> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   = note: required for `Baz` to implement `Into<_>`
+help: consider giving `y` an explicit type
+   |
+LL |     let y: /* Type */ = x.into();
+   |          ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs
index fc79e6201bd..8960f870c39 100644
--- a/tests/ui/inference/need_type_info/concrete-impl.rs
+++ b/tests/ui/inference/need_type_info/concrete-impl.rs
@@ -14,6 +14,4 @@ fn main() {
     <Struct as Ambiguous<_>>::method();
     //~^ ERROR type annotations needed
     //~| NOTE cannot infer type of the type parameter `A`
-    //~| ERROR type annotations needed
-    //~| NOTE infer type of the type parameter `A`
 }
diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr
index 74c3f6cd5cf..6b86753caf9 100644
--- a/tests/ui/inference/need_type_info/concrete-impl.stderr
+++ b/tests/ui/inference/need_type_info/concrete-impl.stderr
@@ -1,9 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/concrete-impl.rs:14:5
-   |
-LL |     <Struct as Ambiguous<_>>::method();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
-
 error[E0283]: type annotations needed
   --> $DIR/concrete-impl.rs:14:5
    |
@@ -19,7 +13,6 @@ LL |
 LL | impl Ambiguous<Two> for Struct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr
index 0ec219415ab..9ca94cd58df 100644
--- a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr
+++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr
@@ -1,9 +1,17 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:10:16
    |
 LL |     (S {}).owo(None)
-   |                ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+   |            --- ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+   |            |
+   |            required by a bound introduced by this call
    |
+   = note: cannot satisfy `_: T`
+note: required by a bound in `S::owo`
+  --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:6:35
+   |
+LL |     fn owo(&self, _: Option<&impl T>) {}
+   |                                   ^ required by this bound in `S::owo`
 help: consider specifying the generic argument
    |
 LL |     (S {}).owo(None::<&_>)
@@ -11,4 +19,4 @@ LL |     (S {}).owo(None::<&_>)
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr
index 7a1e850d157..52baa213302 100644
--- a/tests/ui/inference/question-mark-type-infer.stderr
+++ b/tests/ui/inference/question-mark-type-infer.stderr
@@ -1,9 +1,12 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/question-mark-type-infer.rs:10:21
    |
 LL |     l.iter().map(f).collect()?
    |                     ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
    |
+   = note: cannot satisfy `_: FromIterator<Result<i32, ()>>`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 help: consider specifying the generic argument
    |
 LL |     l.iter().map(f).collect::<Vec<_>>()?
@@ -11,4 +14,4 @@ LL |     l.iter().map(f).collect::<Vec<_>>()?
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr
index 806b7f0ac05..d2a6a96082e 100644
--- a/tests/ui/issues/issue-12187-1.stderr
+++ b/tests/ui/issues/issue-12187-1.stderr
@@ -2,9 +2,9 @@ error[E0282]: type annotations needed for `&T`
   --> $DIR/issue-12187-1.rs:6:9
    |
 LL |     let &v = new();
-   |         ^^
+   |         ^^   ----- type must be known at this point
    |
-help: consider giving this pattern a type, where the placeholders `_` are specified
+help: consider giving this pattern a type, where the type for type parameter `T` is specified
    |
 LL |     let &v: &T = new();
    |           ++++
diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr
index a1fa0a2b002..ac75ebb4256 100644
--- a/tests/ui/issues/issue-12187-2.stderr
+++ b/tests/ui/issues/issue-12187-2.stderr
@@ -2,9 +2,9 @@ error[E0282]: type annotations needed for `&T`
   --> $DIR/issue-12187-2.rs:6:9
    |
 LL |     let &v = new();
-   |         ^^
+   |         ^^   ----- type must be known at this point
    |
-help: consider giving this pattern a type, where the placeholders `_` are specified
+help: consider giving this pattern a type, where the type for type parameter `T` is specified
    |
 LL |     let &v: &T = new();
    |           ++++
diff --git a/tests/ui/issues/issue-16966.stderr b/tests/ui/issues/issue-16966.stderr
index 8c92505b5eb..c53707c5d69 100644
--- a/tests/ui/issues/issue-16966.stderr
+++ b/tests/ui/issues/issue-16966.stderr
@@ -1,9 +1,16 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/issue-16966.rs:2:12
    |
 LL |     panic!(std::default::Default::default());
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+   |     -------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |     |      |
+   |     |      cannot infer type
+   |     required by a bound introduced by this call
+   |
+   = note: cannot satisfy `_: Any`
+note: required by a bound in `begin_panic`
+  --> $SRC_DIR/std/src/panicking.rs:LL:COL
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr
index 5f45a2f8443..3a8f569a3a5 100644
--- a/tests/ui/issues/issue-17551.stderr
+++ b/tests/ui/issues/issue-17551.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `B<T>`
   --> $DIR/issue-17551.rs:6:9
    |
 LL |     let foo = B(marker::PhantomData);
-   |         ^^^
+   |         ^^^     ------------------- type must be known at this point
    |
 help: consider giving `foo` an explicit type, where the type for type parameter `T` is specified
    |
diff --git a/tests/ui/issues/issue-24036.stderr b/tests/ui/issues/issue-24036.stderr
index a425816cdeb..184383b7369 100644
--- a/tests/ui/issues/issue-24036.stderr
+++ b/tests/ui/issues/issue-24036.stderr
@@ -11,12 +11,13 @@ LL |     x = |c| c + 1;
    = note: no two closures, even if identical, have the same type
    = help: consider boxing your closure and/or using it as a trait object
 
-error[E0282]: type annotations needed
+error[E0284]: type annotations needed
   --> $DIR/issue-24036.rs:9:15
    |
 LL |         1 => |c| c + 1,
-   |               ^
+   |               ^    - type must be known at this point
    |
+   = note: cannot satisfy `<_ as Add<i32>>::Output == _`
 help: consider giving this closure parameter an explicit type
    |
 LL |         1 => |c: /* Type */| c + 1,
@@ -24,5 +25,5 @@ LL |         1 => |c: /* Type */| c + 1,
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0282, E0308.
-For more information about an error, try `rustc --explain E0282`.
+Some errors have detailed explanations: E0284, E0308.
+For more information about an error, try `rustc --explain E0284`.
diff --git a/tests/ui/issues/issue-24446.stderr b/tests/ui/issues/issue-24446.stderr
index 4afb87c4825..72d528f1619 100644
--- a/tests/ui/issues/issue-24446.stderr
+++ b/tests/ui/issues/issue-24446.stderr
@@ -1,19 +1,19 @@
-error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time
+error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
   --> $DIR/issue-24446.rs:2:17
    |
 LL |     static foo: dyn Fn() -> u32 = || -> u32 {
-   |                 ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                 ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
    |
-   = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)`
+   = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)`
+   = note: shared static variables must have a type that implements `Sync`
 
-error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
+error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time
   --> $DIR/issue-24446.rs:2:17
    |
 LL |     static foo: dyn Fn() -> u32 = || -> u32 {
-   |                 ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
+   |                 ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)`
-   = note: shared static variables must have a type that implements `Sync`
+   = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr
index 07dc561f06a..45685ef0ce9 100644
--- a/tests/ui/iterators/collect-into-slice.stderr
+++ b/tests/ui/iterators/collect-into-slice.stderr
@@ -1,3 +1,13 @@
+error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
+  --> $DIR/collect-into-slice.rs:6:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |
+   = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
   --> $DIR/collect-into-slice.rs:6:9
    |
@@ -18,16 +28,6 @@ LL |     let some_generated_vec = (0..10).collect();
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
-error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:6:38
-   |
-LL |     let some_generated_vec = (0..10).collect();
-   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
-   |
-   = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
-note: required by a bound in `collect`
-  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-
 error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
   --> $DIR/collect-into-slice.rs:18:38
    |
diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index e0f8a5447b0..0a022dc3984 100644
--- a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec<T>`
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9
    |
 LL |     let mut x = Vec::new();
-   |         ^^^^^
+   |         ^^^^^   ---------- type must be known at this point
    |
 help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
    |
diff --git a/tests/ui/parser/assoc-const-underscore-semantic-fail.rs b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs
index d37ce06c555..d37ce06c555 100644
--- a/tests/ui/parser/assoc-const-underscore-semantic-fail.rs
+++ b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs
diff --git a/tests/ui/parser/assoc-const-underscore-semantic-fail.stderr b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr
index 538bf0ec100..538bf0ec100 100644
--- a/tests/ui/parser/assoc-const-underscore-semantic-fail.stderr
+++ b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr
diff --git a/tests/ui/parser/assoc-const-underscore-syntactic-pass.rs b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs
index 60da408c811..60da408c811 100644
--- a/tests/ui/parser/assoc-const-underscore-syntactic-pass.rs
+++ b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs
diff --git a/tests/ui/parser/assoc-oddities-1.rs b/tests/ui/parser/assoc/assoc-oddities-1.rs
index 5914805e5c1..5914805e5c1 100644
--- a/tests/ui/parser/assoc-oddities-1.rs
+++ b/tests/ui/parser/assoc/assoc-oddities-1.rs
diff --git a/tests/ui/parser/assoc-oddities-1.stderr b/tests/ui/parser/assoc/assoc-oddities-1.stderr
index acf71b4893a..acf71b4893a 100644
--- a/tests/ui/parser/assoc-oddities-1.stderr
+++ b/tests/ui/parser/assoc/assoc-oddities-1.stderr
diff --git a/tests/ui/parser/assoc-oddities-2.rs b/tests/ui/parser/assoc/assoc-oddities-2.rs
index 3d35aad7455..3d35aad7455 100644
--- a/tests/ui/parser/assoc-oddities-2.rs
+++ b/tests/ui/parser/assoc/assoc-oddities-2.rs
diff --git a/tests/ui/parser/assoc-oddities-2.stderr b/tests/ui/parser/assoc/assoc-oddities-2.stderr
index d3b90c34c29..d3b90c34c29 100644
--- a/tests/ui/parser/assoc-oddities-2.stderr
+++ b/tests/ui/parser/assoc/assoc-oddities-2.stderr
diff --git a/tests/ui/parser/assoc-static-semantic-fail.rs b/tests/ui/parser/assoc/assoc-static-semantic-fail.rs
index 403160f1253..403160f1253 100644
--- a/tests/ui/parser/assoc-static-semantic-fail.rs
+++ b/tests/ui/parser/assoc/assoc-static-semantic-fail.rs
diff --git a/tests/ui/parser/assoc-static-semantic-fail.stderr b/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr
index 8178bd22373..8178bd22373 100644
--- a/tests/ui/parser/assoc-static-semantic-fail.stderr
+++ b/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr
diff --git a/tests/ui/parser/assoc-static-syntactic-fail.rs b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs
index 492f2ea16ef..492f2ea16ef 100644
--- a/tests/ui/parser/assoc-static-syntactic-fail.rs
+++ b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs
diff --git a/tests/ui/parser/assoc-static-syntactic-fail.stderr b/tests/ui/parser/assoc/assoc-static-syntactic-fail.stderr
index e9723614512..e9723614512 100644
--- a/tests/ui/parser/assoc-static-syntactic-fail.stderr
+++ b/tests/ui/parser/assoc/assoc-static-syntactic-fail.stderr
diff --git a/tests/ui/parser/assoc-type-in-type-arg.rs b/tests/ui/parser/assoc/assoc-type-in-type-arg.rs
index 000956ea24f..000956ea24f 100644
--- a/tests/ui/parser/assoc-type-in-type-arg.rs
+++ b/tests/ui/parser/assoc/assoc-type-in-type-arg.rs
diff --git a/tests/ui/parser/assoc-type-in-type-arg.stderr b/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr
index b637702f21e..b637702f21e 100644
--- a/tests/ui/parser/assoc-type-in-type-arg.stderr
+++ b/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr
diff --git a/tests/ui/parser/associated-types-project-from-hrtb-explicit.rs b/tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.rs
index b238a9ca226..b238a9ca226 100644
--- a/tests/ui/parser/associated-types-project-from-hrtb-explicit.rs
+++ b/tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.rs
diff --git a/tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr b/tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.stderr
index aa0fa0e3c0a..aa0fa0e3c0a 100644
--- a/tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr
+++ b/tests/ui/parser/assoc/associated-types-project-from-hrtb-explicit.stderr
diff --git a/tests/ui/parser/issues/issue-15980.rs b/tests/ui/parser/issues/issue-15980.rs
index 87faa7d5ff1..eb7b6ca8296 100644
--- a/tests/ui/parser/issues/issue-15980.rs
+++ b/tests/ui/parser/issues/issue-15980.rs
@@ -9,9 +9,6 @@ fn main(){
             //~^ ERROR expected identifier, found keyword `return`
             //~| NOTE expected identifier, found keyword
         }
-        //~^ NOTE expected one of `.`, `=>`, `?`, or an operator
         _ => {}
-        //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_`
-        //~| NOTE unexpected token
     }
 }
diff --git a/tests/ui/parser/issues/issue-15980.stderr b/tests/ui/parser/issues/issue-15980.stderr
index c59c811199e..cf8d0114787 100644
--- a/tests/ui/parser/issues/issue-15980.stderr
+++ b/tests/ui/parser/issues/issue-15980.stderr
@@ -11,15 +11,10 @@ help: escape `return` to use it as an identifier
    |
 LL |             r#return
    |             ++
-
-error: expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_`
-  --> $DIR/issue-15980.rs:13:9
+help: you might have meant to start a match arm after the match guard
    |
-LL |         }
-   |          - expected one of `.`, `=>`, `?`, or an operator
-LL |
-LL |         _ => {}
-   |         ^ unexpected token
+LL |         Err(ref e) if e.kind == io::EndOfFile => {
+   |                                               ++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-52496.stderr b/tests/ui/parser/issues/issue-52496.stderr
index 77335c64c21..78c81bf5b0d 100644
--- a/tests/ui/parser/issues/issue-52496.stderr
+++ b/tests/ui/parser/issues/issue-52496.stderr
@@ -8,10 +8,15 @@ error: expected one of `,`, `:`, or `}`, found `.`
   --> $DIR/issue-52496.rs:8:22
    |
 LL |     let _ = Foo { bar.into(), bat: -1, . };
-   |             ---   -  ^ expected one of `,`, `:`, or `}`
+   |             ---   ---^ expected one of `,`, `:`, or `}`
    |             |     |
-   |             |     help: try naming a field: `bar:`
+   |             |     while parsing this struct field
    |             while parsing this struct
+   |
+help: try naming a field
+   |
+LL |     let _ = Foo { bar: bar.into(), bat: -1, . };
+   |                   ++++
 
 error: expected identifier, found `.`
   --> $DIR/issue-52496.rs:8:40
diff --git a/tests/ui/parser/issues/issue-89396.fixed b/tests/ui/parser/issues/issue-89396.fixed
index 823ad8cd1f8..0c040ddea44 100644
--- a/tests/ui/parser/issues/issue-89396.fixed
+++ b/tests/ui/parser/issues/issue-89396.fixed
@@ -8,9 +8,9 @@ fn main() {
     let _ = match opt {
         Some(_) => true,
         //~^ ERROR: expected one of
-        //~| HELP: try using a fat arrow here
+        //~| HELP: use a fat arrow to start a match arm
         None => false,
         //~^ ERROR: expected one of
-        //~| HELP: try using a fat arrow here
+        //~| HELP: use a fat arrow to start a match arm
     };
 }
diff --git a/tests/ui/parser/issues/issue-89396.rs b/tests/ui/parser/issues/issue-89396.rs
index f1d9efa524f..d95f666d797 100644
--- a/tests/ui/parser/issues/issue-89396.rs
+++ b/tests/ui/parser/issues/issue-89396.rs
@@ -8,9 +8,9 @@ fn main() {
     let _ = match opt {
         Some(_) = true,
         //~^ ERROR: expected one of
-        //~| HELP: try using a fat arrow here
+        //~| HELP: use a fat arrow to start a match arm
         None -> false,
         //~^ ERROR: expected one of
-        //~| HELP: try using a fat arrow here
+        //~| HELP: use a fat arrow to start a match arm
     };
 }
diff --git a/tests/ui/parser/issues/issue-89396.stderr b/tests/ui/parser/issues/issue-89396.stderr
index 504420574e2..41ce0705074 100644
--- a/tests/ui/parser/issues/issue-89396.stderr
+++ b/tests/ui/parser/issues/issue-89396.stderr
@@ -5,7 +5,7 @@ LL |         Some(_) = true,
    |                 ^
    |                 |
    |                 expected one of `=>`, `if`, or `|`
-   |                 help: try using a fat arrow here: `=>`
+   |                 help: use a fat arrow to start a match arm: `=>`
 
 error: expected one of `=>`, `@`, `if`, or `|`, found `->`
   --> $DIR/issue-89396.rs:12:14
@@ -14,7 +14,7 @@ LL |         None -> false,
    |              ^^
    |              |
    |              expected one of `=>`, `@`, `if`, or `|`
-   |              help: try using a fat arrow here: `=>`
+   |              help: use a fat arrow to start a match arm: `=>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/missing-fat-arrow.rs b/tests/ui/parser/missing-fat-arrow.rs
new file mode 100644
index 00000000000..325f1ccf2fd
--- /dev/null
+++ b/tests/ui/parser/missing-fat-arrow.rs
@@ -0,0 +1,38 @@
+fn main() {
+    let x = 1;
+    let y = 2;
+    let value = 3;
+
+    match value {
+        Some(x) if x == y {
+            self.next_token()?; //~ ERROR expected identifier, found keyword `self`
+        },
+        _ => {}
+    }
+    let _: i32 = (); //~ ERROR mismatched types
+}
+
+struct Foo {
+    value: usize
+}
+
+fn foo(a: Option<&mut Foo>, b: usize) {
+    match a {
+        Some(a) if a.value == b {
+            a.value = 1; //~ ERROR expected one of `,`, `:`, or `}`, found `.`
+        },
+        _ => {}
+    }
+    let _: i32 = (); //~ ERROR mismatched types
+}
+
+fn bar(a: Option<&mut Foo>, b: usize) {
+    match a {
+        Some(a) if a.value == b {
+            a.value, //~ ERROR expected one of `,`, `:`, or `}`, found `.`
+        } => {
+        }
+        _ => {}
+    }
+    let _: i32 = (); //~ ERROR mismatched types
+}
diff --git a/tests/ui/parser/missing-fat-arrow.stderr b/tests/ui/parser/missing-fat-arrow.stderr
new file mode 100644
index 00000000000..a6c786905e9
--- /dev/null
+++ b/tests/ui/parser/missing-fat-arrow.stderr
@@ -0,0 +1,78 @@
+error: expected identifier, found keyword `self`
+  --> $DIR/missing-fat-arrow.rs:8:13
+   |
+LL |         Some(x) if x == y {
+   |                         - while parsing this struct
+LL |             self.next_token()?;
+   |             ^^^^ expected identifier, found keyword
+   |
+help: you might have meant to start a match arm after the match guard
+   |
+LL |         Some(x) if x == y => {
+   |                           ++
+
+error: expected one of `,`, `:`, or `}`, found `.`
+  --> $DIR/missing-fat-arrow.rs:22:14
+   |
+LL |         Some(a) if a.value == b {
+   |                               - while parsing this struct
+LL |             a.value = 1;
+   |             -^ expected one of `,`, `:`, or `}`
+   |             |
+   |             while parsing this struct field
+   |
+help: try naming a field
+   |
+LL |             a: a.value = 1;
+   |             ++
+help: you might have meant to start a match arm after the match guard
+   |
+LL |         Some(a) if a.value == b => {
+   |                                 ++
+
+error: expected one of `,`, `:`, or `}`, found `.`
+  --> $DIR/missing-fat-arrow.rs:32:14
+   |
+LL |         Some(a) if a.value == b {
+   |                               - while parsing this struct
+LL |             a.value,
+   |             -^ expected one of `,`, `:`, or `}`
+   |             |
+   |             while parsing this struct field
+   |
+help: try naming a field
+   |
+LL |             a: a.value,
+   |             ++
+help: you might have meant to start a match arm after the match guard
+   |
+LL |         Some(a) if a.value == b => {
+   |                                 ++
+
+error[E0308]: mismatched types
+  --> $DIR/missing-fat-arrow.rs:12:18
+   |
+LL |     let _: i32 = ();
+   |            ---   ^^ expected `i32`, found `()`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/missing-fat-arrow.rs:26:18
+   |
+LL |     let _: i32 = ();
+   |            ---   ^^ expected `i32`, found `()`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/missing-fat-arrow.rs:37:18
+   |
+LL |     let _: i32 = ();
+   |            ---   ^^ expected `i32`, found `()`
+   |            |
+   |            expected due to this
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax-with-2.stderr
index c6ae1ce674f..e75c5bcd643 100644
--- a/tests/ui/parser/removed-syntax-with-2.stderr
+++ b/tests/ui/parser/removed-syntax-with-2.stderr
@@ -2,8 +2,9 @@ error: expected one of `,`, `:`, or `}`, found `a`
   --> $DIR/removed-syntax-with-2.rs:8:31
    |
 LL |     let b = S { foo: (), with a };
-   |             -                 ^ expected one of `,`, `:`, or `}`
-   |             |
+   |             -            ---- ^ expected one of `,`, `:`, or `}`
+   |             |            |
+   |             |            while parsing this struct field
    |             while parsing this struct
 
 error[E0063]: missing field `bar` in initializer of `S`
diff --git a/tests/ui/pattern/slice-patterns-irrefutable.stderr b/tests/ui/pattern/slice-patterns-irrefutable.stderr
index fac99534f3e..e98ee28d686 100644
--- a/tests/ui/pattern/slice-patterns-irrefutable.stderr
+++ b/tests/ui/pattern/slice-patterns-irrefutable.stderr
@@ -3,6 +3,9 @@ error[E0282]: type annotations needed for `[_; 3]`
    |
 LL |     let b;
    |         ^
+LL |
+LL |     [a, b] = Default::default();
+   |      - type must be known at this point
    |
 help: consider giving `b` an explicit type, where the placeholders `_` are specified
    |
diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr
index 84ecd749b0d..656f71eb877 100644
--- a/tests/ui/suggestions/slice-issue-87994.stderr
+++ b/tests/ui/suggestions/slice-issue-87994.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+error[E0277]: `[i32]` is not an iterator
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
@@ -13,7 +13,7 @@ LL |   for _ in &v[1..] {
 LL |   for _ in &mut v[1..] {
    |            ++++
 
-error[E0277]: `[i32]` is not an iterator
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
@@ -28,7 +28,7 @@ LL |   for _ in &v[1..] {
 LL |   for _ in &mut v[1..] {
    |            ++++
 
-error[E0277]: the size for values of type `[K]` cannot be known at compilation time
+error[E0277]: `[K]` is not an iterator
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
@@ -43,7 +43,7 @@ LL |   for i2 in &v2[1..] {
 LL |   for i2 in &mut v2[1..] {
    |             ++++
 
-error[E0277]: `[K]` is not an iterator
+error[E0277]: the size for values of type `[K]` cannot be known at compilation time
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr
index 568b7e5a64a..7e676c9da01 100644
--- a/tests/ui/traits/copy-guessing.stderr
+++ b/tests/ui/traits/copy-guessing.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Option<T>`
   --> $DIR/copy-guessing.rs:20:9
    |
 LL |     let n = None;
-   |         ^
+   |         ^   ---- type must be known at this point
    |
 help: consider giving `n` an explicit type, where the type for type parameter `T` is specified
    |
diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs
index 9a444be500c..205b1173e07 100644
--- a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs
+++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs
@@ -14,7 +14,5 @@ impl<X> Method<u32> for Thing<X> {
 
 fn main() {
     let thing = Thing(true);
-    thing.method(42);
-    //~^ ERROR type annotations needed
-    //~| ERROR type annotations needed
+    thing.method(42); //~ ERROR type annotations needed
 }
diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr
index 57b2587ae5c..2185c51e59d 100644
--- a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr
+++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr
@@ -1,14 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
-   |
-LL |     thing.method(42);
-   |           ^^^^^^
-   |
-help: try using a fully qualified path to specify the expected types
-   |
-LL |     <Thing<bool> as Method<T>>::method(thing, 42);
-   |     +++++++++++++++++++++++++++++++++++     ~
-
 error[E0283]: type annotations needed
   --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
    |
@@ -28,7 +17,6 @@ help: try using a fully qualified path to specify the expected types
 LL |     <Thing<bool> as Method<T>>::method(thing, 42);
    |     +++++++++++++++++++++++++++++++++++     ~
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs
index f5be6cf21c1..2331dda9168 100644
--- a/tests/ui/traits/issue-77982.rs
+++ b/tests/ui/traits/issue-77982.rs
@@ -1,3 +1,4 @@
+// ignore-windows different list of satisfying impls
 use std::collections::HashMap;
 
 fn what() {
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index 33cc186ac0b..592cfd970c6 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -1,5 +1,5 @@
 error[E0283]: type annotations needed
-  --> $DIR/issue-77982.rs:8:10
+  --> $DIR/issue-77982.rs:9:10
    |
 LL |     opts.get(opt.as_ref());
    |          ^^^ ------------ type must be known at this point
@@ -18,7 +18,7 @@ LL |     opts.get::<Q>(opt.as_ref());
    |             +++++
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-77982.rs:8:10
+  --> $DIR/issue-77982.rs:9:10
    |
 LL |     opts.get(opt.as_ref());
    |          ^^^     ------ type must be known at this point
@@ -35,25 +35,34 @@ help: consider specifying the generic argument
 LL |     opts.get::<Q>(opt.as_ref());
    |             +++++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-77982.rs:13:59
+error[E0283]: type annotations needed
+  --> $DIR/issue-77982.rs:14:59
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
-   |                                                           ^^^^
-   |
+   |                                            ---            ^^^^
+   |                                            |
+   |                                            type must be known at this point
+   |
+   = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate:
+           - impl From<Ipv4Addr> for u32;
+           - impl From<NonZeroU32> for u32;
+           - impl From<bool> for u32;
+           - impl From<char> for u32;
+           - impl From<u16> for u32;
+           - impl From<u8> for u32;
 help: try using a fully qualified path to specify the expected types
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
    |                                                      +++++++++++++++++++++++    ~
 
 error[E0283]: type annotations needed for `Box<T>`
-  --> $DIR/issue-77982.rs:36:9
+  --> $DIR/issue-77982.rs:37:9
    |
 LL |     let _ = ().foo();
    |         ^      --- type must be known at this point
    |
 note: multiple `impl`s satisfying `(): Foo<'_, _>` found
-  --> $DIR/issue-77982.rs:29:1
+  --> $DIR/issue-77982.rs:30:1
    |
 LL | impl Foo<'static, u32> for () {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -65,13 +74,13 @@ LL |     let _: Box<T> = ().foo();
    |          ++++++++
 
 error[E0283]: type annotations needed for `Box<T>`
-  --> $DIR/issue-77982.rs:40:9
+  --> $DIR/issue-77982.rs:41:9
    |
 LL |     let _ = (&()).bar();
    |         ^         --- type must be known at this point
    |
 note: multiple `impl`s satisfying `&(): Bar<'_, _>` found
-  --> $DIR/issue-77982.rs:32:1
+  --> $DIR/issue-77982.rs:33:1
    |
 LL | impl<'a> Bar<'static, u32> for &'a () {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,5 +93,4 @@ LL |     let _: Box<T> = (&()).bar();
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.rs b/tests/ui/traits/multidispatch-convert-ambig-dest.rs
index aa74e11c362..36e1e868fca 100644
--- a/tests/ui/traits/multidispatch-convert-ambig-dest.rs
+++ b/tests/ui/traits/multidispatch-convert-ambig-dest.rs
@@ -25,7 +25,6 @@ where T : Convert<U>
 fn a() {
     test(22, std::default::Default::default());
     //~^ ERROR type annotations needed
-    //~| ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
index e927f26e96d..e3bfc78bb08 100644
--- a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
+++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
@@ -1,14 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
-   |
-LL |     test(22, std::default::Default::default());
-   |     ^^^^ cannot infer type of the type parameter `U` declared on the function `test`
-   |
-help: consider specifying the generic arguments
-   |
-LL |     test::<i32, U>(22, std::default::Default::default());
-   |         ++++++++++
-
 error[E0283]: type annotations needed
   --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
    |
@@ -37,7 +26,6 @@ help: consider specifying the generic arguments
 LL |     test::<i32, U>(22, std::default::Default::default());
    |         ++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs
index 38d83d289f1..825e874d71b 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.rs
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs
@@ -27,6 +27,5 @@ fn main() {
     //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
     //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
     //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
-    //~| ERROR type annotations needed
     println!("{x}");
 }
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
index abc6677c132..ca4b5c90ff2 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
@@ -11,18 +11,7 @@ note: required by a bound in `Foo::Item`
 LL |     type Item: Copy
    |                ^^^^ required by this bound in `Foo::Item`
 
-error[E0282]: type annotations needed
-  --> $DIR/alias-bound-unsound.rs:24:5
-   |
-LL |     drop(<() as Foo>::copy_me(&x));
-   |     ^^^^ cannot infer type of the type parameter `T` declared on the function `drop`
-   |
-help: consider specifying the generic argument
-   |
-LL |     drop::<T>(<() as Foo>::copy_me(&x));
-   |         +++++
-
-error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed`
+error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item`
   --> $DIR/alias-bound-unsound.rs:24:31
    |
 LL |     drop(<() as Foo>::copy_me(&x));
@@ -30,40 +19,39 @@ LL |     drop(<() as Foo>::copy_me(&x));
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
 
-error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item`
-  --> $DIR/alias-bound-unsound.rs:24:31
+error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
+  --> $DIR/alias-bound-unsound.rs:24:10
    |
 LL |     drop(<() as Foo>::copy_me(&x));
-   |                               ^^
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
 
-error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed`
+error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized`
   --> $DIR/alias-bound-unsound.rs:24:10
    |
 LL |     drop(<() as Foo>::copy_me(&x));
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
+   = note: the return type of a function must have a statically known size
 
-error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
-  --> $DIR/alias-bound-unsound.rs:24:10
+error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed`
+  --> $DIR/alias-bound-unsound.rs:24:31
    |
 LL |     drop(<() as Foo>::copy_me(&x));
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
 
-error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized`
+error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed`
   --> $DIR/alias-bound-unsound.rs:24:10
    |
 LL |     drop(<() as Foo>::copy_me(&x));
-   |          ^^^^^^^^^^^^^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
-   = note: the return type of a function must have a statically known size
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0275, E0282.
-For more information about an error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr
index 47004821ad7..414deb47727 100644
--- a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr
+++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr
@@ -1,9 +1,16 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/runaway-impl-candidate-selection.rs:13:22
    |
 LL |     println!("{:?}", iter::<_>());
    |                      ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter`
+   |
+   = note: cannot satisfy `_: Iterator`
+note: required by a bound in `iter`
+  --> $DIR/runaway-impl-candidate-selection.rs:8:12
+   |
+LL | fn iter<T: Iterator>() -> <T as Iterator>::Item {
+   |            ^^^^^^^^ required by this bound in `iter`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
index fcafdcf637a..44e763ef990 100644
--- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
+++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
@@ -27,6 +27,5 @@ fn impls<T: Trait>() {}
 
 fn main() {
     impls::<W<_>>();
-    //~^ ERROR type annotations needed
-    //~| ERROR overflow evaluating the requirement
+    //~^ ERROR overflow evaluating the requirement
 }
diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
index a861156711d..1ac0e297729 100644
--- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
+++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
@@ -1,9 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/fixpoint-exponential-growth.rs:29:5
-   |
-LL |     impls::<W<_>>();
-   |     ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls`
-
 error[E0275]: overflow evaluating the requirement `W<_>: Trait`
   --> $DIR/fixpoint-exponential-growth.rs:29:13
    |
@@ -17,7 +11,6 @@ note: required by a bound in `impls`
 LL | fn impls<T: Trait>() {}
    |             ^^^^^ required by this bound in `impls`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0275, E0282.
-For more information about an error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
index 9a8060133b8..9aa4f4531f9 100644
--- a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
@@ -1,9 +1,18 @@
-error[E0282]: type annotations needed
+error[E0284]: type annotations needed: cannot satisfy `<<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc == <<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc`
   --> $DIR/generalize-proj-new-universe-index-2.rs:74:5
    |
 LL |     bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc == <<Leaf as WithAssoc<_>>::Assoc as Id>::Assoc`
+   |
+note: required by a bound in `bound`
+  --> $DIR/generalize-proj-new-universe-index-2.rs:69:21
+   |
+LL | fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+   |    ----- required by a bound in this function
+LL | where
+LL |     T: WithAssoc<U, Assoc = V>,
+   |                     ^^^^^^^^^ required by this bound in `bound`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
index 06283201261..f482e8cfaf9 100644
--- a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
+++ b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
@@ -1,9 +1,17 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5
    |
 LL |     foo(unconstrained())
-   |     ^^^ cannot infer type of the type parameter `T` declared on the function `foo`
+   |     ^^^ --------------- type must be known at this point
+   |     |
+   |     cannot infer type of the type parameter `T` declared on the function `foo`
    |
+   = note: cannot satisfy `_: Trait`
+note: required by a bound in `foo`
+  --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:19:11
+   |
+LL | fn foo<T: Trait<Assoc = u8>>(x: T) {}
+   |           ^^^^^^^^^^^^^^^^^ required by this bound in `foo`
 help: consider specifying the generic argument
    |
 LL |     foo::<T>(unconstrained())
@@ -11,4 +19,4 @@ LL |     foo::<T>(unconstrained())
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs
index b37f09ee185..3d2e70a639f 100644
--- a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs
+++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs
@@ -15,6 +15,5 @@ fn impls<T: Trait>() {}
 
 fn main() {
     impls::<W<_>>();
-    //~^ ERROR type annotations needed
-    //~| ERROR overflow evaluating the requirement `W<_>: Trait`
+    //~^ ERROR overflow evaluating the requirement `W<_>: Trait`
 }
diff --git a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr
index beed40f3649..023efc41aeb 100644
--- a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr
+++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr
@@ -1,9 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/exponential-trait-goals.rs:17:5
-   |
-LL |     impls::<W<_>>();
-   |     ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls`
-
 error[E0275]: overflow evaluating the requirement `W<_>: Trait`
   --> $DIR/exponential-trait-goals.rs:17:13
    |
@@ -17,7 +11,6 @@ note: required by a bound in `impls`
 LL | fn impls<T: Trait>() {}
    |             ^^^^^ required by this bound in `impls`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0275, E0282.
-For more information about an error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
index ed9b57cb1bd..d8db07277c5 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
@@ -23,13 +23,13 @@ LL | where
 LL |     for<V> V: Sized,
    |               ^^^^^ required by this bound in `foo`
 
-error[E0277]: the size for values of type `V` cannot be known at compilation time
+error[E0277]: `V` is not an iterator
   --> $DIR/bad-sized-cond.rs:20:5
    |
 LL |     bar();
-   |     ^^^ doesn't have a size known at compile-time
+   |     ^^^ `V` is not an iterator
    |
-   = help: the trait `Sized` is not implemented for `V`
+   = help: the trait `Iterator` is not implemented for `V`
    = note: required for `V` to implement `IntoIterator`
 note: required by a bound in `bar`
   --> $DIR/bad-sized-cond.rs:12:15
@@ -40,13 +40,13 @@ LL | where
 LL |     for<V> V: IntoIterator,
    |               ^^^^^^^^^^^^ required by this bound in `bar`
 
-error[E0277]: `V` is not an iterator
+error[E0277]: the size for values of type `V` cannot be known at compilation time
   --> $DIR/bad-sized-cond.rs:20:5
    |
 LL |     bar();
-   |     ^^^ `V` is not an iterator
+   |     ^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `Iterator` is not implemented for `V`
+   = help: the trait `Sized` is not implemented for `V`
    = note: required for `V` to implement `IntoIterator`
 note: required by a bound in `bar`
   --> $DIR/bad-sized-cond.rs:12:15
diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs
index 538e74ee1b0..e9e2f6b1290 100644
--- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs
+++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs
@@ -18,7 +18,5 @@ where
 
 fn main() {
     let a = A(B);
-    a.method();
-    //~^ ERROR type annotations needed
-    //~| ERROR type annotations needed
+    a.method(); //~ ERROR type annotations needed
 }
diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
index 92d9d32cf9c..86ae49b32fc 100644
--- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
+++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
@@ -1,14 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7
-   |
-LL |     a.method();
-   |       ^^^^^^
-   |
-help: try using a fully qualified path to specify the expected types
-   |
-LL |     <A<B> as V<U>>::method(a);
-   |     +++++++++++++++++++++++ ~
-
 error[E0283]: type annotations needed
   --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7
    |
@@ -35,7 +24,6 @@ help: try using a fully qualified path to specify the expected types
 LL |     <A<B> as V<U>>::method(a);
    |     +++++++++++++++++++++++ ~
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr
index 2aea3783fea..43cef7027a2 100644
--- a/tests/ui/traits/suggest-fully-qualified-closure.stderr
+++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr
@@ -1,14 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/suggest-fully-qualified-closure.rs:23:7
-   |
-LL |     q.lol(||());
-   |       ^^^
-   |
-help: try using a fully qualified path to specify the expected types
-   |
-LL |     <Qqq as MyTrait<T>>::lol::<{closure@}>(&q, ||());
-   |     +++ ~
-
 error[E0283]: type annotations needed
   --> $DIR/suggest-fully-qualified-closure.rs:23:7
    |
@@ -28,7 +17,6 @@ help: try using a fully qualified path to specify the expected types
 LL |     <Qqq as MyTrait<T>>::lol::<{closure@}>(&q, ||());
    |     +++ ~
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs
index 9a2cf469d08..f0861857bf7 100644
--- a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs
+++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs
@@ -42,9 +42,7 @@ impl<T> DerefMut for DerefsTo<T> {
 
 fn main() {
     let mut thing = Thing;
-    thing.method();
-    //~^ ERROR type annotations needed
-    //~| ERROR type annotations needed
+    thing.method(); //~ ERROR type annotations needed
     thing.mut_method(); //~ ERROR type annotations needed
     thing.by_self(); //~ ERROR type annotations needed
 
diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr
index 68b31a1ca34..841acb5ffd3 100644
--- a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr
+++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr
@@ -1,14 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11
-   |
-LL |     thing.method();
-   |           ^^^^^^
-   |
-help: try using a fully qualified path to specify the expected types
-   |
-LL |     <Thing as Method<T>>::method(&thing);
-   |     ++++++++++++++++++++++++++++++     ~
-
 error[E0283]: type annotations needed
   --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11
    |
@@ -29,7 +18,7 @@ LL |     <Thing as Method<T>>::method(&thing);
    |     ++++++++++++++++++++++++++++++     ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:48:11
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:46:11
    |
 LL |     thing.mut_method();
    |           ^^^^^^^^^^
@@ -48,7 +37,7 @@ LL |     <Thing as Method<T>>::mut_method(&mut thing);
    |     +++++++++++++++++++++++++++++++++++++      ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:49:11
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:47:11
    |
 LL |     thing.by_self();
    |           ^^^^^^^
@@ -67,7 +56,7 @@ LL |     <&Thing as MethodRef<T>>::by_self(&thing);
    |     +++++++++++++++++++++++++++++++++++     ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:50:14
    |
 LL |     deref_to.method();
    |              ^^^^^^
@@ -86,7 +75,7 @@ LL |     <Thing as Method<T>>::method(&deref_to);
    |     ++++++++++++++++++++++++++++++        ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:53:14
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:51:14
    |
 LL |     deref_to.mut_method();
    |              ^^^^^^^^^^
@@ -105,7 +94,7 @@ LL |     <Thing as Method<T>>::mut_method(&mut deref_to);
    |     +++++++++++++++++++++++++++++++++++++         ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:54:14
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14
    |
 LL |     deref_to.by_self();
    |              ^^^^^^^
@@ -124,7 +113,7 @@ LL |     <&Thing as MethodRef<T>>::by_self(&deref_to);
    |     +++++++++++++++++++++++++++++++++++        ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:55:20
    |
 LL |     deref_deref_to.method();
    |                    ^^^^^^
@@ -143,7 +132,7 @@ LL |     <Thing as Method<T>>::method(&deref_deref_to);
    |     ++++++++++++++++++++++++++++++              ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:58:20
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:56:20
    |
 LL |     deref_deref_to.mut_method();
    |                    ^^^^^^^^^^
@@ -162,7 +151,7 @@ LL |     <Thing as Method<T>>::mut_method(&mut deref_deref_to);
    |     +++++++++++++++++++++++++++++++++++++               ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:59:20
+  --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20
    |
 LL |     deref_deref_to.by_self();
    |                    ^^^^^^^
@@ -180,7 +169,6 @@ help: try using a fully qualified path to specify the expected types
 LL |     <&Thing as MethodRef<T>>::by_self(&deref_deref_to);
    |     +++++++++++++++++++++++++++++++++++              ~
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs
index da640c8c8c2..6a63e27f75f 100644
--- a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs
+++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs
@@ -42,9 +42,7 @@ impl<T> DerefMut for DerefsTo<T> {
 
 fn main() {
     let mut ref_thing = &Thing;
-    ref_thing.method();
-    //~^ ERROR type annotations needed
-    //~| ERROR type annotations needed
+    ref_thing.method(); //~ ERROR type annotations needed
     ref_thing.by_self(); //~ ERROR type annotations needed
 
     let mut mut_thing = &mut Thing;
diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr
index 27518a54e75..1865d81bad1 100644
--- a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr
+++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr
@@ -1,14 +1,3 @@
-error[E0282]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15
-   |
-LL |     ref_thing.method();
-   |               ^^^^^^
-   |
-help: try using a fully qualified path to specify the expected types
-   |
-LL |     <Thing as Method<T>>::method(ref_thing);
-   |     +++++++++++++++++++++++++++++         ~
-
 error[E0283]: type annotations needed
   --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15
    |
@@ -29,7 +18,7 @@ LL |     <Thing as Method<T>>::method(ref_thing);
    |     +++++++++++++++++++++++++++++         ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:48:15
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:46:15
    |
 LL |     ref_thing.by_self();
    |               ^^^^^^^
@@ -48,7 +37,7 @@ LL |     <&Thing as MethodRef<T>>::by_self(ref_thing);
    |     ++++++++++++++++++++++++++++++++++         ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:49:15
    |
 LL |     mut_thing.method();
    |               ^^^^^^
@@ -67,7 +56,7 @@ LL |     <Thing as Method<T>>::method(mut_thing);
    |     +++++++++++++++++++++++++++++         ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:52:15
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:50:15
    |
 LL |     mut_thing.mut_method();
    |               ^^^^^^^^^^
@@ -86,7 +75,7 @@ LL |     <Thing as Method<T>>::mut_method(mut_thing);
    |     +++++++++++++++++++++++++++++++++         ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:53:15
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15
    |
 LL |     mut_thing.by_self();
    |               ^^^^^^^
@@ -105,7 +94,7 @@ LL |     <&Thing as MethodRef<T>>::by_self(mut_thing);
    |     ++++++++++++++++++++++++++++++++++         ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:54:14
    |
 LL |     deref_to.method();
    |              ^^^^^^
@@ -124,7 +113,7 @@ LL |     <Thing as Method<T>>::method(deref_to);
    |     +++++++++++++++++++++++++++++        ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:57:14
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:55:14
    |
 LL |     deref_to.mut_method();
    |              ^^^^^^^^^^
@@ -143,7 +132,7 @@ LL |     <Thing as Method<T>>::mut_method(deref_to);
    |     +++++++++++++++++++++++++++++++++        ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:58:14
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14
    |
 LL |     deref_to.by_self();
    |              ^^^^^^^
@@ -162,7 +151,7 @@ LL |     <&Thing as MethodRef<T>>::by_self(deref_to);
    |     ++++++++++++++++++++++++++++++++++        ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:59:20
    |
 LL |     deref_deref_to.method();
    |                    ^^^^^^
@@ -181,7 +170,7 @@ LL |     <Thing as Method<T>>::method(deref_deref_to);
    |     +++++++++++++++++++++++++++++              ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:62:20
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:60:20
    |
 LL |     deref_deref_to.mut_method();
    |                    ^^^^^^^^^^
@@ -200,7 +189,7 @@ LL |     <Thing as Method<T>>::mut_method(deref_deref_to);
    |     +++++++++++++++++++++++++++++++++              ~
 
 error[E0283]: type annotations needed
-  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:63:20
+  --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20
    |
 LL |     deref_deref_to.by_self();
    |                    ^^^^^^^
@@ -218,7 +207,6 @@ help: try using a fully qualified path to specify the expected types
 LL |     <&Thing as MethodRef<T>>::by_self(deref_deref_to);
    |     ++++++++++++++++++++++++++++++++++              ~
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-inference/sort_by_key.stderr b/tests/ui/type-inference/sort_by_key.stderr
index de7b4b24899..81af024b3fb 100644
--- a/tests/ui/type-inference/sort_by_key.stderr
+++ b/tests/ui/type-inference/sort_by_key.stderr
@@ -1,9 +1,14 @@
-error[E0282]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/sort_by_key.rs:3:40
    |
 LL |     lst.sort_by_key(|&(v, _)| v.iter().sum());
-   |                                        ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
+   |         -----------                    ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
+   |         |
+   |         type must be known at this point
    |
+   = note: cannot satisfy `_: Ord`
+note: required by a bound in `slice::<impl [T]>::sort_by_key`
+  --> $SRC_DIR/alloc/src/slice.rs:LL:COL
 help: consider specifying the generic argument
    |
 LL |     lst.sort_by_key(|&(v, _)| v.iter().sum::<S>());
@@ -11,4 +16,4 @@ LL |     lst.sort_by_key(|&(v, _)| v.iter().sum::<S>());
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr
index 09c4b2053b2..7be00341d10 100644
--- a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr
+++ b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/cannot_infer_local_or_vec.rs:2:9
    |
 LL |     let x = vec![];
-   |         ^
+   |         ^   ------ type must be known at this point
    |
 help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr
index 2aec641e71e..cd6c051feed 100644
--- a/tests/ui/wf/wf-fn-where-clause.stderr
+++ b/tests/ui/wf/wf-fn-where-clause.stderr
@@ -14,6 +14,15 @@ help: consider further restricting type parameter `U`
 LL | fn foo<T,U>() where T: ExtraCopy<U>, U: std::marker::Copy
    |                                    ++++++++++++++++++++++
 
+error[E0038]: the trait `Copy` cannot be made into an object
+  --> $DIR/wf-fn-where-clause.rs:12:16
+   |
+LL | fn bar() where Vec<dyn Copy>:, {}
+   |                ^^^^^^^^^^^^^ `Copy` cannot be made into an object
+   |
+   = note: the trait cannot be made into an object because it requires `Self: Sized`
+   = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+
 error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time
   --> $DIR/wf-fn-where-clause.rs:12:16
    |
@@ -34,15 +43,6 @@ LL | struct Vec<T> {
 LL |     t: T,
    |        - ...if indirection were used here: `Box<T>`
 
-error[E0038]: the trait `Copy` cannot be made into an object
-  --> $DIR/wf-fn-where-clause.rs:12:16
-   |
-LL | fn bar() where Vec<dyn Copy>:, {}
-   |                ^^^^^^^^^^^^^ `Copy` cannot be made into an object
-   |
-   = note: the trait cannot be made into an object because it requires `Self: Sized`
-   = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0038, E0277.