about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-24 06:37:41 +0000
committerbors <bors@rust-lang.org>2024-04-24 06:37:41 +0000
commita3fddf2384f9dc0d67252a2ec3481c8e27121aa3 (patch)
tree24d179c88d79c08cb94c57cca50cdfaa7579c1a3
parent26faaa30475a1be4cc26e13882e8d943df91f3d1 (diff)
parent7e968351aa7abb766f56640f7dd9460749ef6f2b (diff)
downloadrust-a3fddf2384f9dc0d67252a2ec3481c8e27121aa3.tar.gz
rust-a3fddf2384f9dc0d67252a2ec3481c8e27121aa3.zip
Auto merge of #3506 - rust-lang:rustup-2024-04-24, r=RalfJung
Automatic Rustup
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs2
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs29
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs29
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs6
-rw-r--r--compiler/rustc_borrowck/src/polonius/loan_invalidations.rs19
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock239
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml14
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/example/alloc_example.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/example/alloc_system.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/example/example.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/mod_bench.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/example/neon.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch5
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs27
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/object.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs26
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs18
-rw-r--r--compiler/rustc_codegen_gcc/example/example.rs7
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs27
-rw-r--r--compiler/rustc_const_eval/messages.ftl12
-rw-r--r--compiler/rustc_const_eval/src/const_eval/dummy_machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/errors.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs22
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs31
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs23
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/resolver.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0522.md2
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs6
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs66
-rw-r--r--compiler/rustc_errors/src/lib.rs33
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs46
-rw-r--r--compiler/rustc_hir/src/lang_items.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs47
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs115
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs25
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs518
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs65
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs13
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs18
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs16
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_interface/src/queries.rs16
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/builtin.rs102
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs18
-rw-r--r--compiler/rustc_lint/src/errors.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs18
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs39
-rw-r--r--compiler/rustc_macros/src/lib.rs1
-rw-r--r--compiler/rustc_metadata/src/creader.rs44
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs15
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs2
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs14
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs99
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs3
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs9
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs71
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/thir.rs5
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs38
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs39
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs4
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs13
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs129
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs101
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs161
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_build/src/errors.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs2
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs40
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs23
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs2
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs153
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs13
-rw-r--r--compiler/rustc_parse/messages.ftl6
-rw-r--r--compiler/rustc_parse/src/errors.rs20
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs38
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_parse/src/parser/path.rs1
-rw-r--r--compiler/rustc_passes/messages.ftl23
-rw-r--r--compiler/rustc_passes/src/check_attr.rs25
-rw-r--r--compiler/rustc_passes/src/errors.rs12
-rw-r--r--compiler/rustc_passes/src/lang_items.rs2
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/errors.rs4
-rw-r--r--compiler/rustc_resolve/src/errors.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs12
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/config.rs8
-rw-r--r--compiler/rustc_session/src/cstore.rs7
-rw-r--r--compiler/rustc_session/src/search_paths.rs9
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs13
-rw-r--r--compiler/rustc_span/src/hygiene.rs2
-rw-r--r--compiler/rustc_span/src/source_map.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs27
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs2
-rw-r--r--compiler/stable_mir/src/mir/body.rs21
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs5
-rw-r--r--library/core/src/alloc/layout.rs4
-rw-r--r--library/core/src/fmt/rt.rs2
-rw-r--r--library/core/src/intrinsics.rs47
-rw-r--r--library/core/src/num/nonzero.rs14
-rw-r--r--library/core/src/num/uint_macros.rs25
-rw-r--r--library/core/src/option.rs4
-rw-r--r--library/core/src/panic.rs4
-rw-r--r--library/core/src/panicking.rs27
-rw-r--r--library/std/src/sync/reentrant_lock/tests.rs9
-rw-r--r--src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md2
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip1.md2
-rw-r--r--src/doc/rustdoc/src/lints.md2
-rw-r--r--src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md2
-rw-r--r--src/librustdoc/config.rs11
-rw-r--r--src/librustdoc/lint.rs2
-rw-r--r--src/rustdoc-json-types/lib.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs6
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed6
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs6
-rw-r--r--src/tools/lint-docs/src/groups.rs4
-rw-r--r--src/tools/lint-docs/src/lib.rs1
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs2
-rw-r--r--src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs5
-rw-r--r--src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr4
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.rs15
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr15
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs9
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs2
-rw-r--r--src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.rs12
-rw-r--r--src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr15
-rw-r--r--src/tools/miri/tests/fail/validity/wrong-dyn-trait.rs6
-rw-r--r--src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr15
-rw-r--r--src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs2
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.rs42
-rw-r--r--src/tools/rustfmt/tests/source/attrib.rs4
-rw-r--r--src/tools/rustfmt/tests/target/attrib.rs4
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--tests/codegen/intrinsics/ctlz.rs56
-rw-r--r--tests/codegen/intrinsics/ctpop.rs31
-rw-r--r--tests/codegen/intrinsics/rotate_left.rs31
-rw-r--r--tests/crashes/122552.rs10
-rw-r--r--tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir12
-rw-r--r--tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir12
-rw-r--r--tests/mir-opt/building/match/match_false_edges.main.built.after.mir20
-rw-r--r--tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir24
-rw-r--r--tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir24
-rw-r--r--tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff8
-rw-r--r--tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff8
-rw-r--r--tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff20
-rw-r--r--tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff20
-rw-r--r--tests/pretty/ast-stmt-expr-attr.rs18
-rw-r--r--tests/pretty/stmt_expr_attributes.rs12
-rw-r--r--tests/rustdoc-gui/notable-trait.goml208
-rw-r--r--tests/rustdoc-ui/invalid_associated_const.stderr9
-rw-r--r--tests/rustdoc-ui/issue-102467.stderr9
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.rs4
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs10
-rw-r--r--tests/ui-fulldeps/stable-mir/check_transform.rs4
-rw-r--r--tests/ui/assoc-lang-items.stderr16
-rw-r--r--tests/ui/associated-consts/issue-102335-const.stderr9
-rw-r--r--tests/ui/associated-type-bounds/issue-102335-ty.rs8
-rw-r--r--tests/ui/associated-type-bounds/issue-102335-ty.stderr38
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.rs120
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.stderr366
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr1
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.stderr1
-rw-r--r--tests/ui/cast/cast-rfc0401-vtable-kinds.rs2
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr5
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013.stderr5
-rw-r--r--tests/ui/consts/const-eval/promoted_errors.noopt.stderr44
-rw-r--r--tests/ui/consts/const-eval/promoted_errors.opt.stderr44
-rw-r--r--tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr44
-rw-r--r--tests/ui/consts/const-eval/promoted_errors.rs52
-rw-r--r--tests/ui/consts/promote-not.rs9
-rw-r--r--tests/ui/consts/promote-not.stderr50
-rw-r--r--tests/ui/consts/promotion.rs36
-rw-r--r--tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr23
-rw-r--r--tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr39
-rw-r--r--tests/ui/consts/required-consts/collect-in-promoted-const.rs26
-rw-r--r--tests/ui/consts/required-consts/interpret-in-promoted.rs2
-rw-r--r--tests/ui/coroutine/clone-impl.rs24
-rw-r--r--tests/ui/coroutine/clone-impl.stderr72
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs10
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr17
-rw-r--r--tests/ui/derives/issue-91550.stderr27
-rw-r--r--tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr1
-rw-r--r--tests/ui/error-codes/E0229.stderr13
-rw-r--r--tests/ui/error-codes/E0522.rs2
-rw-r--r--tests/ui/error-codes/E0522.stderr4
-rw-r--r--tests/ui/error-codes/E0718.rs2
-rw-r--r--tests/ui/error-codes/E0718.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-lang-items.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-lang-items.stderr6
-rw-r--r--tests/ui/generic-associated-types/issue-102335-gat.stderr9
-rw-r--r--tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.rs11
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.stderr44
-rw-r--r--tests/ui/impl-trait/issues/issue-84073.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-84073.stderr4
-rw-r--r--tests/ui/impl-trait/precise-capturing/unexpected-token.rs9
-rw-r--r--tests/ui/impl-trait/precise-capturing/unexpected-token.stderr16
-rw-r--r--tests/ui/intrinsics/bad-intrinsic-monomorphization.rs2
-rw-r--r--tests/ui/intrinsics/intrinsics-integer.rs10
-rw-r--r--tests/ui/lang-items/issue-83471.rs6
-rw-r--r--tests/ui/lang-items/issue-83471.stderr6
-rw-r--r--tests/ui/lang-items/issue-87573.rs4
-rw-r--r--tests/ui/lang-items/issue-87573.stderr4
-rw-r--r--tests/ui/lang-items/lang-item-generic-requirements.rs12
-rw-r--r--tests/ui/lang-items/lang-item-generic-requirements.stderr12
-rw-r--r--tests/ui/lang-items/start_lang_item_with_target_feature.rs2
-rw-r--r--tests/ui/lang-items/start_lang_item_with_target_feature.stderr4
-rw-r--r--tests/ui/layout/ice-type-error-in-tail-124031.rs (renamed from tests/crashes/124031.rs)5
-rw-r--r--tests/ui/layout/ice-type-error-in-tail-124031.stderr12
-rw-r--r--tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr5
-rw-r--r--tests/ui/lint/lint-pre-expansion-extern-module.stderr4
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-edge-cases.rs4
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr14
-rw-r--r--tests/ui/methods/fulfillment-disqualifies-method.rs32
-rw-r--r--tests/ui/methods/leak-check-disquality.rs26
-rw-r--r--tests/ui/methods/self-type-is-sup-no-eq.rs24
-rw-r--r--tests/ui/missing-trait-bounds/issue-35677.stderr2
-rw-r--r--tests/ui/nll/issue-57362-2.rs4
-rw-r--r--tests/ui/nll/issue-57362-2.stderr8
-rw-r--r--tests/ui/nll/issue-57642-higher-ranked-subtype.rs3
-rw-r--r--tests/ui/nll/issue-57642-higher-ranked-subtype.stderr8
-rw-r--r--tests/ui/panic-handler/panic-handler-with-target-feature.rs2
-rw-r--r--tests/ui/panic-handler/panic-handler-with-target-feature.stderr4
-rw-r--r--tests/ui/panic-handler/panic-handler-with-track-caller.rs14
-rw-r--r--tests/ui/panic-handler/panic-handler-with-track-caller.stderr11
-rw-r--r--tests/ui/panic-handler/panic-handler-wrong-location.rs2
-rw-r--r--tests/ui/panic-handler/panic-handler-wrong-location.stderr2
-rw-r--r--tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed15
-rw-r--r--tests/ui/parser/attribute/attr-binary-expr-ambigous.rs15
-rw-r--r--tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr46
-rw-r--r--tests/ui/parser/expr-rarrow-call.fixed33
-rw-r--r--tests/ui/parser/expr-rarrow-call.rs33
-rw-r--r--tests/ui/parser/expr-rarrow-call.stderr42
-rw-r--r--tests/ui/parser/issues/issue-118530-ice.rs3
-rw-r--r--tests/ui/parser/issues/issue-118530-ice.stderr14
-rw-r--r--tests/ui/pattern/deref-patterns/bindings.rs64
-rw-r--r--tests/ui/pattern/deref-patterns/branch.rs40
-rw-r--r--tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs24
-rw-r--r--tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr27
-rw-r--r--tests/ui/pattern/deref-patterns/closure_capture.rs21
-rw-r--r--tests/ui/pattern/deref-patterns/fake_borrows.rs14
-rw-r--r--tests/ui/pattern/deref-patterns/fake_borrows.stderr12
-rw-r--r--tests/ui/pattern/deref-patterns/typeck.rs16
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.rs17
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.stderr19
-rw-r--r--tests/ui/proc-macro/issue-81555.rs3
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs8
-rw-r--r--tests/ui/rust-2018/async-ident-allowed.stderr2
-rw-r--r--tests/ui/rust-2018/async-ident.stderr1
-rw-r--r--tests/ui/rust-2018/dyn-keyword.stderr1
-rw-r--r--tests/ui/rust-2018/try-ident.stderr2
-rw-r--r--tests/ui/rust-2018/try-macro.stderr2
-rw-r--r--tests/ui/rust-2024/gen-kw.e2015.stderr26
-rw-r--r--tests/ui/rust-2024/gen-kw.e2018.stderr26
-rw-r--r--tests/ui/rust-2024/gen-kw.rs16
-rw-r--r--tests/ui/suggestions/derive-trait-for-method-call.stderr24
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed13
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs13
-rw-r--r--tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr16
-rw-r--r--tests/ui/suggestions/issue-85347.rs6
-rw-r--r--tests/ui/suggestions/issue-85347.stderr9
-rw-r--r--tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs35
-rw-r--r--tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr78
-rw-r--r--tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr7
-rw-r--r--tests/ui/traits/track-obligations.stderr30
-rw-r--r--tests/ui/unknown-language-item.rs2
-rw-r--r--tests/ui/unknown-language-item.stderr4
327 files changed, 4269 insertions, 2139 deletions
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index ca0821e2c9e..6799513a323 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -44,7 +44,7 @@ impl Subdiagnostic for InvalidAbiReason {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         #[allow(rustc::untranslatable_diagnostic)]
         diag.note(self.0);
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index f397c949e04..25a125f8393 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -382,7 +382,7 @@ impl Subdiagnostic for EmptyLabelManySpans {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         diag.span_labels(self.0, "");
     }
@@ -751,7 +751,7 @@ impl Subdiagnostic for StableFeature {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         diag.arg("name", self.name);
         diag.arg("since", self.since);
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index a38dd286be5..af5f7571074 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -69,7 +69,8 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
     fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
         let kind = match self.kind {
             mir::BorrowKind::Shared => "",
-            mir::BorrowKind::Fake => "fake ",
+            mir::BorrowKind::Fake(mir::FakeBorrowKind::Deep) => "fake ",
+            mir::BorrowKind::Fake(mir::FakeBorrowKind::Shallow) => "fake shallow ",
             mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
             // FIXME: differentiate `TwoPhaseBorrow`
             mir::BorrowKind::Mut {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 61cd085eef5..4878da530b0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -17,9 +17,9 @@ use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
-    FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
-    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
-    VarBindingForm,
+    FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
+    Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
+    TerminatorKind, VarBindingForm,
 };
 use rustc_middle::ty::{
     self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
@@ -1486,7 +1486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let first_borrow_desc;
         let mut err = match (gen_borrow_kind, issued_borrow.kind) {
             (
-                BorrowKind::Shared,
+                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
                 BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
             ) => {
                 first_borrow_desc = "mutable ";
@@ -1504,7 +1504,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             (
                 BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
-                BorrowKind::Shared,
+                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
             ) => {
                 first_borrow_desc = "immutable ";
                 let mut err = self.cannot_reborrow_already_borrowed(
@@ -1566,7 +1566,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
             }
 
-            (BorrowKind::Mut { .. }, BorrowKind::Fake) => {
+            (BorrowKind::Mut { .. }, BorrowKind::Fake(FakeBorrowKind::Shallow)) => {
                 if let Some(immutable_section_description) =
                     self.classify_immutable_section(issued_borrow.assigned_place)
                 {
@@ -1629,7 +1629,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 )
             }
 
-            (BorrowKind::Shared, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
+            (
+                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
+                BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
+            ) => {
                 first_borrow_desc = "first ";
                 self.cannot_reborrow_already_uniquely_borrowed(
                     span,
@@ -1659,8 +1662,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 )
             }
 
-            (BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Fake)
-            | (BorrowKind::Fake, BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake) => {
+            (
+                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
+                BorrowKind::Shared | BorrowKind::Fake(_),
+            )
+            | (
+                BorrowKind::Fake(FakeBorrowKind::Shallow),
+                BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake(_),
+            ) => {
                 unreachable!()
             }
         };
@@ -3572,7 +3581,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let loan_span = loan_spans.args_or_use();
 
         let descr_place = self.describe_any_place(place.as_ref());
-        if loan.kind == BorrowKind::Fake {
+        if let BorrowKind::Fake(_) = loan.kind {
             if let Some(section) = self.classify_immutable_section(loan.assigned_place) {
                 let mut err = self.cannot_mutate_in_immutable_section(
                     span,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index a505924fabd..6224cda1b16 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -654,7 +654,7 @@ impl UseSpans<'_> {
                     match kind {
                         Some(kd) => match kd {
                             rustc_middle::mir::BorrowKind::Shared
-                            | rustc_middle::mir::BorrowKind::Fake => {
+                            | rustc_middle::mir::BorrowKind::Fake(_) => {
                                 CaptureVarKind::Immut { kind_span: capture_kind_span }
                             }
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index a69b644c4dc..60037d28f62 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1056,18 +1056,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     Control::Continue
                 }
 
-                (Read(_), BorrowKind::Shared | BorrowKind::Fake)
-                | (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => {
-                    Control::Continue
-                }
+                (Read(_), BorrowKind::Shared | BorrowKind::Fake(_))
+                | (
+                    Read(ReadKind::Borrow(BorrowKind::Fake(FakeBorrowKind::Shallow))),
+                    BorrowKind::Mut { .. },
+                ) => Control::Continue,
 
-                (Reservation(_), BorrowKind::Fake | BorrowKind::Shared) => {
+                (Reservation(_), BorrowKind::Fake(_) | BorrowKind::Shared) => {
                     // This used to be a future compatibility warning (to be
                     // disallowed on NLL). See rust-lang/rust#56254
                     Control::Continue
                 }
 
-                (Write(WriteKind::Move), BorrowKind::Fake) => {
+                (Write(WriteKind::Move), BorrowKind::Fake(FakeBorrowKind::Shallow)) => {
                     // Handled by initialization checks.
                     Control::Continue
                 }
@@ -1175,10 +1176,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         match rvalue {
             &Rvalue::Ref(_ /*rgn*/, bk, place) => {
                 let access_kind = match bk {
-                    BorrowKind::Fake => {
+                    BorrowKind::Fake(FakeBorrowKind::Shallow) => {
                         (Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk)))
                     }
-                    BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
+                    BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep) => {
+                        (Deep, Read(ReadKind::Borrow(bk)))
+                    }
                     BorrowKind::Mut { .. } => {
                         let wk = WriteKind::MutableBorrow(bk);
                         if allow_two_phase_borrow(bk) {
@@ -1197,7 +1200,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     flow_state,
                 );
 
-                let action = if bk == BorrowKind::Fake {
+                let action = if bk == BorrowKind::Fake(FakeBorrowKind::Shallow) {
                     InitializationRequiringAction::MatchOn
                 } else {
                     InitializationRequiringAction::Borrow
@@ -1557,7 +1560,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             // only mutable borrows should be 2-phase
             assert!(match borrow.kind {
-                BorrowKind::Shared | BorrowKind::Fake => false,
+                BorrowKind::Shared | BorrowKind::Fake(_) => false,
                 BorrowKind::Mut { .. } => true,
             });
 
@@ -2122,14 +2125,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 | WriteKind::Replace
                 | WriteKind::StorageDeadOrDrop
                 | WriteKind::MutableBorrow(BorrowKind::Shared)
-                | WriteKind::MutableBorrow(BorrowKind::Fake),
+                | WriteKind::MutableBorrow(BorrowKind::Fake(_)),
             )
             | Write(
                 WriteKind::Move
                 | WriteKind::Replace
                 | WriteKind::StorageDeadOrDrop
                 | WriteKind::MutableBorrow(BorrowKind::Shared)
-                | WriteKind::MutableBorrow(BorrowKind::Fake),
+                | WriteKind::MutableBorrow(BorrowKind::Fake(_)),
             ) => {
                 if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err()
                     && !self.has_buffered_diags()
@@ -2153,7 +2156,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 return false;
             }
             Read(
-                ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake)
+                ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake(_))
                 | ReadKind::Copy,
             ) => {
                 // Access authorized
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 7e8dba43b71..c559f9d5748 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -55,7 +55,7 @@ use crate::Overlap;
 use crate::{AccessDepth, Deep, Shallow};
 use rustc_hir as hir;
 use rustc_middle::mir::{
-    Body, BorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
+    Body, BorrowKind, FakeBorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
 };
 use rustc_middle::ty::{self, TyCtxt};
 use std::cmp::max;
@@ -271,10 +271,10 @@ fn place_components_conflict<'tcx>(
     // If the second example, where we did, then we still know
     // that the borrow can access a *part* of our place that
     // our access cares about, so we still have a conflict.
-    if borrow_kind == BorrowKind::Fake
+    if borrow_kind == BorrowKind::Fake(FakeBorrowKind::Shallow)
         && borrow_place.projection.len() < access_place.projection.len()
     {
-        debug!("borrow_conflicts_with_place: fake borrow");
+        debug!("borrow_conflicts_with_place: shallow borrow");
         false
     } else {
         debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
index 956de1dec9b..de469080d14 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
@@ -1,6 +1,8 @@
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue};
+use rustc_middle::mir::{
+    self, BasicBlock, Body, FakeBorrowKind, Location, NonDivergingIntrinsic, Place, Rvalue,
+};
 use rustc_middle::mir::{BorrowKind, Mutability, Operand};
 use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
 use rustc_middle::mir::{Statement, StatementKind};
@@ -239,10 +241,12 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
         match rvalue {
             &Rvalue::Ref(_ /*rgn*/, bk, place) => {
                 let access_kind = match bk {
-                    BorrowKind::Fake => {
+                    BorrowKind::Fake(FakeBorrowKind::Shallow) => {
                         (Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk)))
                     }
-                    BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
+                    BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep) => {
+                        (Deep, Read(ReadKind::Borrow(bk)))
+                    }
                     BorrowKind::Mut { .. } => {
                         let wk = WriteKind::MutableBorrow(bk);
                         if allow_two_phase_borrow(bk) {
@@ -357,8 +361,11 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
                         // have already taken the reservation
                     }
 
-                    (Read(_), BorrowKind::Fake | BorrowKind::Shared)
-                    | (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => {
+                    (Read(_), BorrowKind::Fake(_) | BorrowKind::Shared)
+                    | (
+                        Read(ReadKind::Borrow(BorrowKind::Fake(FakeBorrowKind::Shallow))),
+                        BorrowKind::Mut { .. },
+                    ) => {
                         // Reads don't invalidate shared or shallow borrows
                     }
 
@@ -403,7 +410,7 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
 
             // only mutable borrows should be 2-phase
             assert!(match borrow.kind {
-                BorrowKind::Shared | BorrowKind::Fake => false,
+                BorrowKind::Shared | BorrowKind::Fake(_) => false,
                 BorrowKind::Mut { .. } => true,
             });
 
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 6b6647ef085..9078dc07a31 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -601,7 +601,7 @@ impl Subdiagnostic for FormatUnusedArg {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         diag.arg("named", self.named);
         let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index 8fdc1941de8..33fe52ddbdd 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "ahash"
-version = "0.8.7"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -16,9 +16,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.75"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
+checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
 
 [[package]]
 name = "arbitrary"
@@ -34,9 +34,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bumpalo"
-version = "3.14.0"
+version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "cfg-if"
@@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a535eb1cf5a6003197dc569320c40c1cb2d2f97ef5d5348eebf067f20957381"
+checksum = "79b27922a6879b5b5361d0a084cb0b1941bf109a98540addcb932da13b68bed4"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11b5066db32cec1492573827183af2142d2d88fe85a83cfc9e73f0f63d3788d4"
+checksum = "304c455b28bf56372729acb356afbb55d622f2b0f2f7837aa5e57c138acaac4d"
 dependencies = [
  "bumpalo",
  "cranelift-bforest",
@@ -67,7 +67,7 @@ dependencies = [
  "cranelift-entity",
  "cranelift-isle",
  "gimli",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.3",
  "log",
  "regalloc2",
  "smallvec",
@@ -76,39 +76,39 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64942e5774308e835fbad4dd25f253105412c90324631910e1ec27963147bddb"
+checksum = "1653c56b99591d07f67c5ca7f9f25888948af3f4b97186bff838d687d666f613"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c39c33db9a86dd6d8d04166a10c53deb477aeea3500eaaefca682e4eda9bb986"
+checksum = "f5b6a9cf6b6eb820ee3f973a0db313c05dc12d370f37b4fe9630286e1672573f"
 
 [[package]]
 name = "cranelift-control"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b7fc4937613aea3156a0538800a17bf56f345a5da2e79ae3df58488c93d867f"
+checksum = "d9d06e6bf30075fb6bed9e034ec046475093392eea1aff90eb5c44c4a033d19a"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f85575e79a153ce1ddbfb7fe1813519b4bfe1eb200cc9c8353b45ad123ae4d36"
+checksum = "29be04f931b73cdb9694874a295027471817f26f26d2f0ebe5454153176b6e3a"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbc31d6c0ab2249fe0c21e988256b42f5f401ab2673b4fc40076c82a698bdfb9"
+checksum = "a07fd7393041d7faa2f37426f5dc7fc04003b70988810e8c063beefeff1cd8f9"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -118,15 +118,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc14f37e3314c0e4c53779c2f46753bf242efff76ee9473757a1fff3b495ad37"
+checksum = "f341d7938caa6dff8149dac05bb2b53fc680323826b83b4cf175ab9f5139a3c9"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfdd1942f3233176a68c285380dbc84ff0440246a1bce308611c0a385b56ab18"
+checksum = "42733555e06433f1461570e09dbd756dafc228b4dac75c597cdbdc518de07522"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -139,14 +139,14 @@ dependencies = [
  "region",
  "target-lexicon",
  "wasmtime-jit-icache-coherence",
- "windows-sys 0.52.0",
+ "windows-sys",
 ]
 
 [[package]]
 name = "cranelift-module"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "121b2b5a16912554a1b9aace75b9b21eca49f28e33cbfbad4786dd9bc5361a5c"
+checksum = "84950af02bb85f3da764d53a953b43bb29a732e793d4fe24637a61591be9a024"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -155,9 +155,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ea5375f76ab31f9800a23fb2b440810286a6f669a3eb467cdd7ff255ea64268"
+checksum = "82af6066e6448d26eeabb7aa26a43f7ff79f8217b06bade4ee6ef230aecc8880"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -166,9 +166,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.106.0"
+version = "0.107.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f34e04419ab41661e973d90a73aa7b12771455394dae7a69b101a9b7e7589db7"
+checksum = "00af56107039ed150391df6f753298c7b08f2b6a2e0727d216b5fa599d684d8b"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -181,9 +181,9 @@ dependencies = [
 
 [[package]]
 name = "crc32fast"
-version = "1.3.2"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
 dependencies = [
  "cfg-if",
 ]
@@ -222,21 +222,21 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.14.0"
+version = "0.14.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 dependencies = [
  "ahash",
 ]
 
 [[package]]
 name = "indexmap"
-version = "2.0.0"
+version = "2.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
 dependencies = [
  "equivalent",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.3",
 ]
 
 [[package]]
@@ -247,19 +247,19 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "libloading"
-version = "0.8.1"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
+checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
 dependencies = [
  "cfg-if",
- "windows-sys 0.48.0",
+ "windows-targets",
 ]
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 
 [[package]]
 name = "mach"
@@ -272,42 +272,42 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.6.3"
+version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
 
 [[package]]
 name = "object"
-version = "0.32.0"
+version = "0.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
+checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
 dependencies = [
  "crc32fast",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.3",
  "indexmap",
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.75"
+version = "1.0.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
@@ -369,9 +369,9 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
 
 [[package]]
 name = "smallvec"
-version = "1.11.0"
+version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "stable_deref_trait"
@@ -381,9 +381,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "syn"
-version = "2.0.47"
+version = "2.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -410,13 +410,13 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "19.0.0"
+version = "20.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2796e4b4989db62899d2117e1e0258b839d088c044591b14e3a0396e7b3ae53a"
+checksum = "7a9f93a3289057b26dc75eb84d6e60d7694f7d169c7c09597495de6e016a13ff"
 dependencies = [
  "cfg-if",
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -443,135 +443,76 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.0",
+ "windows-targets",
 ]
 
 [[package]]
 name = "windows-targets"
-version = "0.48.5"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
 [[package]]
-name = "windows-targets"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
-dependencies = [
- "windows_aarch64_gnullvm 0.52.0",
- "windows_aarch64_msvc 0.52.0",
- "windows_i686_gnu 0.52.0",
- "windows_i686_msvc 0.52.0",
- "windows_x86_64_gnu 0.52.0",
- "windows_x86_64_gnullvm 0.52.0",
- "windows_x86_64_msvc 0.52.0",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
 
 [[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
+name = "windows_i686_gnullvm"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.48.5"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.0"
+version = "0.52.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
 
 [[package]]
 name = "zerocopy"
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index d8a855b0383..2015cdbcc2a 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,15 +8,15 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.106.0", default-features = false, features = ["std", "unwind", "all-arch"] }
-cranelift-frontend = { version = "0.106.0" }
-cranelift-module = { version = "0.106.0" }
-cranelift-native = { version = "0.106.0" }
-cranelift-jit = { version = "0.106.0", optional = true }
-cranelift-object = { version = "0.106.0" }
+cranelift-codegen = { version = "0.107.0", default-features = false, features = ["std", "unwind", "all-arch"] }
+cranelift-frontend = { version = "0.107.0" }
+cranelift-module = { version = "0.107.0" }
+cranelift-native = { version = "0.107.0" }
+cranelift-jit = { version = "0.107.0", optional = true }
+cranelift-object = { version = "0.107.0" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.28", default-features = false, features = ["write"]}
-object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
+object = { version = "0.33", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
 
 indexmap = "2.0.0"
 libloading = { version = "0.8.0", optional = true }
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
index 2e7ba1b2060..ecf303c30b6 100644
--- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -43,7 +43,13 @@ pub(crate) fn run(
     let mut cmd = ABI_CAFE.run(bootstrap_host_compiler, dirs);
     cmd.arg("--");
     cmd.arg("--pairs");
-    cmd.args(pairs);
+    cmd.args(
+        if cfg!(not(any(target_os = "macos", all(target_os = "windows", target_env = "msvc")))) {
+            &pairs[..]
+        } else {
+            &pairs[..2]
+        },
+    );
     cmd.arg("--add-rustc-codegen-backend");
     match cg_clif_dylib {
         CodegenBackend::Local(path) => {
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index 9efb6ed715c..76104901474 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -290,7 +290,7 @@ pub(crate) fn run_tests(
         && !skip_tests.contains(&"testsuite.extended_sysroot");
 
     if run_base_sysroot || run_extended_sysroot {
-        let mut target_compiler = build_sysroot::build_sysroot(
+        let target_compiler = build_sysroot::build_sysroot(
             dirs,
             channel,
             sysroot_kind,
@@ -299,11 +299,8 @@ pub(crate) fn run_tests(
             rustup_toolchain_name,
             target_triple.clone(),
         );
-        // Rust's build system denies a couple of lints that trigger on several of the test
-        // projects. Changing the code to fix them is not worth it, so just silence all lints.
-        target_compiler.rustflags.push("--cap-lints=allow".to_owned());
 
-        let runner = TestRunner::new(
+        let mut runner = TestRunner::new(
             dirs.clone(),
             target_compiler,
             use_unstable_features,
@@ -319,6 +316,9 @@ pub(crate) fn run_tests(
         }
 
         if run_extended_sysroot {
+            // Rust's build system denies a couple of lints that trigger on several of the test
+            // projects. Changing the code to fix them is not worth it, so just silence all lints.
+            runner.target_compiler.rustflags.push("--cap-lints=allow".to_owned());
             runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
         } else {
             eprintln!("[SKIP] extended_sysroot tests");
diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
index 117eed5afd8..da70ca79439 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
@@ -1,4 +1,5 @@
 #![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
+#![allow(internal_features)]
 #![no_std]
 
 extern crate alloc;
diff --git a/compiler/rustc_codegen_cranelift/example/alloc_system.rs b/compiler/rustc_codegen_cranelift/example/alloc_system.rs
index e64daf96b01..441f3cd2987 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_system.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_system.rs
@@ -80,7 +80,6 @@ mod platform {
     extern "system" {
         fn GetProcessHeap() -> HANDLE;
         fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
-        fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
         fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
         fn GetLastError() -> DWORD;
     }
@@ -111,7 +110,7 @@ mod platform {
             allocate_with_flags(layout, HEAP_ZERO_MEMORY)
         }
         #[inline]
-        unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
             let header = get_header(ptr);
             let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
             debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError());
diff --git a/compiler/rustc_codegen_cranelift/example/example.rs b/compiler/rustc_codegen_cranelift/example/example.rs
index 885e55bc764..1ef2aa5dd8e 100644
--- a/compiler/rustc_codegen_cranelift/example/example.rs
+++ b/compiler/rustc_codegen_cranelift/example/example.rs
@@ -149,7 +149,7 @@ pub fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
     arr
 }
 
-pub unsafe fn use_ctlz_nonzero(a: u16) -> u16 {
+pub unsafe fn use_ctlz_nonzero(a: u16) -> u32 {
     intrinsics::ctlz_nonzero(a)
 }
 
diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
index a71217a554b..c54574d801d 100644
--- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
+++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
@@ -5,7 +5,7 @@
 // Test that the simd_f{min,max} intrinsics produce the correct results.
 
 #![feature(repr_simd, core_intrinsics)]
-#![allow(non_camel_case_types)]
+#![allow(internal_features, non_camel_case_types)]
 
 #[repr(simd)]
 #[derive(Copy, Clone, PartialEq, Debug)]
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index e45c16ee280..5e535ff62e1 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -627,7 +627,7 @@ pub mod intrinsics {
         pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
         pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
         pub fn transmute<T, U>(e: T) -> U;
-        pub fn ctlz_nonzero<T>(x: T) -> T;
+        pub fn ctlz_nonzero<T>(x: T) -> u32;
         #[rustc_safe_intrinsic]
         pub fn needs_drop<T: ?::Sized>() -> bool;
         #[rustc_safe_intrinsic]
diff --git a/compiler/rustc_codegen_cranelift/example/mod_bench.rs b/compiler/rustc_codegen_cranelift/example/mod_bench.rs
index f15e48acc41..11a3e8fc72d 100644
--- a/compiler/rustc_codegen_cranelift/example/mod_bench.rs
+++ b/compiler/rustc_codegen_cranelift/example/mod_bench.rs
@@ -1,4 +1,5 @@
 #![feature(start, core_intrinsics, lang_items)]
+#![allow(internal_features)]
 #![no_std]
 
 #[cfg_attr(unix, link(name = "c"))]
diff --git a/compiler/rustc_codegen_cranelift/example/neon.rs b/compiler/rustc_codegen_cranelift/example/neon.rs
index bad26947967..00e437d7e54 100644
--- a/compiler/rustc_codegen_cranelift/example/neon.rs
+++ b/compiler/rustc_codegen_cranelift/example/neon.rs
@@ -4,7 +4,9 @@
 
 #[cfg(target_arch = "aarch64")]
 use std::arch::aarch64::*;
+#[cfg(target_arch = "aarch64")]
 use std::mem::transmute;
+#[cfg(target_arch = "aarch64")]
 use std::simd::*;
 
 #[cfg(target_arch = "aarch64")]
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 2fee912e52c..0205de55622 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -7,6 +7,7 @@
     tuple_trait,
     unboxed_closures
 )]
+#![allow(internal_features)]
 
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
index 0e5e7cdfcdf..77716c51399 100644
--- a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
@@ -11,7 +11,7 @@ diff --git a/src/report.rs b/src/report.rs
 index eeec614..f582867 100644
 --- a/src/report.rs
 +++ b/src/report.rs
-@@ -48,6 +48,12 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
+@@ -48,6 +48,15 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
      //
      // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
  
@@ -19,6 +19,9 @@ index eeec614..f582867 100644
 +    if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" {
 +        result.run = Link;
 +        result.check = Pass(Link);
++    } else if test.test_name == "ui128" {
++        result.run == Check;
++        result.check = Pass(Check);
 +    }
 +
      // END OF VENDOR RESERVED AREA
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index 3e7da4e161f..de340cf8c35 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-04-11"
+channel = "nightly-2024-04-23"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 6363a0d59a4..6f346af25c6 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -7,11 +7,13 @@ mod returning;
 use std::borrow::Cow;
 
 use cranelift_codegen::ir::SigRef;
+use cranelift_codegen::isa::CallConv;
 use cranelift_module::ModuleError;
 use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index f428c4c7c0d..e3d050df4cd 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -2,12 +2,14 @@
 
 use cranelift_codegen::ir::UserFuncName;
 use cranelift_codegen::CodegenError;
+use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use cranelift_module::ModuleError;
 use rustc_ast::InlineAsmOptions;
 use rustc_index::IndexVec;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
 
 use crate::constant::ConstantCx;
@@ -823,7 +825,13 @@ fn codegen_stmt<'tcx>(
                     };
                     let data = codegen_operand(fx, data);
                     let meta = codegen_operand(fx, meta);
-                    let ptr_val = CValue::pointer_from_data_and_meta(data, meta, layout);
+                    assert!(data.layout().ty.is_unsafe_ptr());
+                    assert!(layout.ty.is_unsafe_ptr());
+                    let ptr_val = if meta.layout().is_zst() {
+                        data.cast_pointer_to(layout)
+                    } else {
+                        CValue::by_val_pair(data.load_scalar(fx), meta.load_scalar(fx), layout)
+                    };
                     lval.write_cvalue(fx, ptr_val);
                 }
                 Rvalue::Aggregate(ref kind, ref operands) => {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index cf0b065414d..2a24d6150bd 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -1,8 +1,10 @@
 use cranelift_codegen::isa::TargetFrontendConfig;
+use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use rustc_index::IndexVec;
 use rustc_middle::ty::layout::{
-    FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
+    self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
 };
+use rustc_middle::ty::TypeFoldable;
 use rustc_span::source_map::Spanned;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index cb05c17ec2a..cdf499a22f8 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -137,18 +137,23 @@ pub(crate) fn codegen_const_value<'tcx>(
                 let alloc_id = prov.alloc_id();
                 let base_addr = match fx.tcx.global_alloc(alloc_id) {
                     GlobalAlloc::Memory(alloc) => {
-                        let data_id = data_id_for_alloc_id(
-                            &mut fx.constants_cx,
-                            fx.module,
-                            alloc_id,
-                            alloc.inner().mutability,
-                        );
-                        let local_data_id =
-                            fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
-                        if fx.clif_comments.enabled() {
-                            fx.add_comment(local_data_id, format!("{:?}", alloc_id));
+                        if alloc.inner().len() == 0 {
+                            assert_eq!(offset, Size::ZERO);
+                            fx.bcx.ins().iconst(fx.pointer_type, alloc.inner().align.bytes() as i64)
+                        } else {
+                            let data_id = data_id_for_alloc_id(
+                                &mut fx.constants_cx,
+                                fx.module,
+                                alloc_id,
+                                alloc.inner().mutability,
+                            );
+                            let local_data_id =
+                                fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+                            if fx.clif_comments.enabled() {
+                                fx.add_comment(local_data_id, format!("{:?}", alloc_id));
+                            }
+                            fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
                         }
-                        fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
                     }
                     GlobalAlloc::Function(instance) => {
                         let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index 5d943b5d996..f0b78e5d7c6 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -19,7 +19,7 @@ use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefIdMap;
 use rustc_session::Session;
-use rustc_span::{SourceFileHash, StableSourceFileId};
+use rustc_span::{FileNameDisplayPreference, SourceFileHash, StableSourceFileId};
 use rustc_target::abi::call::FnAbi;
 
 pub(crate) use self::emit::{DebugReloc, DebugRelocName};
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
index 27eabd8a0a6..65f4c67b21f 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
@@ -2,7 +2,7 @@ use cranelift_module::{DataId, FuncId};
 use cranelift_object::ObjectProduct;
 use gimli::SectionId;
 use object::write::{Relocation, StandardSegment};
-use object::{RelocationEncoding, SectionKind};
+use object::{RelocationEncoding, RelocationFlags, SectionKind};
 use rustc_data_structures::fx::FxHashMap;
 
 use crate::debuginfo::{DebugReloc, DebugRelocName};
@@ -72,9 +72,11 @@ impl WriteDebugInfo for ObjectProduct {
                 Relocation {
                     offset: u64::from(reloc.offset),
                     symbol,
-                    kind: reloc.kind,
-                    encoding: RelocationEncoding::Generic,
-                    size: reloc.size * 8,
+                    flags: RelocationFlags::Generic {
+                        kind: reloc.kind,
+                        encoding: RelocationEncoding::Generic,
+                        size: reloc.size * 8,
+                    },
                     addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
                 },
             )
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 6dbc3f19127..929fa92596d 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -6,6 +6,7 @@ use std::ffi::CString;
 use std::os::raw::{c_char, c_int};
 use std::sync::{mpsc, Mutex, OnceLock};
 
+use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use cranelift_jit::{JITBuilder, JITModule};
 use rustc_codegen_ssa::CrateInfo;
 use rustc_middle::mir::mono::MonoItem;
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 171ee88a11c..28b92f730da 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -2,6 +2,7 @@
 
 use std::fmt::Write;
 
+use cranelift_codegen::isa::CallConv;
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_span::sym;
 use rustc_target::asm::*;
@@ -785,9 +786,9 @@ fn call_inline_asm<'tcx>(
     for (offset, place) in outputs {
         let ty = if place.layout().ty.is_simd() {
             let (lane_count, lane_type) = place.layout().ty.simd_size_and_type(fx.tcx);
-            fx.clif_type(lane_type).unwrap().by(lane_count.try_into().unwrap()).unwrap()
+            asm_clif_type(fx, lane_type).unwrap().by(lane_count.try_into().unwrap()).unwrap()
         } else {
-            fx.clif_type(place.layout().ty).unwrap()
+            asm_clif_type(fx, place.layout().ty).unwrap()
         };
         let value = stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).load(
             fx,
@@ -797,3 +798,24 @@ fn call_inline_asm<'tcx>(
         place.write_cvalue(fx, CValue::by_val(value, place.layout()));
     }
 }
+
+fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<types::Type> {
+    match ty.kind() {
+        // Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
+        ty::Adt(adt, args) if Some(adt.did()) == fx.tcx.lang_items().maybe_uninit() => {
+            let fields = &adt.non_enum_variant().fields;
+            let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
+            let ty::Adt(ty, args) = ty.kind() else {
+                unreachable!("expected first field of `MaybeUninit` to be an ADT")
+            };
+            assert!(
+                ty.is_manually_drop(),
+                "expected first field of `MaybeUninit` to be `ManuallyDrop`"
+            );
+            let fields = &ty.non_enum_variant().fields;
+            let ty = fields[FieldIdx::ZERO].ty(fx.tcx, args);
+            fx.clif_type(ty)
+        }
+        _ => fx.clif_type(ty),
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 0b213ff8269..79a90507fa2 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -26,6 +26,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
 
 pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
+use crate::cast::clif_intcast;
 use crate::prelude::*;
 
 fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! {
@@ -627,7 +628,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             // FIXME trap on `ctlz_nonzero` with zero arg.
             let res = fx.bcx.ins().clz(val);
-            let res = CValue::by_val(res, arg.layout());
+            let res = clif_intcast(fx, res, types::I32, false);
+            let res = CValue::by_val(res, ret.layout());
             ret.write_cvalue(fx, res);
         }
         sym::cttz | sym::cttz_nonzero => {
@@ -636,7 +638,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             // FIXME trap on `cttz_nonzero` with zero arg.
             let res = fx.bcx.ins().ctz(val);
-            let res = CValue::by_val(res, arg.layout());
+            let res = clif_intcast(fx, res, types::I32, false);
+            let res = CValue::by_val(res, ret.layout());
             ret.write_cvalue(fx, res);
         }
         sym::ctpop => {
@@ -644,7 +647,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let val = arg.load_scalar(fx);
 
             let res = fx.bcx.ins().popcnt(val);
-            let res = CValue::by_val(res, arg.layout());
+            let res = clif_intcast(fx, res, types::I32, false);
+            let res = CValue::by_val(res, ret.layout());
             ret.write_cvalue(fx, res);
         }
         sym::bitreverse => {
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index d0ab64a5584..c9f84b69997 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -87,21 +87,17 @@ mod prelude {
         AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot,
         StackSlotData, StackSlotKind, TrapCode, Type, Value,
     };
-    pub(crate) use cranelift_codegen::isa::{self, CallConv};
     pub(crate) use cranelift_codegen::Context;
-    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
     pub(crate) use cranelift_module::{self, DataDescription, FuncId, Linkage, Module};
     pub(crate) use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
     pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
     pub(crate) use rustc_index::Idx;
-    pub(crate) use rustc_middle::bug;
     pub(crate) use rustc_middle::mir::{self, *};
-    pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
+    pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
     pub(crate) use rustc_middle::ty::{
-        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
-        TypeFoldable, TypeVisitableExt, UintTy,
+        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, UintTy,
     };
-    pub(crate) use rustc_span::{FileNameDisplayPreference, Span};
+    pub(crate) use rustc_span::Span;
     pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT};
 
     pub(crate) use crate::abi::*;
@@ -261,7 +257,7 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple {
     }
 }
 
-fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn isa::TargetIsa + 'static> {
+fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIsa + 'static> {
     use target_lexicon::BinaryFormat;
 
     let target_triple = crate::target_triple(sess);
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 1abfded8b11..1f20ec42ddb 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -1,3 +1,4 @@
+use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use rustc_hir::LangItem;
 use rustc_middle::ty::AssocKind;
 use rustc_middle::ty::GenericArg;
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 8d52fd9d7a8..dded6df7771 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -2,6 +2,7 @@
 
 use cranelift_codegen::entity::EntityRef;
 use cranelift_codegen::ir::immediates::Offset32;
+use cranelift_frontend::Variable;
 use rustc_middle::ty::FnSig;
 
 use crate::prelude::*;
@@ -94,23 +95,6 @@ impl<'tcx> CValue<'tcx> {
         CValue(CValueInner::ByValPair(value, extra), layout)
     }
 
-    /// For `AggregateKind::RawPtr`, create a pointer from its parts.
-    ///
-    /// Panics if the `layout` is not a raw pointer.
-    pub(crate) fn pointer_from_data_and_meta(
-        data: CValue<'tcx>,
-        meta: CValue<'tcx>,
-        layout: TyAndLayout<'tcx>,
-    ) -> CValue<'tcx> {
-        assert!(layout.ty.is_unsafe_ptr());
-        let inner = match (data.0, meta.0) {
-            (CValueInner::ByVal(p), CValueInner::ByVal(m)) => CValueInner::ByValPair(p, m),
-            (p @ CValueInner::ByVal(_), CValueInner::ByRef(..)) if meta.1.is_zst() => p,
-            _ => bug!("RawPtr operands {data:?} {meta:?}"),
-        };
-        CValue(inner, layout)
-    }
-
     pub(crate) fn layout(&self) -> TyAndLayout<'tcx> {
         self.1
     }
diff --git a/compiler/rustc_codegen_gcc/example/example.rs b/compiler/rustc_codegen_gcc/example/example.rs
index 5878e8548d9..7c21b73b630 100644
--- a/compiler/rustc_codegen_gcc/example/example.rs
+++ b/compiler/rustc_codegen_gcc/example/example.rs
@@ -153,9 +153,10 @@ fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
     arr
 }
 
-unsafe fn use_ctlz_nonzero(a: u16) -> u16 {
-    intrinsics::ctlz_nonzero(a)
-}
+// FIXME: fix the intrinsic implementation to work with the new ->u32 signature
+// unsafe fn use_ctlz_nonzero(a: u16) -> u32 {
+//     intrinsics::ctlz_nonzero(a)
+// }
 
 fn ptr_as_usize(ptr: *const u8) -> usize {
     ptr as usize
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 4665009e191..8ffa66a4894 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -593,7 +593,7 @@ pub mod intrinsics {
         pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize;
         pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
         pub fn transmute<T, U>(e: T) -> U;
-        pub fn ctlz_nonzero<T>(x: T) -> T;
+        pub fn ctlz_nonzero<T>(x: T) -> u32;
         #[rustc_safe_intrinsic]
         pub fn needs_drop<T: ?Sized>() -> bool;
         #[rustc_safe_intrinsic]
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 2bed7c1bd1c..ab9f20fdf63 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -315,25 +315,32 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                     Some((width, signed)) => match name {
                         sym::ctlz | sym::cttz => {
                             let y = self.const_bool(false);
-                            self.call_intrinsic(
+                            let ret = self.call_intrinsic(
                                 &format!("llvm.{name}.i{width}"),
                                 &[args[0].immediate(), y],
-                            )
+                            );
+
+                            self.intcast(ret, llret_ty, false)
                         }
                         sym::ctlz_nonzero => {
                             let y = self.const_bool(true);
                             let llvm_name = &format!("llvm.ctlz.i{width}");
-                            self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
+                            let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
+                            self.intcast(ret, llret_ty, false)
                         }
                         sym::cttz_nonzero => {
                             let y = self.const_bool(true);
                             let llvm_name = &format!("llvm.cttz.i{width}");
-                            self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
+                            let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
+                            self.intcast(ret, llret_ty, false)
+                        }
+                        sym::ctpop => {
+                            let ret = self.call_intrinsic(
+                                &format!("llvm.ctpop.i{width}"),
+                                &[args[0].immediate()],
+                            );
+                            self.intcast(ret, llret_ty, false)
                         }
-                        sym::ctpop => self.call_intrinsic(
-                            &format!("llvm.ctpop.i{width}"),
-                            &[args[0].immediate()],
-                        ),
                         sym::bswap => {
                             if width == 8 {
                                 args[0].immediate() // byte swap a u8/i8 is just a no-op
@@ -355,6 +362,10 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                             // rotate = funnel shift with first two args the same
                             let llvm_name =
                                 &format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);
+
+                            // llvm expects shift to be the same type as the values, but rust always uses `u32`
+                            let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
+
                             self.call_intrinsic(llvm_name, &[val, val, raw_shift])
                         }
                         sym::saturating_add | sym::saturating_sub => {
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index f6937dc145d..b79d7441aca 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -82,12 +82,6 @@ const_eval_double_storage_live =
 const_eval_dyn_call_not_a_method =
     `dyn` call trying to call something that is not a method
 
-const_eval_dyn_call_vtable_mismatch =
-    `dyn` call on a pointer whose vtable does not match its type
-
-const_eval_dyn_star_call_vtable_mismatch =
-    `dyn*` call on a pointer whose vtable does not match its type
-
 const_eval_error = {$error_kind ->
     [static] could not evaluate static initializer
     [const] evaluation of constant value failed
@@ -192,6 +186,8 @@ const_eval_invalid_uninit_bytes_unknown =
 const_eval_invalid_vtable_pointer =
     using {$pointer} as vtable pointer but it does not point to a vtable
 
+const_eval_invalid_vtable_trait =
+    using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected
 
 const_eval_live_drop =
     destructor of `{$dropped_ty}` cannot be evaluated at compile-time
@@ -401,9 +397,6 @@ const_eval_unterminated_c_string =
 const_eval_unwind_past_top =
     unwinding past the topmost frame of the stack
 
-const_eval_upcast_mismatch =
-    upcast on a pointer whose vtable does not match its type
-
 ## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
 ## (We'd love to sort this differently to make that more clear but tidy won't let us...)
 const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
@@ -450,6 +443,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
 const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
 const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
 const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
+const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$ref_trait}`, but encountered `{$vtable_trait}`
 const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
 const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
 const_eval_validation_null_box = {$front_matter}: encountered a null box
diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
index ba2e2a1e353..7b6828c6e18 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -46,6 +46,9 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
     type MemoryKind = !;
     const PANIC_ON_ALLOC_FAIL: bool = true;
 
+    // We want to just eval random consts in the program, so `eval_mir_const` can fail.
+    const ALL_CONSTS_ARE_PRECHECKED: bool = false;
+
     #[inline(always)]
     fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         false // no reason to enforce alignment
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index a60cedd6500..90d4f1168e4 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -498,6 +498,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
             InvalidTag(_) => const_eval_invalid_tag,
             InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
             InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
+            InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
             InvalidStr(_) => const_eval_invalid_str,
             InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
             InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
@@ -537,6 +538,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
             | DeadLocal
             | UninhabitedEnumVariantWritten(_)
             | UninhabitedEnumVariantRead(_) => {}
+
             BoundsCheckFailed { len, index } => {
                 diag.arg("len", len);
                 diag.arg("index", index);
@@ -544,6 +546,13 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
             UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
                 diag.arg("pointer", ptr);
             }
+            InvalidVTableTrait { expected_trait, vtable_trait } => {
+                diag.arg("expected_trait", expected_trait.to_string());
+                diag.arg(
+                    "vtable_trait",
+                    vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
+                );
+            }
             PointerUseAfterFree(alloc_id, msg) => {
                 diag.arg("alloc_id", alloc_id)
                     .arg("bad_pointer_message", bad_pointer_message(msg, dcx));
@@ -634,6 +643,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
             UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
             Uninit { .. } => const_eval_validation_uninit,
             InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
+            InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
             InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
                 const_eval_validation_invalid_box_slice_meta
             }
@@ -773,6 +783,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
             DanglingPtrNoProvenance { pointer, .. } => {
                 err.arg("pointer", pointer);
             }
+            InvalidMetaWrongTrait { expected_trait: ref_trait, vtable_trait } => {
+                err.arg("ref_trait", ref_trait.to_string());
+                err.arg(
+                    "vtable_trait",
+                    vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
+                );
+            }
             NullPtr { .. }
             | PtrToStatic { .. }
             | ConstRefToMutable
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 9447d18fe8c..76e59ea9055 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -393,6 +393,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let val = self.read_immediate(src)?;
                 if data_a.principal() == data_b.principal() {
                     // A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
+                    // (But currently mismatching vtables violate the validity invariant so UB is triggered anyway.)
                     return self.write_immediate(*val, dest);
                 }
                 let (old_data, old_vptr) = val.to_scalar_pair();
@@ -400,7 +401,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let old_vptr = old_vptr.to_pointer(self)?;
                 let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
                 if old_trait != data_a.principal() {
-                    throw_ub_custom!(fluent::const_eval_upcast_mismatch);
+                    throw_ub!(InvalidVTableTrait {
+                        expected_trait: data_a,
+                        vtable_trait: old_trait,
+                    });
                 }
                 let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
                 self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 62d169db628..126d64329f8 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -822,15 +822,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         self.stack_mut().push(frame);
 
         // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
-        if M::POST_MONO_CHECKS {
-            for &const_ in &body.required_consts {
-                let c = self
-                    .instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
-                c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
-                    err.emit_note(*self.tcx);
-                    err
-                })?;
-            }
+        for &const_ in &body.required_consts {
+            let c =
+                self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
+            c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
+                err.emit_note(*self.tcx);
+                err
+            })?;
         }
 
         // done
@@ -1181,8 +1179,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
         M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
             let const_val = val.eval(*ecx.tcx, ecx.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`?
+                if M::ALL_CONSTS_ARE_PRECHECKED && !matches!(err, ErrorHandled::TooGeneric(..)) {
+                    // Looks like the const is not captued by `required_consts`, that's bad.
+                    bug!("interpret const eval failure of {val:?} which is not in required_consts");
+                }
                 err.emit_note(*ecx.tcx);
                 err
             })?;
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 63c709d8aed..4d37c3c22cd 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -173,7 +173,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ty = instance_args.type_at(0);
                 let layout = self.layout_of(ty)?;
                 let val = self.read_scalar(&args[0])?;
-                let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?;
+
+                let out_val = self.numeric_intrinsic(intrinsic_name, val, layout, dest.layout)?;
                 self.write_scalar(out_val, dest)?;
             }
             sym::saturating_add | sym::saturating_sub => {
@@ -200,12 +201,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::rotate_left | sym::rotate_right => {
                 // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
-                let layout = self.layout_of(instance_args.type_at(0))?;
+                let layout_val = self.layout_of(instance_args.type_at(0))?;
                 let val = self.read_scalar(&args[0])?;
-                let val_bits = val.to_bits(layout.size)?;
+                let val_bits = val.to_bits(layout_val.size)?;
+
+                let layout_raw_shift = self.layout_of(self.tcx.types.u32)?;
                 let raw_shift = self.read_scalar(&args[1])?;
-                let raw_shift_bits = raw_shift.to_bits(layout.size)?;
-                let width_bits = u128::from(layout.size.bits());
+                let raw_shift_bits = raw_shift.to_bits(layout_raw_shift.size)?;
+
+                let width_bits = u128::from(layout_val.size.bits());
                 let shift_bits = raw_shift_bits % width_bits;
                 let inv_shift_bits = (width_bits - shift_bits) % width_bits;
                 let result_bits = if intrinsic_name == sym::rotate_left {
@@ -213,8 +217,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 } else {
                     (val_bits >> shift_bits) | (val_bits << inv_shift_bits)
                 };
-                let truncated_bits = self.truncate(result_bits, layout);
-                let result = Scalar::from_uint(truncated_bits, layout.size);
+                let truncated_bits = self.truncate(result_bits, layout_val);
+                let result = Scalar::from_uint(truncated_bits, layout_val.size);
                 self.write_scalar(result, dest)?;
             }
             sym::copy => {
@@ -472,6 +476,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         name: Symbol,
         val: Scalar<M::Provenance>,
         layout: TyAndLayout<'tcx>,
+        ret_layout: TyAndLayout<'tcx>,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
         assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
         let bits = val.to_bits(layout.size)?;
@@ -483,11 +488,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra,
             sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra,
-            sym::bswap => (bits << extra).swap_bytes(),
-            sym::bitreverse => (bits << extra).reverse_bits(),
+            sym::bswap => {
+                assert_eq!(layout, ret_layout);
+                (bits << extra).swap_bytes()
+            }
+            sym::bitreverse => {
+                assert_eq!(layout, ret_layout);
+                (bits << extra).reverse_bits()
+            }
             _ => bug!("not a numeric intrinsic: {}", name),
         };
-        Ok(Scalar::from_uint(bits_out, layout.size))
+        Ok(Scalar::from_uint(bits_out, ret_layout.size))
     }
 
     pub fn exact_div(
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 7617cb57b3c..8bc569bed54 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -140,8 +140,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
     /// Should the machine panic on allocation failures?
     const PANIC_ON_ALLOC_FAIL: bool;
 
-    /// Should post-monomorphization checks be run when a stack frame is pushed?
-    const POST_MONO_CHECKS: bool = true;
+    /// Determines whether `eval_mir_constant` can never fail because all required consts have
+    /// already been checked before.
+    const ALL_CONSTS_ARE_PRECHECKED: bool = true;
 
     /// Whether memory accesses should be alignment-checked.
     fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 8364a5a8d18..e5241f1ba19 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -1020,16 +1020,20 @@ where
     pub(super) fn unpack_dyn_trait(
         &self,
         mplace: &MPlaceTy<'tcx, M::Provenance>,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
     ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
         assert!(
             matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
             "`unpack_dyn_trait` only makes sense on `dyn*` types"
         );
         let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
-        let (ty, _) = self.get_ptr_vtable(vtable)?;
-        let layout = self.layout_of(ty)?;
+        let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
+        if expected_trait.principal() != vtable_trait {
+            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
+        }
         // This is a kind of transmute, from a place with unsized type and metadata to
         // a place with sized type and no metadata.
+        let layout = self.layout_of(ty)?;
         let mplace =
             MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..mplace.mplace }, layout };
         Ok((mplace, vtable))
@@ -1040,6 +1044,7 @@ where
     pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
         &self,
         val: &P,
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
     ) -> InterpResult<'tcx, (P, Pointer<Option<M::Provenance>>)> {
         assert!(
             matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
@@ -1048,10 +1053,12 @@ where
         let data = self.project_field(val, 0)?;
         let vtable = self.project_field(val, 1)?;
         let vtable = self.read_pointer(&vtable.to_op(self)?)?;
-        let (ty, _) = self.get_ptr_vtable(vtable)?;
+        let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
+        if expected_trait.principal() != vtable_trait {
+            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
+        }
+        // `data` is already the right thing but has the wrong type. So we transmute it.
         let layout = self.layout_of(ty)?;
-        // `data` is already the right thing but has the wrong type. So we transmute it, by
-        // projecting with offset 0.
         let data = data.transmute(layout, self)?;
         Ok((data, vtable))
     }
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 908c4da71f1..9c31532a9ce 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -803,11 +803,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
                     receiver_place.layout.ty.kind()
                 {
-                    let (recv, vptr) = self.unpack_dyn_star(&receiver_place)?;
-                    let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
-                    if dyn_trait != data.principal() {
-                        throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch);
-                    }
+                    let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?;
+                    let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?;
 
                     (vptr, dyn_ty, recv.ptr())
                 } else {
@@ -829,7 +826,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
                     let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
                     if dyn_trait != data.principal() {
-                        throw_ub_custom!(fluent::const_eval_dyn_call_vtable_mismatch);
+                        throw_ub!(InvalidVTableTrait {
+                            expected_trait: data,
+                            vtable_trait: dyn_trait,
+                        });
                     }
 
                     // It might be surprising that we use a pointer as the receiver even if this
@@ -939,13 +939,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let place = self.force_allocation(place)?;
 
         let place = match place.layout.ty.kind() {
-            ty::Dynamic(_, _, ty::Dyn) => {
+            ty::Dynamic(data, _, ty::Dyn) => {
                 // Dropping a trait object. Need to find actual drop fn.
-                self.unpack_dyn_trait(&place)?.0
+                self.unpack_dyn_trait(&place, data)?.0
             }
-            ty::Dynamic(_, _, ty::DynStar) => {
+            ty::Dynamic(data, _, ty::DynStar) => {
                 // Dropping a `dyn*`. Need to find actual drop fn.
-                self.unpack_dyn_star(&place)?.0
+                self.unpack_dyn_star(&place, data)?.0
             }
             _ => {
                 debug_assert_eq!(
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index b8a1733e45a..14566719ccd 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -339,16 +339,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
     ) -> InterpResult<'tcx> {
         let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
         match tail.kind() {
-            ty::Dynamic(_, _, ty::Dyn) => {
+            ty::Dynamic(data, _, ty::Dyn) => {
                 let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
                 // Make sure it is a genuine vtable pointer.
-                let (_ty, _trait) = try_validation!(
+                let (_dyn_ty, dyn_trait) = try_validation!(
                     self.ecx.get_ptr_vtable(vtable),
                     self.path,
                     Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
                         InvalidVTablePtr { value: format!("{vtable}") }
                 );
-                // FIXME: check if the type/trait match what ty::Dynamic says?
+                // Make sure it is for the right trait.
+                if dyn_trait != data.principal() {
+                    throw_validation_failure!(
+                        self.path,
+                        InvalidMetaWrongTrait { expected_trait: data, vtable_trait: dyn_trait }
+                    );
+                }
             }
             ty::Slice(..) | ty::Str => {
                 let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
@@ -933,7 +939,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 }
             }
             _ => {
-                self.walk_value(op)?; // default handler
+                // default handler
+                try_validation!(
+                    self.walk_value(op),
+                    self.path,
+                    // It's not great to catch errors here, since we can't give a very good path,
+                    // but it's better than ICEing.
+                    Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
+                        InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
+                    },
+                );
             }
         }
 
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 0e824f3f592..84557b8e2d6 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -88,22 +88,22 @@ pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
         // Special treatment for special types, where the (static) layout is not sufficient.
         match *ty.kind() {
             // If it is a trait object, switch to the real type that was used to create it.
-            ty::Dynamic(_, _, ty::Dyn) => {
+            ty::Dynamic(data, _, ty::Dyn) => {
                 // Dyn types. This is unsized, and the actual dynamic type of the data is given by the
                 // vtable stored in the place metadata.
                 // unsized values are never immediate, so we can assert_mem_place
                 let op = v.to_op(self.ecx())?;
                 let dest = op.assert_mem_place();
-                let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0;
+                let inner_mplace = self.ecx().unpack_dyn_trait(&dest, data)?.0;
                 trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout);
                 // recurse with the inner type
                 return self.visit_field(v, 0, &inner_mplace.into());
             }
-            ty::Dynamic(_, _, ty::DynStar) => {
+            ty::Dynamic(data, _, ty::DynStar) => {
                 // DynStar types. Very different from a dyn type (but strangely part of the
                 // same variant in `TyKind`): These are pairs where the 2nd component is the
                 // vtable, and the first component is the data (which must be ptr-sized).
-                let data = self.ecx().unpack_dyn_star(v)?.0;
+                let data = self.ecx().unpack_dyn_star(v, data)?.0;
                 return self.visit_field(v, 0, &data);
             }
             // Slices do not need special handling here: they have `Array` field
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 a506d10c1d0..f9786acfc6c 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -414,7 +414,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         BorrowKind::Shared => {
                             PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
                         }
-                        BorrowKind::Fake => {
+                        BorrowKind::Fake(_) => {
                             PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow)
                         }
                         BorrowKind::Mut { .. } => {
@@ -487,7 +487,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 }
             }
 
-            Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake, place)
+            Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake(_), place)
             | Rvalue::AddressOf(Mutability::Not, place) => {
                 let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
                     self.ccx,
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
index 2c835f6750f..5ae3ffaaec2 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
@@ -105,7 +105,7 @@ where
     fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
         match kind {
             mir::BorrowKind::Mut { .. } => true,
-            mir::BorrowKind::Shared | mir::BorrowKind::Fake => {
+            mir::BorrowKind::Shared | mir::BorrowKind::Fake(_) => {
                 self.shared_borrow_allows_mutation(place)
             }
         }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index bf5592c828f..837c02a5b76 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -965,7 +965,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                 }
             },
-            Rvalue::Ref(_, BorrowKind::Fake, _) => {
+            Rvalue::Ref(_, BorrowKind::Fake(_), _) => {
                 if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0522.md b/compiler/rustc_error_codes/src/error_codes/E0522.md
index 83272314a87..b0dd5a775ac 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0522.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0522.md
@@ -6,7 +6,7 @@ Erroneous code example:
 #![feature(lang_items)]
 
 #[lang = "cookie"]
-fn cookie() -> ! { // error: definition of an unknown language item: `cookie`
+fn cookie() -> ! { // error: definition of an unknown lang item: `cookie`
     loop {}
 }
 ```
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index a17e0da47a5..6c84eeaf888 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -177,7 +177,7 @@ where
 {
     /// Add a subdiagnostic to an existing diagnostic.
     fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
-        self.add_to_diag_with(diag, |_, m| m);
+        self.add_to_diag_with(diag, &|_, m| m);
     }
 
     /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
@@ -185,7 +185,7 @@ where
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     );
 }
 
@@ -1197,7 +1197,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         dcx: &crate::DiagCtxt,
         subdiagnostic: impl Subdiagnostic,
     ) -> &mut Self {
-        subdiagnostic.add_to_diag_with(self, |diag, msg| {
+        subdiagnostic.add_to_diag_with(self, &|diag, msg| {
             let args = diag.args.iter();
             let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
             dcx.eagerly_translate(msg, args)
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 6c0551848d6..2b10fcd8d6a 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -227,6 +227,36 @@ impl IntoDiagArg for rustc_lint_defs::Level {
     }
 }
 
+impl<Id> IntoDiagArg for hir::def::Res<Id> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(self.descr()))
+    }
+}
+
+impl IntoDiagArg for DiagLocation {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Str(Cow::from(self.to_string()))
+    }
+}
+
+impl IntoDiagArg for Backtrace {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Str(Cow::from(self.to_string()))
+    }
+}
+
+impl IntoDiagArg for Level {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Str(Cow::from(self.to_string()))
+    }
+}
+
+impl IntoDiagArg for type_ir::ClosureKind {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Str(self.as_str().into())
+    }
+}
+
 #[derive(Clone)]
 pub struct DiagSymbolList(Vec<Symbol>);
 
@@ -244,12 +274,6 @@ impl IntoDiagArg for DiagSymbolList {
     }
 }
 
-impl<Id> IntoDiagArg for hir::def::Res<Id> {
-    fn into_diag_arg(self) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Borrowed(self.descr()))
-    }
-}
-
 impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
     fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         match self {
@@ -302,7 +326,7 @@ impl Subdiagnostic for SingleLabelManySpans {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         diag.span_labels(self.spans, self.label);
     }
@@ -316,24 +340,6 @@ pub struct ExpectedLifetimeParameter {
     pub count: usize,
 }
 
-impl IntoDiagArg for DiagLocation {
-    fn into_diag_arg(self) -> DiagArgValue {
-        DiagArgValue::Str(Cow::from(self.to_string()))
-    }
-}
-
-impl IntoDiagArg for Backtrace {
-    fn into_diag_arg(self) -> DiagArgValue {
-        DiagArgValue::Str(Cow::from(self.to_string()))
-    }
-}
-
-impl IntoDiagArg for Level {
-    fn into_diag_arg(self) -> DiagArgValue {
-        DiagArgValue::Str(Cow::from(self.to_string()))
-    }
-}
-
 #[derive(Subdiagnostic)]
 #[suggestion(errors_indicate_anonymous_lifetime, code = "{suggestion}", style = "verbose")]
 pub struct IndicateAnonymousLifetime {
@@ -343,8 +349,10 @@ pub struct IndicateAnonymousLifetime {
     pub suggestion: String,
 }
 
-impl IntoDiagArg for type_ir::ClosureKind {
-    fn into_diag_arg(self) -> DiagArgValue {
-        DiagArgValue::Str(self.as_str().into())
-    }
+#[derive(Subdiagnostic)]
+pub struct ElidedLifetimeInPathSubdiag {
+    #[subdiagnostic]
+    pub expected: ExpectedLifetimeParameter,
+    #[subdiagnostic]
+    pub indicate: Option<IndicateAnonymousLifetime>,
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index e3363e89594..b3c1c6c8515 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -40,8 +40,8 @@ pub use diagnostic::{
     SubdiagMessageOp, Subdiagnostic,
 };
 pub use diagnostic_impls::{
-    DiagArgFromDisplay, DiagSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime,
-    SingleLabelManySpans,
+    DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
+    IndicateAnonymousLifetime, SingleLabelManySpans,
 };
 pub use emitter::ColorConfig;
 pub use rustc_error_messages::{
@@ -1911,27 +1911,24 @@ impl Level {
 }
 
 // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite.
-pub fn add_elided_lifetime_in_path_suggestion<G: EmissionGuarantee>(
+pub fn elided_lifetime_in_path_suggestion(
     source_map: &SourceMap,
-    diag: &mut Diag<'_, G>,
     n: usize,
     path_span: Span,
     incl_angl_brckt: bool,
     insertion_span: Span,
-) {
-    diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n });
-    if !source_map.is_span_accessible(insertion_span) {
-        // Do not try to suggest anything if generated by a proc-macro.
-        return;
-    }
-    let anon_lts = vec!["'_"; n].join(", ");
-    let suggestion =
-        if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
-
-    diag.subdiagnostic(
-        diag.dcx,
-        IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion },
-    );
+) -> ElidedLifetimeInPathSubdiag {
+    let expected = ExpectedLifetimeParameter { span: path_span, count: n };
+    // Do not try to suggest anything if generated by a proc-macro.
+    let indicate = source_map.is_span_accessible(insertion_span).then(|| {
+        let anon_lts = vec!["'_"; n].join(", ");
+        let suggestion =
+            if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
+
+        IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
+    });
+
+    ElidedLifetimeInPathSubdiag { expected, indicate }
 }
 
 pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 4f62323231a..23b3f31b437 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -798,7 +798,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
     gated!(
         lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
-        "language items are subject to change",
+        "lang items are subject to change",
     ),
     rustc_attr!(
         rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e4f8d77dbc2..2268905430a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -644,13 +644,49 @@ impl<'hir> Generics<'hir> {
         })
     }
 
-    pub fn bounds_span_for_suggestions(&self, param_def_id: LocalDefId) -> Option<Span> {
+    /// Returns a suggestable empty span right after the "final" bound of the generic parameter.
+    ///
+    /// If that bound needs to be wrapped in parentheses to avoid ambiguity with
+    /// subsequent bounds, it also returns an empty span for an open parenthesis
+    /// as the second component.
+    ///
+    /// E.g., adding `+ 'static` after `Fn() -> dyn Future<Output = ()>` or
+    /// `Fn() -> &'static dyn Debug` requires parentheses:
+    /// `Fn() -> (dyn Future<Output = ()>) + 'static` and
+    /// `Fn() -> &'static (dyn Debug) + 'static`, respectively.
+    pub fn bounds_span_for_suggestions(
+        &self,
+        param_def_id: LocalDefId,
+    ) -> Option<(Span, Option<Span>)> {
         self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
             |bound| {
-                // We include bounds that come from a `#[derive(_)]` but point at the user's code,
-                // as we use this method to get a span appropriate for suggestions.
-                let bs = bound.span();
-                bs.can_be_used_for_suggestions().then(|| bs.shrink_to_hi())
+                let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref()
+                    && let [.., segment] = trait_ref.path.segments
+                    && segment.args().parenthesized == GenericArgsParentheses::ParenSugar
+                    && let [binding] = segment.args().bindings
+                    && let TypeBindingKind::Equality { term: Term::Ty(ret_ty) } = binding.kind
+                    && let ret_ty = ret_ty.peel_refs()
+                    && let TyKind::TraitObject(
+                        _,
+                        _,
+                        TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar,
+                    ) = ret_ty.kind
+                    && ret_ty.span.can_be_used_for_suggestions()
+                {
+                    Some(ret_ty.span)
+                } else {
+                    None
+                };
+
+                span_for_parentheses.map_or_else(
+                    || {
+                        // We include bounds that come from a `#[derive(_)]` but point at the user's code,
+                        // as we use this method to get a span appropriate for suggestions.
+                        let bs = bound.span();
+                        bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None))
+                    },
+                    |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))),
+                )
             },
         )
     }
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 879476f890e..6aee1183a10 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -1,4 +1,4 @@
-//! Defines language items.
+//! Defines lang items.
 //!
 //! Language items are items that represent concepts intrinsic to the language
 //! itself. Examples are:
@@ -16,7 +16,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
-/// All of the language items, defined or not.
+/// All of the lang items, defined or not.
 /// Defined lang items can come from the current crate or its dependencies.
 #[derive(HashStable_Generic, Debug)]
 pub struct LanguageItems {
@@ -57,7 +57,7 @@ macro_rules! language_item_table {
     ) => {
 
         enum_from_u32! {
-            /// A representation of all the valid language items in Rust.
+            /// A representation of all the valid lang items in Rust.
             #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
             pub enum LangItem {
                 $(
@@ -177,7 +177,7 @@ language_item_table! {
     CoerceUnsized,           sym::coerce_unsized,      coerce_unsized_trait,       Target::Trait,          GenericRequirement::Minimum(1);
     DispatchFromDyn,         sym::dispatch_from_dyn,   dispatch_from_dyn_trait,    Target::Trait,          GenericRequirement::Minimum(1);
 
-    // language items relating to transmutability
+    // lang items relating to transmutability
     TransmuteOpts,           sym::transmute_opts,      transmute_opts,             Target::Struct,         GenericRequirement::Exact(0);
     TransmuteTrait,          sym::transmute_trait,     transmute_trait,            Target::Trait,          GenericRequirement::Exact(2);
 
@@ -304,7 +304,7 @@ language_item_table! {
     OwnedBox,                sym::owned_box,           owned_box,                  Target::Struct,         GenericRequirement::Minimum(1);
     GlobalAlloc,             sym::global_alloc_ty,     global_alloc_ty,            Target::Struct,         GenericRequirement::None;
 
-    // Experimental language item for Miri
+    // Experimental lang item for Miri
     PtrUnique,               sym::ptr_unique,          ptr_unique,                 Target::Struct,         GenericRequirement::Exact(1);
 
     PhantomData,             sym::phantom_data,        phantom_data,               Target::Struct,         GenericRequirement::Exact(1);
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index d3f51195dfb..aafb5c1c0b4 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -44,16 +44,6 @@ impl<'tcx> Bounds<'tcx> {
         span: Span,
         polarity: ty::PredicatePolarity,
     ) {
-        self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
-    }
-
-    fn push_trait_bound_inner(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        span: Span,
-        polarity: ty::PredicatePolarity,
-    ) {
         let clause = (
             trait_ref
                 .map_bound(|trait_ref| {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a43a67d50d8..32e1b19eaae 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -10,11 +10,10 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::Node;
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
-use rustc_infer::traits::{Obligation, TraitEngineExt as _};
+use rustc_infer::traits::Obligation;
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
-use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
@@ -24,10 +23,10 @@ use rustc_middle::ty::{
 };
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_target::abi::FieldIdx;
+use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
 use rustc_type_ir::fold::TypeFoldable;
 
 use std::cell::LazyCell;
@@ -1715,55 +1714,31 @@ fn opaque_type_cycle_error(
     err.emit()
 }
 
-// FIXME(@lcnr): This should not be computed per coroutine, but instead once for
-// each typeck root.
 pub(super) fn check_coroutine_obligations(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
-    debug_assert!(tcx.is_coroutine(def_id.to_def_id()));
+    debug_assert!(!tcx.is_typeck_child(def_id.to_def_id()));
 
-    let typeck = tcx.typeck(def_id);
-    let param_env = tcx.param_env(typeck.hir_owner.def_id);
+    let typeck_results = tcx.typeck(def_id);
+    let param_env = tcx.param_env(def_id);
 
-    let coroutine_interior_predicates = &typeck.coroutine_interior_predicates[&def_id];
-    debug!(?coroutine_interior_predicates);
+    debug!(?typeck_results.coroutine_stalled_predicates);
 
     let infcx = tcx
         .infer_ctxt()
         // typeck writeback gives us predicates with their regions erased.
         // As borrowck already has checked lifetimes, we do not need to do it again.
         .ignoring_regions()
-        // Bind opaque types to type checking root, as they should have been checked by borrowck,
-        // but may show up in some cases, like when (root) obligations are stalled in the new solver.
-        .with_opaque_type_inference(typeck.hir_owner.def_id)
+        .with_opaque_type_inference(def_id)
         .build();
 
-    let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
-    for (predicate, cause) in coroutine_interior_predicates {
-        let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
-        fulfillment_cx.register_predicate_obligation(&infcx, obligation);
-    }
-
-    if (tcx.features().unsized_locals || tcx.features().unsized_fn_params)
-        && let Some(coroutine) = tcx.mir_coroutine_witnesses(def_id)
-    {
-        for field_ty in coroutine.field_tys.iter() {
-            fulfillment_cx.register_bound(
-                &infcx,
-                param_env,
-                field_ty.ty,
-                tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)),
-                ObligationCause::new(
-                    field_ty.source_info.span,
-                    def_id,
-                    ObligationCauseCode::SizedCoroutineInterior(def_id),
-                ),
-            );
-        }
+    let ocx = ObligationCtxt::new(&infcx);
+    for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
+        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
     }
 
-    let errors = fulfillment_cx.select_all_or_error(&infcx);
+    let errors = ocx.select_all_or_error();
     debug!(?errors);
     if !errors.is_empty() {
         return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index fb4a76bf089..74324c8695b 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -412,13 +412,11 @@ pub fn check_intrinsic_type(
                 (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx))
             }
 
-            sym::ctpop
-            | sym::ctlz
-            | sym::ctlz_nonzero
-            | sym::cttz
-            | sym::cttz_nonzero
-            | sym::bswap
-            | sym::bitreverse => (1, 0, vec![param(0)], param(0)),
+            sym::ctpop | sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => {
+                (1, 0, vec![param(0)], tcx.types.u32)
+            }
+
+            sym::bswap | sym::bitreverse => (1, 0, vec![param(0)], param(0)),
 
             sym::three_way_compare => {
                 (1, 0, vec![param(0), param(0)], tcx.ty_ordering_enum(Some(span)))
@@ -461,7 +459,7 @@ pub fn check_intrinsic_type(
                 (1, 0, vec![param(0), param(0)], param(0))
             }
             sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
-            sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), param(0)], param(0)),
+            sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), tcx.types.u32], param(0)),
             sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
                 (1, 0, vec![param(0), param(0)], param(0))
             }
@@ -535,7 +533,7 @@ pub fn check_intrinsic_type(
 
             sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
                 Some((va_list_ref_ty, _)) => (0, 0, vec![va_list_ref_ty], Ty::new_unit(tcx)),
-                None => bug!("`va_list` language item needed for C-variadic intrinsics"),
+                None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
             },
 
             sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
@@ -543,12 +541,12 @@ pub fn check_intrinsic_type(
                     let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
                     (0, 0, vec![va_list_ptr_ty, va_list_ref_ty], Ty::new_unit(tcx))
                 }
-                None => bug!("`va_list` language item needed for C-variadic intrinsics"),
+                None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
             },
 
             sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
                 Some((va_list_ref_ty, _)) => (1, 0, vec![va_list_ref_ty], param(0)),
-                None => bug!("`va_list` language item needed for C-variadic intrinsics"),
+                None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
             },
 
             sym::nontemporal_store => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 822bf95305f..8e64a9425bb 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -17,6 +17,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
 use rustc_middle::query::Key;
+use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, suggest_constraining_type_param};
 use rustc_middle::ty::{AdtDef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{Binder, TraitRef};
@@ -1200,12 +1201,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 /// Emits an error regarding forbidden type binding associations
 pub fn prohibit_assoc_item_binding(
     tcx: TyCtxt<'_>,
-    span: Span,
-    segment: Option<(&hir::PathSegment<'_>, Span)>,
+    binding: &hir::TypeBinding<'_>,
+    segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
 ) -> ErrorGuaranteed {
-    tcx.dcx().emit_err(AssocTypeBindingNotAllowed {
-        span,
-        fn_trait_expansion: if let Some((segment, span)) = segment
+    let mut err = tcx.dcx().create_err(AssocTypeBindingNotAllowed {
+        span: binding.span,
+        fn_trait_expansion: if let Some((_, segment, span)) = segment
             && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
         {
             Some(ParenthesizedFnTraitExpansion {
@@ -1215,7 +1216,109 @@ pub fn prohibit_assoc_item_binding(
         } else {
             None
         },
-    })
+    });
+
+    // Emit a suggestion to turn the assoc item binding into a generic arg
+    // if the relevant item has a generic param whose name matches the binding name;
+    // otherwise suggest the removal of the binding.
+    if let Some((def_id, segment, _)) = segment
+        && segment.args().parenthesized == hir::GenericArgsParentheses::No
+        && let hir::TypeBindingKind::Equality { term } = binding.kind
+    {
+        // Suggests removal of the offending binding
+        let suggest_removal = |e: &mut Diag<'_>| {
+            let bindings = segment.args().bindings;
+            let args = segment.args().args;
+            let binding_span = binding.span;
+
+            // Compute the span to remove based on the position
+            // of the binding. We do that as follows:
+            //  1. Find the index of the binding in the list of bindings
+            //  2. Locate the spans preceding and following the binding.
+            //     If it's the first binding the preceding span would be
+            //     that of the last arg
+            //  3. Using this information work out whether the span
+            //     to remove will start from the end of the preceding span,
+            //     the start of the next span or will simply be the
+            //     span encomassing everything within the generics brackets
+
+            let Some(binding_index) = bindings.iter().position(|b| b.hir_id == binding.hir_id)
+            else {
+                bug!("a type binding exists but its HIR ID not found in generics");
+            };
+
+            let preceding_span = if binding_index > 0 {
+                Some(bindings[binding_index - 1].span)
+            } else {
+                args.last().map(|a| a.span())
+            };
+
+            let next_span = if binding_index < bindings.len() - 1 {
+                Some(bindings[binding_index + 1].span)
+            } else {
+                None
+            };
+
+            let removal_span = match (preceding_span, next_span) {
+                (Some(prec), _) => binding_span.with_lo(prec.hi()),
+                (None, Some(next)) => binding_span.with_hi(next.lo()),
+                (None, None) => {
+                    let Some(generics_span) = segment.args().span_ext() else {
+                        bug!("a type binding exists but generic span is empty");
+                    };
+
+                    generics_span
+                }
+            };
+
+            // Now emit the suggestion
+            if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
+                e.span_suggestion_verbose(
+                    removal_span,
+                    "consider removing this type binding",
+                    suggestion,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        };
+
+        // Suggest replacing the associated item binding with a generic argument.
+        // i.e., replacing `<..., T = A, ...>` with `<..., A, ...>`.
+        let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
+            if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
+                e.span_suggestion_verbose(
+                    binding.span,
+                    format!("to use `{snippet}` as a generic argument specify it directly"),
+                    snippet,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        };
+
+        // Check if the type has a generic param with the
+        // same name as the assoc type name in type binding
+        let generics = tcx.generics_of(def_id);
+        let matching_param =
+            generics.params.iter().find(|p| p.name.as_str() == binding.ident.as_str());
+
+        // Now emit the appropriate suggestion
+        if let Some(matching_param) = matching_param {
+            match (&matching_param.kind, term) {
+                (GenericParamDefKind::Type { .. }, hir::Term::Ty(ty)) => {
+                    suggest_direct_use(&mut err, ty.span);
+                }
+                (GenericParamDefKind::Const { .. }, hir::Term::Const(c)) => {
+                    let span = tcx.hir().span(c.hir_id);
+                    suggest_direct_use(&mut err, span);
+                }
+                _ => suggest_removal(&mut err),
+            }
+        } else {
+            suggest_removal(&mut err);
+        }
+    }
+
+    err.emit()
 }
 
 pub(crate) fn fn_trait_to_string(
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index dd76862451c..e6a7dfa759c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -454,7 +454,7 @@ pub(crate) fn check_generic_arg_count(
     if gen_pos != GenericArgPosition::Type
         && let Some(b) = gen_args.bindings.first()
     {
-        prohibit_assoc_item_binding(tcx, b.span, None);
+        prohibit_assoc_item_binding(tcx, b, None);
     }
 
     let explicit_late_bound =
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 0d5a295ca96..4a0df6cf7b8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -323,7 +323,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
-            prohibit_assoc_item_binding(self.tcx(), b.span, Some((item_segment, span)));
+            prohibit_assoc_item_binding(self.tcx(), b, Some((def_id, item_segment, span)));
         }
         args
     }
@@ -620,7 +620,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
-            prohibit_assoc_item_binding(self.tcx(), b.span, Some((item_segment, span)));
+            prohibit_assoc_item_binding(self.tcx(), b, Some((item_def_id, item_segment, span)));
         }
         args
     }
@@ -765,7 +765,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             constness,
         );
         if let Some(b) = trait_segment.args().bindings.first() {
-            prohibit_assoc_item_binding(self.tcx(), b.span, Some((trait_segment, span)));
+            prohibit_assoc_item_binding(self.tcx(), b, Some((trait_def_id, trait_segment, span)));
         }
         ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
     }
@@ -1544,7 +1544,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         for segment in segments {
             // Only emit the first error to avoid overloading the user with error messages.
             if let Some(b) = segment.args().bindings.first() {
-                return Err(prohibit_assoc_item_binding(self.tcx(), b.span, None));
+                return Err(prohibit_assoc_item_binding(self.tcx(), b, None));
             }
         }
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d6d22a43fe0..618d90a07ec 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             [candidate] => format!(
                 "the method of the same name on {} `{}`",
                 match candidate.kind {
-                    probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
+                    probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for",
                     _ => "trait",
                 },
                 self.tcx.def_path_str(candidate.item.container_id(self.tcx))
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 3dc9c7b86f7..1c4d5657b17 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -191,7 +191,7 @@ impl Subdiagnostic for TypeMismatchFruTypo {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
 
@@ -370,7 +370,7 @@ impl Subdiagnostic for RemoveSemiForCoerce {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         let mut multispan: MultiSpan = self.semi.into();
         multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr);
@@ -546,7 +546,7 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         match self {
             CastUnknownPointerSub::To(span) => {
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index a0a5a75d382..cc42e69f538 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -750,6 +750,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         }
                     }
                 }
+            } else if let PatKind::Deref(subpattern) = pat.kind {
+                // A deref pattern is a bit special: the binding mode of its inner bindings
+                // determines whether to borrow *at the level of the deref pattern* rather than
+                // borrowing the bound place (since that inner place is inside the temporary that
+                // stores the result of calling `deref()`/`deref_mut()` so can't be captured).
+                let mutable = mc.typeck_results.pat_has_ref_mut_binding(subpattern);
+                let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+                let bk = ty::BorrowKind::from_mutbl(mutability);
+                delegate.borrow(place, discr_place.hir_id, bk);
             }
         }));
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 0b684fdf57b..0ba5d187864 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -588,12 +588,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             obligations
                 .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx));
 
-            let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause)).collect();
-            debug!(?obligations);
-            self.typeck_results
-                .borrow_mut()
-                .coroutine_interior_predicates
-                .insert(expr_def_id, obligations);
+            let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause));
+            self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(obligations);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 43e5ab0ed53..133778a416c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -23,7 +23,7 @@ use rustc_hir::{
 };
 use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::traits::{self};
+use rustc_infer::traits;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::print::with_no_trimmed_paths;
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 121815ecc0b..8bc070bcd36 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -66,7 +66,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::traits;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config;
-use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
@@ -84,21 +84,6 @@ macro_rules! type_error_struct {
     })
 }
 
-fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    // Closures' typeck results come from their outermost function,
-    // as they are part of the same "inference environment".
-    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
-    if typeck_root_def_id != def_id {
-        return tcx.has_typeck_results(typeck_root_def_id);
-    }
-
-    if let Some(def_id) = def_id.as_local() {
-        tcx.hir_node_by_def_id(def_id).body_id().is_some()
-    } else {
-        false
-    }
-}
-
 fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
     &tcx.typeck(def_id).used_trait_imports
 }
@@ -429,11 +414,5 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
 
 pub fn provide(providers: &mut Providers) {
     method::provide(providers);
-    *providers = Providers {
-        typeck,
-        diagnostic_only_typeck,
-        has_typeck_results,
-        used_trait_imports,
-        ..*providers
-    };
+    *providers = Providers { typeck, diagnostic_only_typeck, used_trait_imports, ..*providers };
 }
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 859877962fe..b44c2345933 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -711,13 +711,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                 self.cat_pattern_(place_with_id, subpat, op)?;
             }
 
-            PatKind::Box(subpat) | PatKind::Ref(subpat, _) | PatKind::Deref(subpat) => {
+            PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
                 // box p1, &p1, &mut p1. we can ignore the mutability of
                 // PatKind::Ref since that information is already contained
                 // in the type.
                 let subplace = self.cat_deref(pat, place_with_id)?;
                 self.cat_pattern_(subplace, subpat, op)?;
             }
+            PatKind::Deref(subpat) => {
+                let mutable = self.typeck_results.pat_has_ref_mut_binding(subpat);
+                let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+                let re_erased = self.tcx().lifetimes.re_erased;
+                let ty = self.pat_ty_adjusted(subpat)?;
+                let ty = Ty::new_ref(self.tcx(), re_erased, ty, mutability);
+                // A deref pattern generates a temporary.
+                let place = self.cat_rvalue(pat.hir_id, ty);
+                self.cat_pattern_(place, subpat, op)?;
+            }
 
             PatKind::Slice(before, ref slice, after) => {
                 let Some(element_ty) = place_with_id.place.ty().builtin_index() else {
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 2876e0b49db..8a7ebd6478b 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -21,7 +21,7 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::AssocItem;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::ToPredicate;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
@@ -37,7 +37,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
     CandidateStep, MethodAutoderefStepsResult,
 };
 use rustc_trait_selection::traits::query::CanonicalTyGoal;
-use rustc_trait_selection::traits::NormalizeExt;
+use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCause};
 use std::cell::RefCell;
 use std::cmp::max;
@@ -99,39 +99,6 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
 
 #[derive(Debug, Clone)]
 pub(crate) struct Candidate<'tcx> {
-    // Candidates are (I'm not quite sure, but they are mostly) basically
-    // some metadata on top of a `ty::AssocItem` (without args).
-    //
-    // However, method probing wants to be able to evaluate the predicates
-    // for a function with the args applied - for example, if a function
-    // has `where Self: Sized`, we don't want to consider it unless `Self`
-    // is actually `Sized`, and similarly, return-type suggestions want
-    // to consider the "actual" return type.
-    //
-    // The way this is handled is through `xform_self_ty`. It contains
-    // the receiver type of this candidate, but `xform_self_ty`,
-    // `xform_ret_ty` and `kind` (which contains the predicates) have the
-    // generic parameters of this candidate instantiated with the *same set*
-    // of inference variables, which acts as some weird sort of "query".
-    //
-    // When we check out a candidate, we require `xform_self_ty` to be
-    // a subtype of the passed-in self-type, and this equates the type
-    // variables in the rest of the fields.
-    //
-    // For example, if we have this candidate:
-    // ```
-    //    trait Foo {
-    //        fn foo(&self) where Self: Sized;
-    //    }
-    // ```
-    //
-    // Then `xform_self_ty` will be `&'erased ?X` and `kind` will contain
-    // the predicate `?X: Sized`, so if we are evaluating `Foo` for a
-    // the receiver `&T`, we'll do the subtyping which will make `?X`
-    // get the right value, then when we evaluate the predicate we'll check
-    // if `T: Sized`.
-    xform_self_ty: Ty<'tcx>,
-    xform_ret_ty: Option<Ty<'tcx>>,
     pub(crate) item: ty::AssocItem,
     pub(crate) kind: CandidateKind<'tcx>,
     pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
@@ -139,17 +106,10 @@ pub(crate) struct Candidate<'tcx> {
 
 #[derive(Debug, Clone)]
 pub(crate) enum CandidateKind<'tcx> {
-    InherentImplCandidate(
-        GenericArgsRef<'tcx>,
-        // Normalize obligations
-        Vec<traits::PredicateObligation<'tcx>>,
-    ),
-    ObjectCandidate,
-    TraitCandidate(ty::TraitRef<'tcx>),
-    WhereClauseCandidate(
-        // Trait
-        ty::PolyTraitRef<'tcx>,
-    ),
+    InherentImplCandidate(DefId),
+    ObjectCandidate(ty::PolyTraitRef<'tcx>),
+    TraitCandidate(ty::PolyTraitRef<'tcx>),
+    WhereClauseCandidate(ty::PolyTraitRef<'tcx>),
 }
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -743,42 +703,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 self.record_static_candidate(CandidateSource::Impl(impl_def_id));
                 continue;
             }
-
-            let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id);
-            let impl_ty = impl_ty.instantiate(self.tcx, impl_args);
-
-            debug!("impl_ty: {:?}", impl_ty);
-
-            // Determine the receiver type that the method itself expects.
-            let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args);
-            debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
-
-            // We can't use `FnCtxt::normalize` as it will pollute the
-            // fcx's fulfillment context after this probe is over.
-            //
-            // Note: we only normalize `xform_self_ty` here since the normalization
-            // of the return type can lead to inference results that prohibit
-            // valid candidates from being found, see issue #85671
-            //
-            // FIXME Postponing the normalization of the return type likely only hides a deeper bug,
-            // which might be caused by the `param_env` itself. The clauses of the `param_env`
-            // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized,
-            // see issue #89650
-            let cause = traits::ObligationCause::misc(self.span, self.body_id);
-            let InferOk { value: xform_self_ty, obligations } =
-                self.fcx.at(&cause, self.param_env).normalize(xform_self_ty);
-
-            debug!(
-                "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}",
-                xform_self_ty, xform_ret_ty
-            );
-
             self.push_candidate(
                 Candidate {
-                    xform_self_ty,
-                    xform_ret_ty,
                     item,
-                    kind: InherentImplCandidate(impl_args, obligations),
+                    kind: InherentImplCandidate(impl_def_id),
                     import_ids: smallvec![],
                 },
                 true,
@@ -810,26 +738,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         // a `&self` method will wind up with an argument type like `&dyn Trait`.
         let trait_ref = principal.with_self_ty(self.tcx, self_ty);
         self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
-            if new_trait_ref.has_non_region_bound_vars() {
-                this.dcx().span_delayed_bug(
-                    this.span,
-                    "tried to select method from HRTB with non-lifetime bound vars",
-                );
-                return;
-            }
-
-            let new_trait_ref = this.instantiate_bound_regions_with_erased(new_trait_ref);
-
-            let (xform_self_ty, xform_ret_ty) =
-                this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
             this.push_candidate(
-                Candidate {
-                    xform_self_ty,
-                    xform_ret_ty,
-                    item,
-                    kind: ObjectCandidate,
-                    import_ids: smallvec![],
-                },
+                Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] },
                 true,
             );
         });
@@ -860,19 +770,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         });
 
         self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
-            let trait_ref = this.instantiate_binder_with_fresh_vars(
-                this.span,
-                infer::BoundRegionConversionTime::FnCall,
-                poly_trait_ref,
-            );
-
-            let (xform_self_ty, xform_ret_ty) =
-                this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.args);
-
             this.push_candidate(
                 Candidate {
-                    xform_self_ty,
-                    xform_ret_ty,
                     item,
                     kind: WhereClauseCandidate(poly_trait_ref),
                     import_ids: smallvec![],
@@ -929,27 +828,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
-    fn matches_return_type(
-        &self,
-        method: ty::AssocItem,
-        self_ty: Option<Ty<'tcx>>,
-        expected: Ty<'tcx>,
-    ) -> bool {
+    fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool {
         match method.kind {
             ty::AssocKind::Fn => self.probe(|_| {
                 let args = self.fresh_args_for_item(self.span, method.def_id);
                 let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args);
                 let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty);
-
-                if let Some(self_ty) = self_ty {
-                    if self
-                        .at(&ObligationCause::dummy(), self.param_env)
-                        .sup(DefineOpaqueTypes::No, fty.inputs()[0], self_ty)
-                        .is_err()
-                    {
-                        return false;
-                    }
-                }
                 self.can_sub(self.param_env, fty.output(), expected)
             }),
             _ => false,
@@ -978,21 +862,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                             bound_trait_ref.def_id(),
                         ));
                     } else {
-                        let new_trait_ref = self.instantiate_binder_with_fresh_vars(
-                            self.span,
-                            infer::BoundRegionConversionTime::FnCall,
-                            bound_trait_ref,
-                        );
-
-                        let (xform_self_ty, xform_ret_ty) =
-                            self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
                         self.push_candidate(
                             Candidate {
-                                xform_self_ty,
-                                xform_ret_ty,
                                 item,
                                 import_ids: import_ids.clone(),
-                                kind: TraitCandidate(new_trait_ref),
+                                kind: TraitCandidate(bound_trait_ref),
                             },
                             false,
                         );
@@ -1011,16 +885,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     self.record_static_candidate(CandidateSource::Trait(trait_def_id));
                     continue;
                 }
-
-                let (xform_self_ty, xform_ret_ty) =
-                    self.xform_self_ty(item, trait_ref.self_ty(), trait_args);
                 self.push_candidate(
                     Candidate {
-                        xform_self_ty,
-                        xform_ret_ty,
                         item,
                         import_ids: import_ids.clone(),
-                        kind: TraitCandidate(trait_ref),
+                        kind: TraitCandidate(ty::Binder::dummy(trait_ref)),
                     },
                     false,
                 );
@@ -1040,7 +909,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             .filter(|candidate| candidate_filter(&candidate.item))
             .filter(|candidate| {
                 if let Some(return_ty) = self.return_type {
-                    self.matches_return_type(candidate.item, None, return_ty)
+                    self.matches_return_type(candidate.item, return_ty)
                 } else {
                     true
                 }
@@ -1450,16 +1319,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
     fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource {
         match candidate.kind {
-            InherentImplCandidate(..) => {
+            InherentImplCandidate(_) => {
                 CandidateSource::Impl(candidate.item.container_id(self.tcx))
             }
-            ObjectCandidate | WhereClauseCandidate(_) => {
+            ObjectCandidate(_) | WhereClauseCandidate(_) => {
                 CandidateSource::Trait(candidate.item.container_id(self.tcx))
             }
             TraitCandidate(trait_ref) => self.probe(|_| {
+                let trait_ref =
+                    self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, trait_ref);
+                let (xform_self_ty, _) =
+                    self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args);
                 let _ = self.at(&ObligationCause::dummy(), self.param_env).sup(
                     DefineOpaqueTypes::No,
-                    candidate.xform_self_ty,
+                    xform_self_ty,
                     self_ty,
                 );
                 match self.select_trait_candidate(trait_ref) {
@@ -1486,54 +1359,46 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) -> ProbeResult {
         debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);
 
-        self.probe(|_| {
-            // First check that the self type can be related.
-            let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup(
-                DefineOpaqueTypes::No,
-                probe.xform_self_ty,
-                self_ty,
-            ) {
-                Ok(InferOk { obligations, value: () }) => obligations,
-                Err(err) => {
-                    debug!("--> cannot relate self-types {:?}", err);
-                    return ProbeResult::NoMatch;
-                }
-            };
+        self.probe(|snapshot| {
+            let outer_universe = self.universe();
 
             let mut result = ProbeResult::Match;
-            let mut xform_ret_ty = probe.xform_ret_ty;
-            debug!(?xform_ret_ty);
-
-            let cause = traits::ObligationCause::misc(self.span, self.body_id);
+            let cause = &self.misc(self.span);
+            let ocx = ObligationCtxt::new(self);
 
-            let mut parent_pred = None;
+            let mut trait_predicate = None;
+            let (mut xform_self_ty, mut xform_ret_ty);
 
-            // If so, impls may carry other conditions (e.g., where
-            // clauses) that must be considered. Make sure that those
-            // match as well (or at least may match, sometimes we
-            // don't have enough information to fully evaluate).
             match probe.kind {
-                InherentImplCandidate(args, ref ref_obligations) => {
-                    // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`,
-                    // see the reasons mentioned in the comments in `assemble_inherent_impl_probe`
-                    // for why this is necessary
-                    let InferOk {
-                        value: normalized_xform_ret_ty,
-                        obligations: normalization_obligations,
-                    } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty);
-                    xform_ret_ty = normalized_xform_ret_ty;
-                    debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
-
+                InherentImplCandidate(impl_def_id) => {
+                    let impl_args = self.fresh_args_for_item(self.span, impl_def_id);
+                    let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args);
+                    (xform_self_ty, xform_ret_ty) =
+                        self.xform_self_ty(probe.item, impl_ty, impl_args);
+                    xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
+                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
+                    match self.at(cause, self.param_env).sup(
+                        DefineOpaqueTypes::No,
+                        xform_self_ty,
+                        self_ty,
+                    ) {
+                        Ok(infer_ok) => {
+                            ocx.register_infer_ok_obligations(infer_ok);
+                        }
+                        Err(err) => {
+                            debug!("--> cannot relate self-types {:?}", err);
+                            return ProbeResult::NoMatch;
+                        }
+                    }
+                    // FIXME: Weirdly, we normalize the ret ty in this candidate, but no other candidates.
+                    xform_ret_ty = ocx.normalize(cause, self.param_env, xform_ret_ty);
                     // Check whether the impl imposes obligations we have to worry about.
                     let impl_def_id = probe.item.container_id(self.tcx);
-                    let impl_bounds = self.tcx.predicates_of(impl_def_id);
-                    let impl_bounds = impl_bounds.instantiate(self.tcx, args);
-
-                    let InferOk { value: impl_bounds, obligations: norm_obligations } =
-                        self.fcx.at(&cause, self.param_env).normalize(impl_bounds);
-
+                    let impl_bounds =
+                        self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
+                    let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds);
                     // Convert the bounds into obligations.
-                    let impl_obligations = traits::predicates_for_generics(
+                    ocx.register_obligations(traits::predicates_for_generics(
                         |idx, span| {
                             let code = if span.is_dummy() {
                                 traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
@@ -1549,106 +1414,92 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         },
                         self.param_env,
                         impl_bounds,
-                    );
-
-                    let candidate_obligations = impl_obligations
-                        .chain(norm_obligations)
-                        .chain(ref_obligations.iter().cloned())
-                        .chain(normalization_obligations);
-
-                    // Evaluate those obligations to see if they might possibly hold.
-                    for o in candidate_obligations {
-                        let o = self.resolve_vars_if_possible(o);
-                        if !self.predicate_may_hold(&o) {
-                            result = ProbeResult::NoMatch;
-                            let parent_o = o.clone();
-                            let implied_obligations = traits::elaborate(self.tcx, vec![o]);
-                            for o in implied_obligations {
-                                let parent = if o == parent_o {
-                                    None
-                                } else {
-                                    if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id())
-                                        == self.tcx.lang_items().sized_trait()
-                                    {
-                                        // We don't care to talk about implicit `Sized` bounds.
-                                        continue;
-                                    }
-                                    Some(parent_o.predicate)
-                                };
-                                if !self.predicate_may_hold(&o) {
-                                    possibly_unsatisfied_predicates.push((
-                                        o.predicate,
-                                        parent,
-                                        Some(o.cause),
-                                    ));
-                                }
-                            }
-                        }
-                    }
-                }
-
-                ObjectCandidate | WhereClauseCandidate(..) => {
-                    // These have no additional conditions to check.
+                    ));
                 }
-
-                TraitCandidate(trait_ref) => {
+                TraitCandidate(poly_trait_ref) => {
+                    // Some trait methods are excluded for arrays before 2021.
+                    // (`array.into_iter()` wants a slice iterator for compatibility.)
                     if let Some(method_name) = self.method_name {
-                        // Some trait methods are excluded for arrays before 2021.
-                        // (`array.into_iter()` wants a slice iterator for compatibility.)
                         if self_ty.is_array() && !method_name.span.at_least_rust_2021() {
-                            let trait_def = self.tcx.trait_def(trait_ref.def_id);
+                            let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
                             if trait_def.skip_array_during_method_dispatch {
                                 return ProbeResult::NoMatch;
                             }
                         }
                     }
-                    let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx);
-                    parent_pred = Some(predicate);
-                    let obligation =
-                        traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate);
-                    if !self.predicate_may_hold(&obligation) {
+
+                    let trait_ref = self.instantiate_binder_with_fresh_vars(
+                        self.span,
+                        infer::FnCall,
+                        poly_trait_ref,
+                    );
+                    let trait_ref = ocx.normalize(cause, self.param_env, trait_ref);
+                    (xform_self_ty, xform_ret_ty) =
+                        self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
+                    xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
+                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
+                    match self.at(cause, self.param_env).sup(
+                        DefineOpaqueTypes::No,
+                        xform_self_ty,
+                        self_ty,
+                    ) {
+                        Ok(infer_ok) => {
+                            ocx.register_infer_ok_obligations(infer_ok);
+                        }
+                        Err(err) => {
+                            debug!("--> cannot relate self-types {:?}", err);
+                            return ProbeResult::NoMatch;
+                        }
+                    }
+                    let obligation = traits::Obligation::new(
+                        self.tcx,
+                        cause.clone(),
+                        self.param_env,
+                        ty::Binder::dummy(trait_ref),
+                    );
+
+                    // FIXME(-Znext-solver): We only need this hack to deal with fatal
+                    // overflow in the old solver.
+                    if self.infcx.next_trait_solver() || self.infcx.predicate_may_hold(&obligation)
+                    {
+                        ocx.register_obligation(obligation);
+                    } else {
                         result = ProbeResult::NoMatch;
-                        if self.probe(|_| {
-                            match self.select_trait_candidate(trait_ref) {
-                                Err(_) => return true,
-                                Ok(Some(impl_source))
-                                    if !impl_source.borrow_nested_obligations().is_empty() =>
-                                {
-                                    for obligation in impl_source.borrow_nested_obligations() {
-                                        // Determine exactly which obligation wasn't met, so
-                                        // that we can give more context in the error.
-                                        if !self.predicate_may_hold(obligation) {
-                                            let nested_predicate =
-                                                self.resolve_vars_if_possible(obligation.predicate);
-                                            let predicate =
-                                                self.resolve_vars_if_possible(predicate);
-                                            let p = if predicate == nested_predicate {
-                                                // Avoid "`MyStruct: Foo` which is required by
-                                                // `MyStruct: Foo`" in E0599.
-                                                None
-                                            } else {
-                                                Some(predicate)
-                                            };
-                                            possibly_unsatisfied_predicates.push((
-                                                nested_predicate,
-                                                p,
-                                                Some(obligation.cause.clone()),
-                                            ));
-                                        }
-                                    }
-                                }
-                                _ => {
-                                    // Some nested subobligation of this predicate
-                                    // failed.
-                                    let predicate = self.resolve_vars_if_possible(predicate);
-                                    possibly_unsatisfied_predicates.push((predicate, None, None));
+                        if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref) {
+                            for nested_obligation in candidate.nested_obligations() {
+                                if !self.infcx.predicate_may_hold(&nested_obligation) {
+                                    possibly_unsatisfied_predicates.push((
+                                        self.resolve_vars_if_possible(nested_obligation.predicate),
+                                        Some(self.resolve_vars_if_possible(obligation.predicate)),
+                                        Some(nested_obligation.cause),
+                                    ));
                                 }
                             }
-                            false
-                        }) {
-                            // This candidate's primary obligation doesn't even
-                            // select - don't bother registering anything in
-                            // `potentially_unsatisfied_predicates`.
+                        }
+                    }
+
+                    trait_predicate = Some(ty::Binder::dummy(trait_ref).to_predicate(self.tcx));
+                }
+                ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => {
+                    let trait_ref = self.instantiate_binder_with_fresh_vars(
+                        self.span,
+                        infer::FnCall,
+                        poly_trait_ref,
+                    );
+                    (xform_self_ty, xform_ret_ty) =
+                        self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
+                    xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
+                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
+                    match self.at(cause, self.param_env).sup(
+                        DefineOpaqueTypes::No,
+                        xform_self_ty,
+                        self_ty,
+                    ) {
+                        Ok(infer_ok) => {
+                            ocx.register_infer_ok_obligations(infer_ok);
+                        }
+                        Err(err) => {
+                            debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
                         }
                     }
@@ -1656,11 +1507,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             }
 
             // Evaluate those obligations to see if they might possibly hold.
-            for o in sub_obligations {
-                let o = self.resolve_vars_if_possible(o);
-                if !self.predicate_may_hold(&o) {
-                    result = ProbeResult::NoMatch;
-                    possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause)));
+            for error in ocx.select_where_possible() {
+                result = ProbeResult::NoMatch;
+                let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate);
+                if let Some(trait_predicate) = trait_predicate
+                    && nested_predicate == self.resolve_vars_if_possible(trait_predicate)
+                {
+                    // Don't report possibly unsatisfied predicates if the root
+                    // trait obligation from a `TraitCandidate` is unsatisfied.
+                    // That just means the candidate doesn't hold.
+                } else {
+                    possibly_unsatisfied_predicates.push((
+                        nested_predicate,
+                        Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
+                            .filter(|root_predicate| *root_predicate != nested_predicate),
+                        Some(error.obligation.cause),
+                    ));
                 }
             }
 
@@ -1672,38 +1534,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 // We don't normalize the other candidates for perf/backwards-compat reasons...
                 // but `self.return_type` is only set on the diagnostic-path, so we
                 // should be okay doing it here.
-                if !matches!(probe.kind, InherentImplCandidate(..)) {
-                    let InferOk {
-                        value: normalized_xform_ret_ty,
-                        obligations: normalization_obligations,
-                    } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty);
-                    xform_ret_ty = normalized_xform_ret_ty;
-                    debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
-                    // Evaluate those obligations to see if they might possibly hold.
-                    for o in normalization_obligations {
-                        let o = self.resolve_vars_if_possible(o);
-                        if !self.predicate_may_hold(&o) {
-                            result = ProbeResult::NoMatch;
-                            possibly_unsatisfied_predicates.push((
-                                o.predicate,
-                                None,
-                                Some(o.cause),
-                            ));
-                        }
-                    }
+                if !matches!(probe.kind, InherentImplCandidate(_)) {
+                    xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty);
                 }
 
                 debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty);
-                if let ProbeResult::Match = result
-                    && self
-                        .at(&ObligationCause::dummy(), self.param_env)
-                        .sup(DefineOpaqueTypes::Yes, return_ty, xform_ret_ty)
-                        .is_err()
-                {
-                    result = ProbeResult::BadReturnType;
+                match ocx.sup(cause, self.param_env, return_ty, xform_ret_ty) {
+                    Ok(()) => {}
+                    Err(_) => {
+                        result = ProbeResult::BadReturnType;
+                    }
+                }
+
+                // Evaluate those obligations to see if they might possibly hold.
+                for error in ocx.select_where_possible() {
+                    result = ProbeResult::NoMatch;
+                    possibly_unsatisfied_predicates.push((
+                        error.obligation.predicate,
+                        Some(error.root_obligation.predicate)
+                            .filter(|predicate| *predicate != error.obligation.predicate),
+                        Some(error.root_obligation.cause),
+                    ));
                 }
             }
 
+            // Previously, method probe used `evaluate_predicate` to determine if a predicate
+            // was impossible to satisfy. This did a leak check, so we must also do a leak
+            // check here to prevent backwards-incompatible ambiguity being introduced. See
+            // `tests/ui/methods/leak-check-disquality.rs` for a simple example of when this
+            // may happen.
+            if let Err(_) = self.leak_check(outer_universe, Some(snapshot)) {
+                result = ProbeResult::NoMatch;
+            }
+
             result
         })
     }
@@ -1894,40 +1757,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             fn_sig.instantiate(self.tcx, args)
         };
 
-        self.instantiate_bound_regions_with_erased(xform_fn_sig)
-    }
-
-    /// Gets the type of an impl and generate generic parameters with inference vars.
-    fn impl_ty_and_args(
-        &self,
-        impl_def_id: DefId,
-    ) -> (ty::EarlyBinder<Ty<'tcx>>, GenericArgsRef<'tcx>) {
-        (self.tcx.type_of(impl_def_id), self.fresh_args_for_item(self.span, impl_def_id))
-    }
-
-    /// Replaces late-bound-regions bound by `value` with `'static` using
-    /// `ty::instantiate_bound_regions_with_erased`.
-    ///
-    /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of
-    /// method matching. It is reasonable during the probe phase because we don't consider region
-    /// relationships at all. Therefore, we can just replace all the region variables with 'static
-    /// rather than creating fresh region variables. This is nice for two reasons:
-    ///
-    /// 1. Because the numbers of the region variables would otherwise be fairly unique to this
-    ///    particular method call, it winds up creating fewer types overall, which helps for memory
-    ///    usage. (Admittedly, this is a rather small effect, though measurable.)
-    ///
-    /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any
-    ///    late-bound regions with 'static. Otherwise, if we were going to replace late-bound
-    ///    regions with actual region variables as is proper, we'd have to ensure that the same
-    ///    region got replaced with the same variable, which requires a bit more coordination
-    ///    and/or tracking the instantiations and
-    ///    so forth.
-    fn instantiate_bound_regions_with_erased<T>(&self, value: ty::Binder<'tcx, T>) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        self.tcx.instantiate_bound_regions_with_erased(value)
+        self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig)
     }
 
     /// Determine if the given associated item type is relevant in the current context.
@@ -2051,10 +1881,10 @@ impl<'tcx> Candidate<'tcx> {
         Pick {
             item: self.item,
             kind: match self.kind {
-                InherentImplCandidate(..) => InherentImplPick,
-                ObjectCandidate => ObjectPick,
+                InherentImplCandidate(_) => InherentImplPick,
+                ObjectCandidate(_) => ObjectPick,
                 TraitCandidate(_) => TraitPick,
-                WhereClauseCandidate(ref trait_ref) => {
+                WhereClauseCandidate(trait_ref) => {
                     // Only trait derived from where-clauses should
                     // appear here, so they should not contain any
                     // inference variables or other artifacts. This
@@ -2065,7 +1895,7 @@ impl<'tcx> Candidate<'tcx> {
                             && !trait_ref.skip_binder().args.has_placeholders()
                     );
 
-                    WhereClausePick(*trait_ref)
+                    WhereClausePick(trait_ref)
                 }
             },
             import_ids: self.import_ids.clone(),
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index e74c4d06b5b..078009515e4 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3291,14 +3291,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 param.name.ident(),
                             ));
                             let bounds_span = hir_generics.bounds_span_for_suggestions(def_id);
-                            if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
+                            if rcvr_ty.is_ref()
+                                && param.is_impl_trait()
+                                && let Some((bounds_span, _)) = bounds_span
+                            {
                                 err.multipart_suggestions(
                                     msg,
                                     candidates.iter().map(|t| {
                                         vec![
                                             (param.span.shrink_to_lo(), "(".to_string()),
                                             (
-                                                bounds_span.unwrap(),
+                                                bounds_span,
                                                 format!(" + {})", self.tcx.def_path_str(t.def_id)),
                                             ),
                                         ]
@@ -3308,32 +3311,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 return;
                             }
 
-                            let (sp, introducer) = if let Some(span) = bounds_span {
-                                (span, Introducer::Plus)
-                            } else if let Some(colon_span) = param.colon_span {
-                                (colon_span.shrink_to_hi(), Introducer::Nothing)
-                            } else if param.is_impl_trait() {
-                                (param.span.shrink_to_hi(), Introducer::Plus)
-                            } else {
-                                (param.span.shrink_to_hi(), Introducer::Colon)
-                            };
+                            let (sp, introducer, open_paren_sp) =
+                                if let Some((span, open_paren_sp)) = bounds_span {
+                                    (span, Introducer::Plus, open_paren_sp)
+                                } else if let Some(colon_span) = param.colon_span {
+                                    (colon_span.shrink_to_hi(), Introducer::Nothing, None)
+                                } else if param.is_impl_trait() {
+                                    (param.span.shrink_to_hi(), Introducer::Plus, None)
+                                } else {
+                                    (param.span.shrink_to_hi(), Introducer::Colon, None)
+                                };
 
-                            err.span_suggestions(
-                                sp,
+                            let all_suggs = candidates.iter().map(|cand| {
+                                let suggestion = format!(
+                                    "{} {}",
+                                    match introducer {
+                                        Introducer::Plus => " +",
+                                        Introducer::Colon => ":",
+                                        Introducer::Nothing => "",
+                                    },
+                                    self.tcx.def_path_str(cand.def_id)
+                                );
+
+                                let mut suggs = vec![];
+
+                                if let Some(open_paren_sp) = open_paren_sp {
+                                    suggs.push((open_paren_sp, "(".to_string()));
+                                    suggs.push((sp, format!("){suggestion}")));
+                                } else {
+                                    suggs.push((sp, suggestion));
+                                }
+
+                                suggs
+                            });
+
+                            err.multipart_suggestions(
                                 msg,
-                                candidates.iter().map(|t| {
-                                    format!(
-                                        "{} {}",
-                                        match introducer {
-                                            Introducer::Plus => " +",
-                                            Introducer::Colon => ":",
-                                            Introducer::Nothing => "",
-                                        },
-                                        self.tcx.def_path_str(t.def_id)
-                                    )
-                                }),
+                                all_suggs,
                                 Applicability::MaybeIncorrect,
                             );
+
                             return;
                         }
                         Node::Item(hir::Item {
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 875f8b23a84..0a40ffb0d5a 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -551,15 +551,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn visit_coroutine_interior(&mut self) {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
-        self.tcx().with_stable_hashing_context(move |ref hcx| {
-            for (&expr_def_id, predicates) in
-                fcx_typeck_results.coroutine_interior_predicates.to_sorted(hcx, false).into_iter()
-            {
-                let predicates =
-                    self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
-                self.typeck_results.coroutine_interior_predicates.insert(expr_def_id, predicates);
-            }
-        })
+        for (predicate, cause) in &fcx_typeck_results.coroutine_stalled_predicates {
+            let (predicate, cause) = self.resolve((*predicate, cause.clone()), &cause.span);
+            self.typeck_results.coroutine_stalled_predicates.insert((predicate, cause));
+        }
     }
 
     #[instrument(skip(self), level = "debug")]
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 4593108edac..2acaeac2439 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -239,7 +239,7 @@ impl Subdiagnostic for RegionOriginNote<'_> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         let mut label_or_note = |span, msg: DiagMessage| {
             let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
@@ -304,7 +304,7 @@ impl Subdiagnostic for LifetimeMismatchLabels {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         match self {
             LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
@@ -352,7 +352,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         let mut mk_suggestion = || {
             let (
@@ -454,7 +454,7 @@ impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         mut self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         self.unmet_requirements
             .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
@@ -773,7 +773,7 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         let mut type_param_span: MultiSpan = self.spans.clone().into();
         for &span in &self.spans {
@@ -818,7 +818,7 @@ impl Subdiagnostic for DynTraitConstraintSuggestion {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         let mut multi_span: MultiSpan = vec![self.span].into();
         multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
@@ -865,7 +865,7 @@ impl Subdiagnostic for ReqIntroducedLocations {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         mut self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         for sp in self.spans {
             self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
@@ -888,7 +888,7 @@ impl Subdiagnostic for MoreTargeted {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         diag.code(E0772);
         diag.primary_message(fluent::infer_more_targeted);
@@ -1293,7 +1293,7 @@ impl Subdiagnostic for SuggestTuplePatternMany {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         diag.arg("path", self.path);
         let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 7b962b01408..70d94873530 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -163,7 +163,7 @@ impl Subdiagnostic for RegionExplanation<'_> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         diag.arg("pref_kind", self.prefix);
         diag.arg("suff_kind", self.suffix);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index feef64bc6a5..40a9db10956 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2369,7 +2369,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 generic_param_scope = self.tcx.local_parent(generic_param_scope);
             }
 
-            // type_param_sugg_span is (span, has_bounds)
+            // type_param_sugg_span is (span, has_bounds, needs_parentheses)
             let (type_scope, type_param_sugg_span) = match bound_kind {
                 GenericKind::Param(param) => {
                     let generics = self.tcx.generics_of(generic_param_scope);
@@ -2380,10 +2380,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     // instead we suggest `T: 'a + 'b` in that case.
                     let hir_generics = self.tcx.hir().get_generics(scope).unwrap();
                     let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
-                        Some(span) => Some((span, true)),
+                        Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
                         // If `param` corresponds to `Self`, no usable suggestion span.
                         None if generics.has_self && param.index == 0 => None,
-                        None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false)),
+                        None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)),
                     };
                     (scope, sugg_span)
                 }
@@ -2406,12 +2406,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let mut suggs = vec![];
             let lt_name = self.suggest_name_region(sub, &mut suggs);
 
-            if let Some((sp, has_lifetimes)) = type_param_sugg_span
+            if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span
                 && suggestion_scope == type_scope
             {
                 let suggestion =
                     if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
-                suggs.push((sp, suggestion))
+
+                if let Some(open_paren_sp) = open_paren_sp {
+                    suggs.push((open_paren_sp, "(".to_string()));
+                    suggs.push((sp, format!("){suggestion}")));
+                } else {
+                    suggs.push((sp, suggestion))
+                }
             } else if let GenericKind::Alias(ref p) = bound_kind
                 && let ty::Projection = p.kind(self.tcx)
                 && let DefKind::AssocTy = self.tcx.def_kind(p.def_id)
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 91cef02c7d1..b593c41a8ea 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -759,7 +759,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
     tcx.hir().par_body_owners(|def_id| {
         if tcx.is_coroutine(def_id.to_def_id()) {
             tcx.ensure().mir_coroutine_witnesses(def_id);
-            tcx.ensure().check_coroutine_obligations(def_id);
+            tcx.ensure().check_coroutine_obligations(
+                tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
+            );
         }
     });
     sess.time("layout_testing", || layout_test::test_layout(tcx));
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index ee677a092e2..1b9165342d4 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -8,7 +8,7 @@ use rustc_codegen_ssa::CodegenResults;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
-use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
+use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_incremental::setup_dep_graph;
 use rustc_metadata::creader::CStore;
@@ -140,11 +140,16 @@ impl<'tcx> Queries<'tcx> {
 
             let cstore = FreezeLock::new(Box::new(CStore::new(
                 self.compiler.codegen_backend.metadata_loader(),
-                stable_crate_id,
             )) as _);
             let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
-            let untracked =
-                Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions };
+
+            let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
+            let untracked = Untracked {
+                cstore,
+                source_span: AppendOnlyIndexVec::new(),
+                definitions,
+                stable_crate_ids,
+            };
 
             let qcx = passes::create_global_ctxt(
                 self.compiler,
@@ -158,7 +163,8 @@ impl<'tcx> Queries<'tcx> {
             );
 
             qcx.enter(|tcx| {
-                let feed = tcx.feed_local_crate();
+                let feed = tcx.create_crate_num(stable_crate_id).unwrap();
+                assert_eq!(feed.key(), LOCAL_CRATE);
                 feed.crate_name(crate_name);
 
                 let feed = tcx.feed_unit_query();
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 8d741ef4c1b..f6014bcd893 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -321,6 +321,7 @@ fn test_search_paths_tracking_hash_different_order() {
             &opts.target_triple,
             &early_dcx,
             search_path,
+            false,
         ));
     };
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8b974a461d4..0c89e186c47 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1769,13 +1769,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
 }
 
 declare_lint! {
-    /// The `keyword_idents` lint detects edition keywords being used as an
+    /// The `keyword_idents_2018` lint detects edition keywords being used as an
     /// identifier.
     ///
     /// ### Example
     ///
     /// ```rust,edition2015,compile_fail
-    /// #![deny(keyword_idents)]
+    /// #![deny(keyword_idents_2018)]
     /// // edition 2015
     /// fn dyn() {}
     /// ```
@@ -1804,7 +1804,7 @@ declare_lint! {
     /// [editions]: https://doc.rust-lang.org/edition-guide/
     /// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
     /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
-    pub KEYWORD_IDENTS,
+    pub KEYWORD_IDENTS_2018,
     Allow,
     "detects edition keywords being used as an identifier",
     @future_incompatible = FutureIncompatibleInfo {
@@ -1813,9 +1813,54 @@ declare_lint! {
     };
 }
 
+declare_lint! {
+    /// The `keyword_idents_2024` lint detects edition keywords being used as an
+    /// identifier.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,edition2015,compile_fail
+    /// #![deny(keyword_idents_2024)]
+    /// // edition 2015
+    /// fn gen() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Rust [editions] allow the language to evolve without breaking
+    /// backwards compatibility. This lint catches code that uses new keywords
+    /// that are added to the language that are used as identifiers (such as a
+    /// variable name, function name, etc.). If you switch the compiler to a
+    /// new edition without updating the code, then it will fail to compile if
+    /// you are using a new keyword as an identifier.
+    ///
+    /// You can manually change the identifiers to a non-keyword, or use a
+    /// [raw identifier], for example `r#gen`, to transition to a new edition.
+    ///
+    /// This lint solves the problem automatically. It is "allow" by default
+    /// because the code is perfectly valid in older editions. The [`cargo
+    /// fix`] tool with the `--edition` flag will switch this lint to "warn"
+    /// and automatically apply the suggested fix from the compiler (which is
+    /// to use a raw identifier). This provides a completely automated way to
+    /// update old code for a new edition.
+    ///
+    /// [editions]: https://doc.rust-lang.org/edition-guide/
+    /// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
+    /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
+    pub KEYWORD_IDENTS_2024,
+    Allow,
+    "detects edition keywords being used as an identifier",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
+    };
+}
+
 declare_lint_pass!(
     /// Check for uses of edition keywords used as an identifier.
-    KeywordIdents => [KEYWORD_IDENTS]
+    KeywordIdents => [KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024]
 );
 
 struct UnderMacro(bool);
@@ -1841,42 +1886,39 @@ impl KeywordIdents {
         UnderMacro(under_macro): UnderMacro,
         ident: Ident,
     ) {
-        let next_edition = match cx.sess().edition() {
-            Edition::Edition2015 => {
-                match ident.name {
-                    kw::Async | kw::Await | kw::Try => Edition::Edition2018,
-
-                    // rust-lang/rust#56327: Conservatively do not
-                    // attempt to report occurrences of `dyn` within
-                    // macro definitions or invocations, because `dyn`
-                    // can legitimately occur as a contextual keyword
-                    // in 2015 code denoting its 2018 meaning, and we
-                    // do not want rustfix to inject bugs into working
-                    // code by rewriting such occurrences.
-                    //
-                    // But if we see `dyn` outside of a macro, we know
-                    // its precise role in the parsed AST and thus are
-                    // assured this is truly an attempt to use it as
-                    // an identifier.
-                    kw::Dyn if !under_macro => Edition::Edition2018,
-
-                    _ => return,
-                }
-            }
+        let (lint, edition) = match ident.name {
+            kw::Async | kw::Await | kw::Try => (KEYWORD_IDENTS_2018, Edition::Edition2018),
+
+            // rust-lang/rust#56327: Conservatively do not
+            // attempt to report occurrences of `dyn` within
+            // macro definitions or invocations, because `dyn`
+            // can legitimately occur as a contextual keyword
+            // in 2015 code denoting its 2018 meaning, and we
+            // do not want rustfix to inject bugs into working
+            // code by rewriting such occurrences.
+            //
+            // But if we see `dyn` outside of a macro, we know
+            // its precise role in the parsed AST and thus are
+            // assured this is truly an attempt to use it as
+            // an identifier.
+            kw::Dyn if !under_macro => (KEYWORD_IDENTS_2018, Edition::Edition2018),
+
+            kw::Gen => (KEYWORD_IDENTS_2024, Edition::Edition2024),
 
-            // There are no new keywords yet for the 2018 edition and beyond.
             _ => return,
         };
 
         // Don't lint `r#foo`.
-        if cx.sess().psess.raw_identifier_spans.contains(ident.span) {
+        if ident.span.edition() >= edition
+            || cx.sess().psess.raw_identifier_spans.contains(ident.span)
+        {
             return;
         }
 
         cx.emit_span_lint(
-            KEYWORD_IDENTS,
+            lint,
             ident.span,
-            BuiltinKeywordIdents { kw: ident, next: next_edition, suggestion: ident.span },
+            BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span },
         );
     }
 }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 64ef30039a8..d1dcfc524b5 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -741,7 +741,7 @@ impl<'tcx> LateContext<'tcx> {
                 .filter(|typeck_results| typeck_results.hir_owner == id.owner)
                 .or_else(|| {
                     self.tcx
-                        .has_typeck_results(id.owner.to_def_id())
+                        .has_typeck_results(id.owner.def_id)
                         .then(|| self.tcx.typeck(id.owner.def_id))
                 })
                 .and_then(|typeck_results| typeck_results.type_dependent_def(id))
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index b2403836397..8458b539335 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -2,7 +2,7 @@
 #![allow(rustc::untranslatable_diagnostic)]
 
 use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
-use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag};
+use rustc_errors::{elided_lifetime_in_path_suggestion, Diag};
 use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_middle::middle::stability;
 use rustc_session::lint::BuiltinLintDiag;
@@ -74,13 +74,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
             diag.span_note(span_def, "the macro is defined here");
         }
         BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
-            add_elided_lifetime_in_path_suggestion(
-                sess.source_map(),
-                diag,
-                n,
-                path_span,
-                incl_angl_brckt,
-                insertion_span,
+            diag.subdiagnostic(
+                sess.dcx(),
+                elided_lifetime_in_path_suggestion(
+                    sess.source_map(),
+                    n,
+                    path_span,
+                    incl_angl_brckt,
+                    insertion_span,
+                ),
             );
         }
         BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => {
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index ee99e824a54..c23d1221bc8 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -27,7 +27,7 @@ impl Subdiagnostic for OverruledAttributeSub {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         match self {
             OverruledAttributeSub::DefaultSource { id } => {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 086c3834410..e00d8c1e6bd 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -312,6 +312,8 @@ fn register_builtins(store: &mut LintStore) {
                                        // MACRO_USE_EXTERN_CRATE
     );
 
+    add_lint_group!("keyword_idents", KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024);
+
     add_lint_group!(
         "refining_impl_trait",
         REFINING_IMPL_TRAIT_REACHABLE,
@@ -324,7 +326,7 @@ fn register_builtins(store: &mut LintStore) {
     store.register_renamed("bare_trait_object", "bare_trait_objects");
     store.register_renamed("unstable_name_collision", "unstable_name_collisions");
     store.register_renamed("unused_doc_comment", "unused_doc_comments");
-    store.register_renamed("async_idents", "keyword_idents");
+    store.register_renamed("async_idents", "keyword_idents_2018");
     store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
     store.register_renamed("redundant_semicolon", "redundant_semicolons");
     store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index a034bebc85e..74a0a224dba 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -274,7 +274,7 @@ impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         // Access to associates types should use `<T as Bound>::Assoc`, which does not need a
         // bound. Let's see if this type does that.
@@ -330,7 +330,7 @@ impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         diag.multipart_suggestion(
             fluent::lint_suggestion,
@@ -451,7 +451,7 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         let mut err = self.err;
         loop {
@@ -506,7 +506,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         let mut expected_str = DiagStyledString::new();
         expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
@@ -788,7 +788,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         for (c, span) in self.spans {
             diag.span_label(span, format!("{c:?}"));
@@ -806,7 +806,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         match self {
             HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
@@ -954,7 +954,7 @@ impl Subdiagnostic for NonBindingLetSub {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
 
@@ -1240,7 +1240,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         match self {
             NonSnakeCaseDiagSub::Label { span } => {
@@ -1482,7 +1482,7 @@ impl Subdiagnostic for OverflowingBinHexSign {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         match self {
             OverflowingBinHexSign::Positive => {
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index a2d07fff506..e81790a7348 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
 
                 if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
                     || Some(def_id) == cx.tcx.lang_items().panic_fn()
-                    || f_diagnostic_name == Some(sym::panic_str)
+                    || f_diagnostic_name == Some(sym::panic_str_2015)
                 {
                     if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
                         if matches!(
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index ced782cdbc0..45236771bce 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -71,6 +71,7 @@ impl SubdiagnosticDerive {
                     span_field: None,
                     applicability: None,
                     has_suggestion_parts: false,
+                    has_subdiagnostic: false,
                     is_enum,
                 };
                 builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
@@ -90,7 +91,7 @@ impl SubdiagnosticDerive {
                 fn add_to_diag_with<__G, __F>(
                     self,
                     #diag: &mut rustc_errors::Diag<'_, __G>,
-                    #f: __F
+                    #f: &__F
                 ) where
                     __G: rustc_errors::EmissionGuarantee,
                     __F: rustc_errors::SubdiagMessageOp<__G>,
@@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
     /// during finalization if still `false`.
     has_suggestion_parts: bool,
 
+    /// Set to true when a `#[subdiagnostic]` field is encountered, used to suppress the error
+    /// emitted when no subdiagnostic kinds are specified on the variant itself.
+    has_subdiagnostic: bool,
+
     /// Set to true when this variant is an enum variant rather than just the body of a struct.
     is_enum: bool,
 }
@@ -373,6 +378,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
 
                 Ok(quote! {})
             }
+            "subdiagnostic" => {
+                let f = &self.parent.f;
+                let diag = &self.parent.diag;
+                let binding = &info.binding;
+                self.has_subdiagnostic = true;
+                Ok(quote! { #binding.add_to_diag_with(#diag, #f); })
+            }
             _ => {
                 let mut span_attrs = vec![];
                 if kind_stats.has_multipart_suggestion {
@@ -480,18 +492,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
 
     pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
         let kind_slugs = self.identify_kind()?;
-        if kind_slugs.is_empty() {
-            if self.is_enum {
-                // It's okay for a variant to not be a subdiagnostic at all..
-                return Ok(quote! {});
-            } else {
-                // ..but structs should always be _something_.
-                throw_span_err!(
-                    self.variant.ast().ident.span().unwrap(),
-                    "subdiagnostic kind not specified"
-                );
-            }
-        };
 
         let kind_stats: KindsStatistics =
             kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect();
@@ -510,6 +510,19 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             .map(|binding| self.generate_field_attr_code(binding, kind_stats))
             .collect();
 
+        if kind_slugs.is_empty() {
+            if self.is_enum {
+                // It's okay for a variant to not be a subdiagnostic at all..
+                return Ok(quote! {});
+            } else if !self.has_subdiagnostic {
+                // ..but structs should always be _something_.
+                throw_span_err!(
+                    self.variant.ast().ident.span().unwrap(),
+                    "subdiagnostic kind not specified"
+                );
+            }
+        };
+
         let span_field = self.span_field.value_ref();
 
         let diag = &self.parent.diag;
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index eedc508fb14..c7b7eadbd9d 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -144,6 +144,7 @@ decl_derive!(
         help,
         note,
         warning,
+        subdiagnostic,
         suggestion,
         suggestion_short,
         suggestion_hidden,
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 784fd4b3a3b..888c2427d8f 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -13,10 +13,10 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard};
 use rustc_errors::DiagCtxt;
 use rustc_expand::base::SyntaxExtension;
 use rustc_fs_util::try_canonicalize;
-use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_index::IndexVec;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
 use rustc_session::config::{self, CrateType, ExternLocation};
 use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
 use rustc_session::lint;
@@ -62,9 +62,6 @@ pub struct CStore {
     /// This crate has a `#[alloc_error_handler]` item.
     has_alloc_error_handler: bool,
 
-    /// The interned [StableCrateId]s.
-    pub(crate) stable_crate_ids: StableCrateIdMap,
-
     /// Unused externs of the crate
     unused_externs: Vec<Symbol>,
 }
@@ -165,25 +162,27 @@ impl CStore {
         })
     }
 
-    fn intern_stable_crate_id(&mut self, root: &CrateRoot) -> Result<CrateNum, CrateError> {
-        assert_eq!(self.metas.len(), self.stable_crate_ids.len());
-        let num = CrateNum::new(self.stable_crate_ids.len());
-        if let Some(&existing) = self.stable_crate_ids.get(&root.stable_crate_id()) {
+    fn intern_stable_crate_id<'tcx>(
+        &mut self,
+        root: &CrateRoot,
+        tcx: TyCtxt<'tcx>,
+    ) -> Result<TyCtxtFeed<'tcx, CrateNum>, CrateError> {
+        assert_eq!(self.metas.len(), tcx.untracked().stable_crate_ids.read().len());
+        let num = tcx.create_crate_num(root.stable_crate_id()).map_err(|existing| {
             // Check for (potential) conflicts with the local crate
             if existing == LOCAL_CRATE {
-                Err(CrateError::SymbolConflictsCurrent(root.name()))
+                CrateError::SymbolConflictsCurrent(root.name())
             } else if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name())
             {
                 let crate_name0 = root.name();
-                Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1))
+                CrateError::StableCrateIdCollision(crate_name0, crate_name1)
             } else {
-                Err(CrateError::NotFound(root.name()))
+                CrateError::NotFound(root.name())
             }
-        } else {
-            self.metas.push(None);
-            self.stable_crate_ids.insert(root.stable_crate_id(), num);
-            Ok(num)
-        }
+        })?;
+
+        self.metas.push(None);
+        Ok(num)
     }
 
     pub fn has_crate_data(&self, cnum: CrateNum) -> bool {
@@ -289,12 +288,7 @@ impl CStore {
         }
     }
 
-    pub fn new(
-        metadata_loader: Box<MetadataLoaderDyn>,
-        local_stable_crate_id: StableCrateId,
-    ) -> CStore {
-        let mut stable_crate_ids = StableCrateIdMap::default();
-        stable_crate_ids.insert(local_stable_crate_id, LOCAL_CRATE);
+    pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
         CStore {
             metadata_loader,
             // We add an empty entry for LOCAL_CRATE (which maps to zero) in
@@ -307,7 +301,6 @@ impl CStore {
             alloc_error_handler_kind: None,
             has_global_allocator: false,
             has_alloc_error_handler: false,
-            stable_crate_ids,
             unused_externs: Vec::new(),
         }
     }
@@ -416,7 +409,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         let private_dep = self.is_private_dep(name.as_str(), private_dep);
 
         // Claim this crate number and cache it
-        let cnum = self.cstore.intern_stable_crate_id(&crate_root)?;
+        let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?;
+        let cnum = feed.key();
 
         info!(
             "register crate `{}` (cnum = {}. private_dep = {})",
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 596da58b091..c4ab4eb2657 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1208,7 +1208,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self))
     }
 
-    /// Iterates over the language items in the given crate.
+    /// Iterates over the lang items in the given crate.
     fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
         tcx.arena.alloc_from_iter(
             self.root
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 2935d5b8f63..531b2e05411 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -629,13 +629,6 @@ impl CrateStore for CStore {
         self.get_crate_data(cnum).root.stable_crate_id
     }
 
-    fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum {
-        *self
-            .stable_crate_ids
-            .get(&stable_crate_id)
-            .unwrap_or_else(|| bug!("uninterned StableCrateId: {stable_crate_id:?}"))
-    }
-
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
@@ -657,7 +650,13 @@ fn provide_cstore_hooks(providers: &mut Providers) {
         // If this is a DefPathHash from an upstream crate, let the CrateStore map
         // it to a DefId.
         let cstore = CStore::from_tcx(tcx.tcx);
-        let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
+        let cnum = *tcx
+            .untracked()
+            .stable_crate_ids
+            .read()
+            .get(&stable_crate_id)
+            .unwrap_or_else(|| bug!("uninterned StableCrateId: {stable_crate_id:?}"));
+        assert_ne!(cnum, LOCAL_CRATE);
         let def_index = cstore.get_crate_data(cnum).def_path_hash_to_def_index(hash);
         DefId { krate: cnum, index: def_index }
     };
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index a4e193ba2c9..4fd1c1f4a1b 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -1,4 +1,4 @@
-//! Detecting language items.
+//! Detecting lang items.
 //!
 //! Language items are items that represent concepts intrinsic to the language
 //! itself. Examples are:
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 596271c1e47..6ff40c53c85 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -238,6 +238,20 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
+    /// Determines whether we need to add this const to `required_consts`. This is the case if and
+    /// only if evaluating it may error.
+    #[inline]
+    pub fn is_required_const(&self) -> bool {
+        match self {
+            Const::Ty(c) => match c.kind() {
+                ty::ConstKind::Value(_) => false, // already a value, cannot error
+                _ => true,
+            },
+            Const::Val(..) => false, // already a value, cannot error
+            Const::Unevaluated(..) => true,
+        }
+    }
+
     #[inline]
     pub fn try_to_scalar(self) -> Option<Scalar> {
         match self {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 65ce1cd8f50..a3d16d4f097 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -2,7 +2,7 @@ use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
 
 use crate::error;
 use crate::mir::{ConstAlloc, ConstValue};
-use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
+use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
 
 use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
@@ -344,6 +344,11 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     InvalidFunctionPointer(Pointer<AllocId>),
     /// Using a pointer-not-to-a-vtable as vtable pointer.
     InvalidVTablePointer(Pointer<AllocId>),
+    /// Using a vtable for the wrong trait.
+    InvalidVTableTrait {
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+        vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    },
     /// Using a string that is not valid UTF-8,
     InvalidStr(std::str::Utf8Error),
     /// Using uninitialized data where it is not allowed.
@@ -414,34 +419,86 @@ impl From<PointerKind> for ExpectedKind {
 
 #[derive(Debug)]
 pub enum ValidationErrorKind<'tcx> {
-    PointerAsInt { expected: ExpectedKind },
+    PointerAsInt {
+        expected: ExpectedKind,
+    },
     PartialPointer,
-    PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
-    PtrToStatic { ptr_kind: PointerKind },
+    PtrToUninhabited {
+        ptr_kind: PointerKind,
+        ty: Ty<'tcx>,
+    },
+    PtrToStatic {
+        ptr_kind: PointerKind,
+    },
     ConstRefToMutable,
     ConstRefToExtern,
     MutableRefToImmutable,
     UnsafeCellInImmutable,
     NullFnPtr,
     NeverVal,
-    NullablePtrOutOfRange { range: WrappingRange, max_value: u128 },
-    PtrOutOfRange { range: WrappingRange, max_value: u128 },
-    OutOfRange { value: String, range: WrappingRange, max_value: u128 },
-    UninhabitedVal { ty: Ty<'tcx> },
-    InvalidEnumTag { value: String },
+    NullablePtrOutOfRange {
+        range: WrappingRange,
+        max_value: u128,
+    },
+    PtrOutOfRange {
+        range: WrappingRange,
+        max_value: u128,
+    },
+    OutOfRange {
+        value: String,
+        range: WrappingRange,
+        max_value: u128,
+    },
+    UninhabitedVal {
+        ty: Ty<'tcx>,
+    },
+    InvalidEnumTag {
+        value: String,
+    },
     UninhabitedEnumVariant,
-    Uninit { expected: ExpectedKind },
-    InvalidVTablePtr { value: String },
-    InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
-    InvalidMetaTooLarge { ptr_kind: PointerKind },
-    UnalignedPtr { ptr_kind: PointerKind, required_bytes: u64, found_bytes: u64 },
-    NullPtr { ptr_kind: PointerKind },
-    DanglingPtrNoProvenance { ptr_kind: PointerKind, pointer: String },
-    DanglingPtrOutOfBounds { ptr_kind: PointerKind },
-    DanglingPtrUseAfterFree { ptr_kind: PointerKind },
-    InvalidBool { value: String },
-    InvalidChar { value: String },
-    InvalidFnPtr { value: String },
+    Uninit {
+        expected: ExpectedKind,
+    },
+    InvalidVTablePtr {
+        value: String,
+    },
+    InvalidMetaWrongTrait {
+        expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+        vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    },
+    InvalidMetaSliceTooLarge {
+        ptr_kind: PointerKind,
+    },
+    InvalidMetaTooLarge {
+        ptr_kind: PointerKind,
+    },
+    UnalignedPtr {
+        ptr_kind: PointerKind,
+        required_bytes: u64,
+        found_bytes: u64,
+    },
+    NullPtr {
+        ptr_kind: PointerKind,
+    },
+    DanglingPtrNoProvenance {
+        ptr_kind: PointerKind,
+        pointer: String,
+    },
+    DanglingPtrOutOfBounds {
+        ptr_kind: PointerKind,
+    },
+    DanglingPtrUseAfterFree {
+        ptr_kind: PointerKind,
+    },
+    InvalidBool {
+        value: String,
+    },
+    InvalidChar {
+        value: String,
+    },
+    InvalidFnPtr {
+        value: String,
+    },
 }
 
 /// Error information for when the program did something that might (or might not) be correct
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 7a91d7383e5..a350eb05226 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -985,7 +985,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
             Ref(region, borrow_kind, ref place) => {
                 let kind_str = match borrow_kind {
                     BorrowKind::Shared => "",
-                    BorrowKind::Fake => "fake ",
+                    BorrowKind::Fake(FakeBorrowKind::Deep) => "fake ",
+                    BorrowKind::Fake(FakeBorrowKind::Shallow) => "fake shallow ",
                     BorrowKind::Mut { .. } => "mut ",
                 };
 
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index 069c8019cb2..375f1f15a39 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -237,6 +237,11 @@ impl<'tcx> PlaceRef<'tcx> {
     }
 
     #[inline]
+    pub fn to_place(&self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
+        Place { local: self.local, projection: tcx.mk_place_elems(self.projection) }
+    }
+
+    #[inline]
     pub fn last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> {
         if let &[ref proj_base @ .., elem] = self.projection {
             Some((PlaceRef { local: self.local, projection: proj_base }, elem))
@@ -446,7 +451,7 @@ impl<'tcx> Rvalue<'tcx> {
 impl BorrowKind {
     pub fn mutability(&self) -> Mutability {
         match *self {
-            BorrowKind::Shared | BorrowKind::Fake => Mutability::Not,
+            BorrowKind::Shared | BorrowKind::Fake(_) => Mutability::Not,
             BorrowKind::Mut { .. } => Mutability::Mut,
         }
     }
@@ -454,7 +459,7 @@ impl BorrowKind {
     pub fn allows_two_phase_borrow(&self) -> bool {
         match *self {
             BorrowKind::Shared
-            | BorrowKind::Fake
+            | BorrowKind::Fake(_)
             | BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => {
                 false
             }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index db13bb9a3e8..5ddd71178ca 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -165,13 +165,16 @@ pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
     Shared,
 
-    /// The immediately borrowed place must be immutable, but projections from
-    /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
-    /// conflict with a mutable borrow of `a.b.c`.
+    /// An immutable, aliasable borrow that is discarded after borrow-checking. Can behave either
+    /// like a normal shared borrow or like a special shallow borrow (see [`FakeBorrowKind`]).
     ///
-    /// This is used when lowering matches: when matching on a place we want to
-    /// ensure that place have the same value from the start of the match until
-    /// an arm is selected. This prevents this code from compiling:
+    /// This is used when lowering index expressions and matches. This is used to prevent code like
+    /// the following from compiling:
+    /// ```compile_fail,E0510
+    /// let mut x: &[_] = &[[0, 1]];
+    /// let y: &[_] = &[];
+    /// let _ = x[0][{x = y; 1}];
+    /// ```
     /// ```compile_fail,E0510
     /// let mut x = &Some(0);
     /// match *x {
@@ -180,11 +183,8 @@ pub enum BorrowKind {
     ///     Some(_) => (),
     /// }
     /// ```
-    /// This can't be a shared borrow because mutably borrowing (*x as Some).0
-    /// should not prevent `if let None = x { ... }`, for example, because the
-    /// mutating `(*x as Some).0` can't affect the discriminant of `x`.
     /// We can also report errors with this kind of borrow differently.
-    Fake,
+    Fake(FakeBorrowKind),
 
     /// Data is mutable and not aliasable.
     Mut { kind: MutBorrowKind },
@@ -240,6 +240,57 @@ pub enum MutBorrowKind {
     ClosureCapture,
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Hash, HashStable)]
+pub enum FakeBorrowKind {
+    /// A shared shallow borrow. The immediately borrowed place must be immutable, but projections
+    /// from it don't need to be. For example, a shallow borrow of `a.b` doesn't conflict with a
+    /// mutable borrow of `a.b.c`.
+    ///
+    /// This is used when lowering matches: when matching on a place we want to ensure that place
+    /// have the same value from the start of the match until an arm is selected. This prevents this
+    /// code from compiling:
+    /// ```compile_fail,E0510
+    /// let mut x = &Some(0);
+    /// match *x {
+    ///     None => (),
+    ///     Some(_) if { x = &None; false } => (),
+    ///     Some(_) => (),
+    /// }
+    /// ```
+    /// This can't be a shared borrow because mutably borrowing `(*x as Some).0` should not checking
+    /// the discriminant or accessing other variants, because the mutating `(*x as Some).0` can't
+    /// affect the discriminant of `x`. E.g. the following is allowed:
+    /// ```rust
+    /// let mut x = Some(0);
+    /// match x {
+    ///     Some(_)
+    ///         if {
+    ///             if let Some(ref mut y) = x {
+    ///                 *y += 1;
+    ///             };
+    ///             true
+    ///         } => {}
+    ///     _ => {}
+    /// }
+    /// ```
+    Shallow,
+    /// A shared (deep) borrow. Data must be immutable and is aliasable.
+    ///
+    /// This is used when lowering deref patterns, where shallow borrows wouldn't prevent something
+    /// like:
+    // ```compile_fail
+    // let mut b = Box::new(false);
+    // match b {
+    //     deref!(true) => {} // not reached because `*b == false`
+    //     _ if { *b = true; false } => {} // not reached because the guard is `false`
+    //     deref!(false) => {} // not reached because the guard changed it
+    //     // UB because we reached the unreachable.
+    // }
+    // ```
+    Deep,
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index abe99f3e95c..ded2b93d6a1 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -294,7 +294,7 @@ impl BorrowKind {
 
             // We have no type corresponding to a shallow borrow, so use
             // `&` as an approximation.
-            BorrowKind::Fake => hir::Mutability::Not,
+            BorrowKind::Fake(_) => hir::Mutability::Not,
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index a6d525230b0..d97abc3f190 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -655,7 +655,7 @@ macro_rules! make_mir_visitor {
                             BorrowKind::Shared => PlaceContext::NonMutatingUse(
                                 NonMutatingUseContext::SharedBorrow
                             ),
-                            BorrowKind::Fake => PlaceContext::NonMutatingUse(
+                            BorrowKind::Fake(_) => PlaceContext::NonMutatingUse(
                                 NonMutatingUseContext::FakeBorrow
                             ),
                             BorrowKind::Mut { .. } =>
@@ -1284,6 +1284,8 @@ pub enum NonMutatingUseContext {
     /// Shared borrow.
     SharedBorrow,
     /// A fake borrow.
+    /// FIXME: do we need to distinguish shallow and deep fake borrows? In fact, do we need to
+    /// distinguish fake and normal deep borrows?
     FakeBorrow,
     /// AddressOf for *const pointer.
     AddressOf,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4ae79399ef4..a5d21c47e5b 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -975,10 +975,6 @@ rustc_queries! {
         cache_on_disk_if { true }
     }
 
-    query has_typeck_results(def_id: DefId) -> bool {
-        desc { |tcx| "checking whether `{}` has a body", tcx.def_path_str(def_id) }
-    }
-
     query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) }
         ensure_forwards_result_if_red
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index d52b1efce4b..99498fedcca 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -642,7 +642,7 @@ impl<'tcx> Pat<'tcx> {
             AscribeUserType { subpattern, .. }
             | Binding { subpattern: Some(subpattern), .. }
             | Deref { subpattern }
-            | DerefPattern { subpattern }
+            | DerefPattern { subpattern, .. }
             | InlineConstant { subpattern, .. } => subpattern.walk_(it),
             Leaf { subpatterns } | Variant { subpatterns, .. } => {
                 subpatterns.iter().for_each(|field| field.pattern.walk_(it))
@@ -760,6 +760,7 @@ pub enum PatKind<'tcx> {
     /// Deref pattern, written `box P` for now.
     DerefPattern {
         subpattern: Box<Pat<'tcx>>,
+        mutability: hir::Mutability,
     },
 
     /// One of the following:
@@ -1166,7 +1167,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                 }
                 write!(f, "{subpattern}")
             }
-            PatKind::DerefPattern { ref subpattern } => {
+            PatKind::DerefPattern { ref subpattern, .. } => {
                 write!(f, "deref!({subpattern})")
             }
             PatKind::Constant { value } => write!(f, "{value}"),
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index e42b85530b5..f1988810437 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -229,7 +229,7 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
     match &pat.kind {
         AscribeUserType { subpattern, ascription: _ }
         | Deref { subpattern }
-        | DerefPattern { subpattern }
+        | DerefPattern { subpattern, .. }
         | Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern),
         Binding { .. } | Wild | Never | Error(_) => {}
         Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6275c5d2a11..7dbe59e132d 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -565,13 +565,6 @@ impl<'tcx> TyCtxt<'tcx> {
         TyCtxtFeed { tcx: self, key: () }
     }
 
-    /// Can only be fed before queries are run, and is thus exempt from any
-    /// incremental issues. Do not use except for the initial query feeding.
-    pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
-        self.dep_graph.assert_ignored();
-        TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
-    }
-
     /// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed
     /// some queries for it. It will panic if used twice.
     pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> {
@@ -817,6 +810,17 @@ impl CurrentGcx {
 }
 
 impl<'tcx> TyCtxt<'tcx> {
+    pub fn has_typeck_results(self, def_id: LocalDefId) -> bool {
+        // Closures' typeck results come from their outermost function,
+        // as they are part of the same "inference environment".
+        let typeck_root_def_id = self.typeck_root_def_id(def_id.to_def_id());
+        if typeck_root_def_id != def_id.to_def_id() {
+            return self.has_typeck_results(typeck_root_def_id.expect_local());
+        }
+
+        self.hir_node_by_def_id(def_id).body_id().is_some()
+    }
+
     /// Expects a body and returns its codegen attributes.
     ///
     /// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
@@ -1140,7 +1144,12 @@ impl<'tcx> TyCtxt<'tcx> {
         if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
             LOCAL_CRATE
         } else {
-            self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
+            *self
+                .untracked()
+                .stable_crate_ids
+                .read()
+                .get(&stable_crate_id)
+                .unwrap_or_else(|| bug!("uninterned StableCrateId: {stable_crate_id:?}"))
         }
     }
 
@@ -1256,6 +1265,19 @@ impl<'tcx> TyCtxt<'tcx> {
         feed
     }
 
+    pub fn create_crate_num(
+        self,
+        stable_crate_id: StableCrateId,
+    ) -> Result<TyCtxtFeed<'tcx, CrateNum>, CrateNum> {
+        if let Some(&existing) = self.untracked().stable_crate_ids.read().get(&stable_crate_id) {
+            return Err(existing);
+        }
+
+        let num = CrateNum::new(self.untracked().stable_crate_ids.read().len());
+        self.untracked().stable_crate_ids.write().insert(stable_crate_id, num);
+        Ok(TyCtxtFeed { key: num, tcx: self })
+    }
+
     pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
         // Create a dependency to the red node to be sure we re-execute this when the amount of
         // definitions change.
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index cc1d6e50f6d..8c3ee6955f5 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -279,24 +279,29 @@ pub fn suggest_constraining_type_params<'a>(
         constraint.sort();
         constraint.dedup();
         let constraint = constraint.join(" + ");
-        let mut suggest_restrict = |span, bound_list_non_empty| {
-            suggestions.push((
-                span,
-                if span_to_replace.is_some() {
-                    constraint.clone()
-                } else if constraint.starts_with('<') {
-                    constraint.to_string()
-                } else if bound_list_non_empty {
-                    format!(" + {constraint}")
-                } else {
-                    format!(" {constraint}")
-                },
-                SuggestChangingConstraintsMessage::RestrictBoundFurther,
-            ))
+        let mut suggest_restrict = |span, bound_list_non_empty, open_paren_sp| {
+            let suggestion = if span_to_replace.is_some() {
+                constraint.clone()
+            } else if constraint.starts_with('<') {
+                constraint.to_string()
+            } else if bound_list_non_empty {
+                format!(" + {constraint}")
+            } else {
+                format!(" {constraint}")
+            };
+
+            use SuggestChangingConstraintsMessage::RestrictBoundFurther;
+
+            if let Some(open_paren_sp) = open_paren_sp {
+                suggestions.push((open_paren_sp, "(".to_string(), RestrictBoundFurther));
+                suggestions.push((span, format!("){suggestion}"), RestrictBoundFurther));
+            } else {
+                suggestions.push((span, suggestion, RestrictBoundFurther));
+            }
         };
 
         if let Some(span) = span_to_replace {
-            suggest_restrict(span, true);
+            suggest_restrict(span, true, None);
             continue;
         }
 
@@ -327,8 +332,8 @@ pub fn suggest_constraining_type_params<'a>(
         //          --
         //          |
         //          replace with: `T: Bar +`
-        if let Some(span) = generics.bounds_span_for_suggestions(param.def_id) {
-            suggest_restrict(span, true);
+        if let Some((span, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
+            suggest_restrict(span, true, open_paren_sp);
             continue;
         }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 6381bd190ac..897d6f5662f 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -338,6 +338,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
                         debug_assert!(tail.has_non_region_param());
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
+                    ty::Error(guar) => {
+                        // Fixes ICE #124031
+                        return Err(tcx.arena.alloc(LayoutError::ReferencesError(*guar)));
+                    }
                     _ => bug!(
                         "SizeSkeleton::compute({ty}): layout errored ({err:?}), yet \
                               tail `{tail}` is not a type parameter or a projection",
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index a28afcc4fb8..0c4409197bb 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -7,10 +7,8 @@ use crate::{
         GenericArgs, GenericArgsRef, Ty, UserArgs,
     },
 };
-use rustc_data_structures::{
-    fx::FxIndexMap,
-    unord::{ExtendUnord, UnordItems, UnordSet},
-};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::{
     self as hir,
@@ -201,8 +199,7 @@ pub struct TypeckResults<'tcx> {
 
     /// Stores the predicates that apply on coroutine witness types.
     /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
-    pub coroutine_interior_predicates:
-        LocalDefIdMap<Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
+    pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
 
     /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
     /// as `&[u8]`, depending on the pattern in which they are used.
@@ -243,7 +240,7 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_min_captures: Default::default(),
             closure_fake_reads: Default::default(),
             rvalue_scopes: Default::default(),
-            coroutine_interior_predicates: Default::default(),
+            coroutine_stalled_predicates: Default::default(),
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
             offset_of_data: Default::default(),
@@ -451,7 +448,7 @@ impl<'tcx> TypeckResults<'tcx> {
     /// This is computed from the typeck results since we want to make
     /// sure to apply any match-ergonomics adjustments, which we cannot
     /// determine from the HIR alone.
-    pub fn pat_has_ref_mut_binding(&self, pat: &'tcx hir::Pat<'tcx>) -> bool {
+    pub fn pat_has_ref_mut_binding(&self, pat: &hir::Pat<'_>) -> bool {
         let mut has_ref_mut = false;
         pat.walk(|pat| {
             if let hir::PatKind::Binding(_, id, _, _) = pat.kind
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index f12e25db6fc..060b328ef48 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -685,7 +685,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             fake_borrow_temp.into(),
                             Rvalue::Ref(
                                 tcx.lifetimes.re_erased,
-                                BorrowKind::Fake,
+                                BorrowKind::Fake(FakeBorrowKind::Shallow),
                                 Place { local: base_place.local, projection },
                             ),
                         );
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index f46dceeeedf..d36c51f4472 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -10,10 +10,7 @@ use crate::build::scope::DropKind;
 use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
-use rustc_data_structures::{
-    fx::{FxHashSet, FxIndexMap, FxIndexSet},
-    stack::ensure_sufficient_stack,
-};
+use rustc_data_structures::{fx::FxIndexMap, stack::ensure_sufficient_stack};
 use rustc_hir::{BindingMode, ByRef};
 use rustc_middle::middle::region;
 use rustc_middle::mir::{self, *};
@@ -211,7 +208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// 2. Create the decision tree ([Builder::lower_match_tree]).
     /// 3. Determine the fake borrows that are needed from the places that were
     ///    matched against and create the required temporaries for them
-    ///    ([Builder::calculate_fake_borrows]).
+    ///    ([util::collect_fake_borrows]).
     /// 4. Create everything else: the guards and the arms ([Builder::lower_match_arms]).
     ///
     /// ## False edges
@@ -380,12 +377,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match_start_span: Span,
         match_has_guard: bool,
         candidates: &mut [&mut Candidate<'pat, 'tcx>],
-    ) -> Vec<(Place<'tcx>, Local)> {
-        // The set of places that we are creating fake borrows of. If there are
-        // no match guards then we don't need any fake borrows, so don't track
-        // them.
-        let fake_borrows = match_has_guard
-            .then(|| util::FakeBorrowCollector::collect_fake_borrows(self, candidates));
+    ) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
+        // The set of places that we are creating fake borrows of. If there are no match guards then
+        // we don't need any fake borrows, so don't track them.
+        let fake_borrows: Vec<(Place<'tcx>, Local, FakeBorrowKind)> = if match_has_guard {
+            util::collect_fake_borrows(
+                self,
+                candidates,
+                scrutinee_span,
+                scrutinee_place_builder.base(),
+            )
+        } else {
+            Vec::new()
+        };
 
         // See the doc comment on `match_candidates` for why we have an
         // otherwise block. Match checking will ensure this is actually
@@ -439,11 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             });
         }
 
-        if let Some(ref borrows) = fake_borrows {
-            self.calculate_fake_borrows(borrows, scrutinee_span)
-        } else {
-            Vec::new()
-        }
+        fake_borrows
     }
 
     /// Lower the bindings, guards and arm bodies of a `match` expression.
@@ -459,7 +459,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         scrutinee_span: Span,
         arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>,
         outer_source_info: SourceInfo,
-        fake_borrow_temps: Vec<(Place<'tcx>, Local)>,
+        fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
     ) -> BlockAnd<()> {
         let arm_end_blocks: Vec<_> = arm_candidates
             .into_iter()
@@ -543,7 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         outer_source_info: SourceInfo,
         candidate: Candidate<'_, 'tcx>,
-        fake_borrow_temps: &[(Place<'tcx>, Local)],
+        fake_borrow_temps: &[(Place<'tcx>, Local, FakeBorrowKind)],
         scrutinee_span: Span,
         arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
         storages_alive: bool,
@@ -940,7 +940,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f);
             }
 
-            PatKind::DerefPattern { ref subpattern } => {
+            PatKind::DerefPattern { ref subpattern, .. } => {
                 self.visit_primary_bindings(subpattern, UserTypeProjections::none(), f);
             }
 
@@ -1165,6 +1165,7 @@ enum TestCase<'pat, 'tcx> {
     Constant { value: mir::Const<'tcx> },
     Range(&'pat PatRange<'tcx>),
     Slice { len: usize, variable_length: bool },
+    Deref { temp: Place<'tcx>, mutability: Mutability },
     Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
 }
 
@@ -1224,6 +1225,13 @@ enum TestKind<'tcx> {
 
     /// Test that the length of the slice is equal to `len`.
     Len { len: u64, op: BinOp },
+
+    /// Call `Deref::deref[_mut]` on the value.
+    Deref {
+        /// Temporary to store the result of `deref()`/`deref_mut()`.
+        temp: Place<'tcx>,
+        mutability: Mutability,
+    },
 }
 
 /// A test to perform to determine which [`Candidate`] matches a value.
@@ -1905,81 +1913,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             target_blocks,
         );
     }
-
-    /// Determine the fake borrows that are needed from a set of places that
-    /// have to be stable across match guards.
-    ///
-    /// Returns a list of places that need a fake borrow and the temporary
-    /// that's used to store the fake borrow.
-    ///
-    /// Match exhaustiveness checking is not able to handle the case where the
-    /// place being matched on is mutated in the guards. We add "fake borrows"
-    /// to the guards that prevent any mutation of the place being matched.
-    /// There are a some subtleties:
-    ///
-    /// 1. Borrowing `*x` doesn't prevent assigning to `x`. If `x` is a shared
-    ///    reference, the borrow isn't even tracked. As such we have to add fake
-    ///    borrows of any prefixes of a place
-    /// 2. We don't want `match x { _ => (), }` to conflict with mutable
-    ///    borrows of `x`, so we only add fake borrows for places which are
-    ///    bound or tested by the match.
-    /// 3. We don't want the fake borrows to conflict with `ref mut` bindings,
-    ///    so we use a special BorrowKind for them.
-    /// 4. The fake borrows may be of places in inactive variants, so it would
-    ///    be UB to generate code for them. They therefore have to be removed
-    ///    by a MIR pass run after borrow checking.
-    fn calculate_fake_borrows<'b>(
-        &mut self,
-        fake_borrows: &'b FxIndexSet<Place<'tcx>>,
-        temp_span: Span,
-    ) -> Vec<(Place<'tcx>, Local)> {
-        let tcx = self.tcx;
-
-        debug!("add_fake_borrows fake_borrows = {:?}", fake_borrows);
-
-        let mut all_fake_borrows = Vec::with_capacity(fake_borrows.len());
-
-        // Insert a Shallow borrow of the prefixes of any fake borrows.
-        for place in fake_borrows {
-            let mut cursor = place.projection.as_ref();
-            while let [proj_base @ .., elem] = cursor {
-                cursor = proj_base;
-
-                if let ProjectionElem::Deref = elem {
-                    // Insert a shallow borrow after a deref. For other
-                    // projections the borrow of prefix_cursor will
-                    // conflict with any mutation of base.
-                    all_fake_borrows.push(PlaceRef { local: place.local, projection: proj_base });
-                }
-            }
-
-            all_fake_borrows.push(place.as_ref());
-        }
-
-        // Deduplicate
-        let mut dedup = FxHashSet::default();
-        all_fake_borrows.retain(|b| dedup.insert(*b));
-
-        debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
-
-        all_fake_borrows
-            .into_iter()
-            .map(|matched_place_ref| {
-                let matched_place = Place {
-                    local: matched_place_ref.local,
-                    projection: tcx.mk_place_elems(matched_place_ref.projection),
-                };
-                let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
-                let fake_borrow_ty =
-                    Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty);
-                let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span);
-                fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow));
-                let fake_borrow_temp = self.local_decls.push(fake_borrow_temp);
-
-                (matched_place, fake_borrow_temp)
-            })
-            .collect()
-    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -2044,7 +1977,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         candidate: Candidate<'pat, 'tcx>,
         parent_data: &[PatternExtraData<'tcx>],
-        fake_borrows: &[(Place<'tcx>, Local)],
+        fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)],
         scrutinee_span: Span,
         arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
         schedule_drops: bool,
@@ -2174,8 +2107,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             let re_erased = tcx.lifetimes.re_erased;
             let scrutinee_source_info = self.source_info(scrutinee_span);
-            for &(place, temp) in fake_borrows {
-                let borrow = Rvalue::Ref(re_erased, BorrowKind::Fake, place);
+            for &(place, temp, kind) in fake_borrows {
+                let borrow = Rvalue::Ref(re_erased, BorrowKind::Fake(kind), place);
                 self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
             }
 
@@ -2198,7 +2131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let guard_frame = self.guard_context.pop().unwrap();
             debug!("Exiting guard building context with locals: {:?}", guard_frame);
 
-            for &(_, temp) in fake_borrows {
+            for &(_, temp, _) in fake_borrows {
                 let cause = FakeReadCause::ForMatchGuard;
                 self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(temp));
             }
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 690879b9488..5dd478aa422 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -42,6 +42,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 TestKind::Len { len: len as u64, op }
             }
 
+            TestCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability },
+
             TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
 
             TestCase::Irrefutable { .. } => span_bug!(
@@ -143,34 +145,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         );
                     }
                     let re_erased = tcx.lifetimes.re_erased;
-                    let ref_string = self.temp(Ty::new_imm_ref(tcx, re_erased, ty), test.span);
                     let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
                     let ref_str = self.temp(ref_str_ty, test.span);
-                    let deref = tcx.require_lang_item(LangItem::Deref, None);
-                    let method = trait_method(tcx, deref, sym::deref, [ty]);
                     let eq_block = self.cfg.start_new_block();
-                    self.cfg.push_assign(
-                        block,
-                        source_info,
-                        ref_string,
-                        Rvalue::Ref(re_erased, BorrowKind::Shared, place),
-                    );
-                    self.cfg.terminate(
+                    // `let ref_str: &str = <String as Deref>::deref(&place);`
+                    self.call_deref(
                         block,
-                        source_info,
-                        TerminatorKind::Call {
-                            func: Operand::Constant(Box::new(ConstOperand {
-                                span: test.span,
-                                user_ty: None,
-                                const_: method,
-                            })),
-                            args: vec![Spanned { node: Operand::Move(ref_string), span: DUMMY_SP }],
-                            destination: ref_str,
-                            target: Some(eq_block),
-                            unwind: UnwindAction::Continue,
-                            call_source: CallSource::Misc,
-                            fn_span: source_info.span,
-                        },
+                        eq_block,
+                        place,
+                        Mutability::Not,
+                        ty,
+                        ref_str,
+                        test.span,
                     );
                     self.non_scalar_compare(
                         eq_block,
@@ -270,9 +256,66 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Operand::Move(expected),
                 );
             }
+
+            TestKind::Deref { temp, mutability } => {
+                let ty = place_ty.ty;
+                let target = target_block(TestBranch::Success);
+                self.call_deref(block, target, place, mutability, ty, temp, test.span);
+            }
         }
     }
 
+    /// Perform `let temp = <ty as Deref>::deref(&place)`.
+    /// or `let temp = <ty as DerefMut>::deref_mut(&mut place)`.
+    pub(super) fn call_deref(
+        &mut self,
+        block: BasicBlock,
+        target_block: BasicBlock,
+        place: Place<'tcx>,
+        mutability: Mutability,
+        ty: Ty<'tcx>,
+        temp: Place<'tcx>,
+        span: Span,
+    ) {
+        let (trait_item, method) = match mutability {
+            Mutability::Not => (LangItem::Deref, sym::deref),
+            Mutability::Mut => (LangItem::DerefMut, sym::deref_mut),
+        };
+        let borrow_kind = super::util::ref_pat_borrow_kind(mutability);
+        let source_info = self.source_info(span);
+        let re_erased = self.tcx.lifetimes.re_erased;
+        let trait_item = self.tcx.require_lang_item(trait_item, None);
+        let method = trait_method(self.tcx, trait_item, method, [ty]);
+        let ref_src = self.temp(Ty::new_ref(self.tcx, re_erased, ty, mutability), span);
+        // `let ref_src = &src_place;`
+        // or `let ref_src = &mut src_place;`
+        self.cfg.push_assign(
+            block,
+            source_info,
+            ref_src,
+            Rvalue::Ref(re_erased, borrow_kind, place),
+        );
+        // `let temp = <Ty as Deref>::deref(ref_src);`
+        // or `let temp = <Ty as DerefMut>::deref_mut(ref_src);`
+        self.cfg.terminate(
+            block,
+            source_info,
+            TerminatorKind::Call {
+                func: Operand::Constant(Box::new(ConstOperand {
+                    span,
+                    user_ty: None,
+                    const_: method,
+                })),
+                args: vec![Spanned { node: Operand::Move(ref_src), span }],
+                destination: temp,
+                target: Some(target_block),
+                unwind: UnwindAction::Continue,
+                call_source: CallSource::Misc,
+                fn_span: source_info.span,
+            },
+        );
+    }
+
     /// Compare using the provided built-in comparison operator
     fn compare(
         &mut self,
@@ -660,13 +703,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
 
+            (TestKind::Deref { temp: test_temp, .. }, TestCase::Deref { temp, .. })
+                if test_temp == temp =>
+            {
+                fully_matched = true;
+                Some(TestBranch::Success)
+            }
+
             (
                 TestKind::Switch { .. }
                 | TestKind::SwitchInt { .. }
                 | TestKind::If
                 | TestKind::Len { .. }
                 | TestKind::Range { .. }
-                | TestKind::Eq { .. },
+                | TestKind::Eq { .. }
+                | TestKind::Deref { .. },
                 _,
             ) => {
                 fully_matched = false;
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index d6376b7b0dc..2f9390c22a8 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -1,12 +1,13 @@
 use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
 use crate::build::matches::{Binding, Candidate, FlatPat, MatchPair, TestCase};
 use crate::build::Builder;
-use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{self, *};
-use rustc_middle::ty;
 use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::{self, Ty};
+use rustc_span::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn field_match_pairs<'pat>(
@@ -249,10 +250,15 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                 default_irrefutable()
             }
 
-            PatKind::DerefPattern { .. } => {
-                // FIXME(deref_patterns)
-                // Treat it like a wildcard for now.
-                default_irrefutable()
+            PatKind::DerefPattern { ref subpattern, mutability } => {
+                // Create a new temporary for each deref pattern.
+                // FIXME(deref_patterns): dedup temporaries to avoid multiple `deref()` calls?
+                let temp = cx.temp(
+                    Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, subpattern.ty, mutability),
+                    pattern.span,
+                );
+                subpairs.push(MatchPair::new(PlaceBuilder::from(temp).deref(), subpattern, cx));
+                TestCase::Deref { temp, mutability }
             }
         };
 
@@ -262,19 +268,103 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
 
 pub(super) struct FakeBorrowCollector<'a, 'b, 'tcx> {
     cx: &'a mut Builder<'b, 'tcx>,
-    fake_borrows: FxIndexSet<Place<'tcx>>,
+    /// Base of the scrutinee place. Used to distinguish bindings inside the scrutinee place from
+    /// bindings inside deref patterns.
+    scrutinee_base: PlaceBase,
+    /// Store for each place the kind of borrow to take. In case of conflicts, we take the strongest
+    /// borrow (i.e. Deep > Shallow).
+    /// Invariant: for any place in `fake_borrows`, all the prefixes of this place that are
+    /// dereferences are also borrowed with the same of stronger borrow kind.
+    fake_borrows: FxIndexMap<Place<'tcx>, FakeBorrowKind>,
+}
+
+/// Determine the set of places that have to be stable across match guards.
+///
+/// Returns a list of places that need a fake borrow along with a local to store it.
+///
+/// Match exhaustiveness checking is not able to handle the case where the place being matched on is
+/// mutated in the guards. We add "fake borrows" to the guards that prevent any mutation of the
+/// place being matched. There are a some subtleties:
+///
+/// 1. Borrowing `*x` doesn't prevent assigning to `x`. If `x` is a shared reference, the borrow
+///    isn't even tracked. As such we have to add fake borrows of any prefixes of a place.
+/// 2. We don't want `match x { (Some(_), _) => (), .. }` to conflict with mutable borrows of `x.1`, so we
+///    only add fake borrows for places which are bound or tested by the match.
+/// 3. We don't want `match x { Some(_) => (), .. }` to conflict with mutable borrows of `(x as
+///    Some).0`, so the borrows are a special shallow borrow that only affects the place and not its
+///    projections.
+///    ```rust
+///    let mut x = (Some(0), true);
+///    match x {
+///        (Some(_), false) => {}
+///        _ if { if let Some(ref mut y) = x.0 { *y += 1 }; true } => {}
+///        _ => {}
+///    }
+///    ```
+/// 4. The fake borrows may be of places in inactive variants, e.g. here we need to fake borrow `x`
+///    and `(x as Some).0`, but when we reach the guard `x` may not be `Some`.
+///    ```rust
+///    let mut x = (Some(Some(0)), true);
+///    match x {
+///        (Some(Some(_)), false) => {}
+///        _ if { if let Some(Some(ref mut y)) = x.0 { *y += 1 }; true } => {}
+///        _ => {}
+///    }
+///    ```
+///    So it would be UB to generate code for the fake borrows. They therefore have to be removed by
+///    a MIR pass run after borrow checking.
+pub(super) fn collect_fake_borrows<'tcx>(
+    cx: &mut Builder<'_, 'tcx>,
+    candidates: &[&mut Candidate<'_, 'tcx>],
+    temp_span: Span,
+    scrutinee_base: PlaceBase,
+) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
+    let mut collector =
+        FakeBorrowCollector { cx, scrutinee_base, fake_borrows: FxIndexMap::default() };
+    for candidate in candidates.iter() {
+        collector.visit_candidate(candidate);
+    }
+    let fake_borrows = collector.fake_borrows;
+    debug!("add_fake_borrows fake_borrows = {:?}", fake_borrows);
+    let tcx = cx.tcx;
+    fake_borrows
+        .iter()
+        .map(|(matched_place, borrow_kind)| {
+            let fake_borrow_deref_ty = matched_place.ty(&cx.local_decls, tcx).ty;
+            let fake_borrow_ty =
+                Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty);
+            let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span);
+            fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow));
+            let fake_borrow_temp = cx.local_decls.push(fake_borrow_temp);
+            (*matched_place, fake_borrow_temp, *borrow_kind)
+        })
+        .collect()
 }
 
 impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
-    pub(super) fn collect_fake_borrows(
-        cx: &'a mut Builder<'b, 'tcx>,
-        candidates: &[&mut Candidate<'_, 'tcx>],
-    ) -> FxIndexSet<Place<'tcx>> {
-        let mut collector = Self { cx, fake_borrows: FxIndexSet::default() };
-        for candidate in candidates.iter() {
-            collector.visit_candidate(candidate);
+    // Fake borrow this place and its dereference prefixes.
+    fn fake_borrow(&mut self, place: Place<'tcx>, kind: FakeBorrowKind) {
+        if self.fake_borrows.get(&place).is_some_and(|k| *k >= kind) {
+            return;
+        }
+        self.fake_borrows.insert(place, kind);
+        // Also fake borrow the prefixes of any fake borrow.
+        self.fake_borrow_deref_prefixes(place, kind);
+    }
+
+    // Fake borrow the prefixes of this place that are dereferences.
+    fn fake_borrow_deref_prefixes(&mut self, place: Place<'tcx>, kind: FakeBorrowKind) {
+        for (place_ref, elem) in place.as_ref().iter_projections().rev() {
+            if let ProjectionElem::Deref = elem {
+                // Insert a shallow borrow after a deref. For other projections the borrow of
+                // `place_ref` will conflict with any mutation of `place.base`.
+                let place = place_ref.to_place(self.cx.tcx);
+                if self.fake_borrows.get(&place).is_some_and(|k| *k >= kind) {
+                    return;
+                }
+                self.fake_borrows.insert(place, kind);
+            }
         }
-        collector.fake_borrows
     }
 
     fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
@@ -300,10 +390,27 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
             for flat_pat in pats.iter() {
                 self.visit_flat_pat(flat_pat)
             }
+        } else if matches!(match_pair.test_case, TestCase::Deref { .. }) {
+            // The subpairs of a deref pattern are all places relative to the deref temporary, so we
+            // don't fake borrow them. Problem is, if we only shallowly fake-borrowed
+            // `match_pair.place`, this would allow:
+            // ```
+            // let mut b = Box::new(false);
+            // match b {
+            //     deref!(true) => {} // not reached because `*b == false`
+            //     _ if { *b = true; false } => {} // not reached because the guard is `false`
+            //     deref!(false) => {} // not reached because the guard changed it
+            //     // UB because we reached the unreachable.
+            // }
+            // ```
+            // Hence we fake borrow using a deep borrow.
+            if let Some(place) = match_pair.place {
+                self.fake_borrow(place, FakeBorrowKind::Deep);
+            }
         } else {
             // Insert a Shallow borrow of any place that is switched on.
             if let Some(place) = match_pair.place {
-                self.fake_borrows.insert(place);
+                self.fake_borrow(place, FakeBorrowKind::Shallow);
             }
 
             for subpair in &match_pair.subpairs {
@@ -313,6 +420,14 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_binding(&mut self, Binding { source, .. }: &Binding<'tcx>) {
+        if let PlaceBase::Local(l) = self.scrutinee_base
+            && l != source.local
+        {
+            // The base of this place is a temporary created for deref patterns. We don't emit fake
+            // borrows for these as they are not initialized in all branches.
+            return;
+        }
+
         // Insert a borrows of prefixes of places that are bound and are
         // behind a dereference projection.
         //
@@ -329,13 +444,13 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
         //     y if { y == 1 && (x = &2) == () } => y,
         //     _ => 3,
         // }
-        if let Some(i) = source.projection.iter().rposition(|elem| elem == ProjectionElem::Deref) {
-            let proj_base = &source.projection[..i];
-            self.fake_borrows.insert(Place {
-                local: source.local,
-                projection: self.cx.tcx.mk_place_elems(proj_base),
-            });
-        }
+        //
+        // We don't just fake borrow the whole place because this is allowed:
+        // match u {
+        //     _ if { u = true; false } => (),
+        //     x => (),
+        // }
+        self.fake_borrow_deref_prefixes(*source, FakeBorrowKind::Shallow);
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 0c1e1d59c4f..227d19c3e43 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -513,7 +513,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 visit::walk_expr(&mut visitor, expr);
                 if visitor.found {
                     match borrow_kind {
-                        BorrowKind::Fake | BorrowKind::Shared
+                        BorrowKind::Fake(_) | BorrowKind::Shared
                             if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
                         {
                             self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
@@ -521,7 +521,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                         BorrowKind::Mut { .. } => {
                             self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField)
                         }
-                        BorrowKind::Fake | BorrowKind::Shared => {}
+                        BorrowKind::Fake(_) | BorrowKind::Shared => {}
                     }
                 }
             }
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 9ddfb12bf76..f67113afd6d 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -423,7 +423,7 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
         let body_start = self.body_span.shrink_to_lo();
@@ -871,7 +871,7 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         diag.arg("ty", self.ty);
         let mut spans = MultiSpan::from(self.adt_def_span);
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index bcb43a00547..5c016682d8d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -264,7 +264,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
 
             hir::PatKind::Deref(subpattern) => {
-                PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern) }
+                let mutable = self.typeck_results.pat_has_ref_mut_binding(subpattern);
+                let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+                PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), mutability }
             }
             hir::PatKind::Ref(subpattern, _) | hir::PatKind::Box(subpattern) => {
                 PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 49e48427b65..619bfbcf43d 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -688,7 +688,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 self.print_pat(subpattern, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
-            PatKind::DerefPattern { subpattern } => {
+            PatKind::DerefPattern { subpattern, .. } => {
                 print_indented!(self, "DerefPattern { ", depth_lvl + 1);
                 print_indented!(self, "subpattern:", depth_lvl + 2);
                 self.print_pat(subpattern, depth_lvl + 2);
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 693994b5da7..bdc70de58e8 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -102,7 +102,7 @@ where
             }
 
             Rvalue::Cast(..)
-            | Rvalue::Ref(_, BorrowKind::Fake, _)
+            | Rvalue::Ref(_, BorrowKind::Fake(_), _)
             | Rvalue::ShallowInitBox(..)
             | Rvalue::Use(..)
             | Rvalue::ThreadLocalRef(..)
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index da82f8de781..48a6a83e146 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -29,7 +29,7 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
             for statement in basic_block.statements.iter_mut() {
                 match statement.kind {
                     StatementKind::AscribeUserType(..)
-                    | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _)))
+                    | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake(_), _)))
                     | StatementKind::Coverage(
                         // These kinds of coverage statements are markers inserted during
                         // MIR building, and are not needed after InstrumentCoverage.
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index e2a911f0dc7..b745d97567d 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -80,6 +80,10 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_target::spec::PanicStrategy;
+use rustc_trait_selection::infer::TyCtxtInferExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 use std::{iter, ops};
 
 pub struct StateTransform;
@@ -1584,10 +1588,46 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>(
     let (_, coroutine_layout, _) = compute_layout(liveness_info, body);
 
     check_suspend_tys(tcx, &coroutine_layout, body);
+    check_field_tys_sized(tcx, &coroutine_layout, def_id);
 
     Some(coroutine_layout)
 }
 
+fn check_field_tys_sized<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    coroutine_layout: &CoroutineLayout<'tcx>,
+    def_id: LocalDefId,
+) {
+    // No need to check if unsized_locals/unsized_fn_params is disabled,
+    // since we will error during typeck.
+    if !tcx.features().unsized_locals && !tcx.features().unsized_fn_params {
+        return;
+    }
+
+    let infcx = tcx.infer_ctxt().ignoring_regions().build();
+    let param_env = tcx.param_env(def_id);
+
+    let ocx = ObligationCtxt::new(&infcx);
+    for field_ty in &coroutine_layout.field_tys {
+        ocx.register_bound(
+            ObligationCause::new(
+                field_ty.source_info.span,
+                def_id,
+                ObligationCauseCode::SizedCoroutineInterior(def_id),
+            ),
+            param_env,
+            field_ty.ty,
+            tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)),
+        );
+    }
+
+    let errors = ocx.select_all_or_error();
+    debug!(?errors);
+    if !errors.is_empty() {
+        infcx.err_ctxt().report_fulfillment_errors(errors);
+    }
+}
+
 impl<'tcx> MirPass<'tcx> for StateTransform {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let Some(old_yield_ty) = body.yield_ty() else {
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index ca63f5550ae..370e930b740 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -160,7 +160,7 @@ pub fn deduced_param_attrs<'tcx>(
         return &[];
     }
 
-    // If the Freeze language item isn't present, then don't bother.
+    // If the Freeze lang item isn't present, then don't bother.
     if tcx.lang_items().freeze_trait().is_none() {
         return &[];
     }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 7dcff458ced..7a3b08f82f6 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -720,18 +720,12 @@ impl<'tcx> Inliner<'tcx> {
             kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) },
         });
 
-        // Copy only unevaluated constants from the callee_body into the caller_body.
-        // Although we are only pushing `ConstKind::Unevaluated` consts to
-        // `required_consts`, here we may not only have `ConstKind::Unevaluated`
-        // because we are calling `instantiate_and_normalize_erasing_regions`.
-        caller_body.required_consts.extend(callee_body.required_consts.iter().copied().filter(
-            |&ct| match ct.const_ {
-                Const::Ty(_) => {
-                    bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
-                }
-                Const::Val(..) | Const::Unevaluated(..) => true,
-            },
-        ));
+        // Copy required constants from the callee_body into the caller_body. Although we are only
+        // pushing unevaluated consts to `required_consts`, here they may have been evaluated
+        // because we are calling `instantiate_and_normalize_erasing_regions` -- so we filter again.
+        caller_body.required_consts.extend(
+            callee_body.required_consts.into_iter().filter(|ct| ct.const_.is_required_const()),
+        );
         // Now that we incorporated the callee's `required_consts`, we can remove the callee from
         // `mentioned_items` -- but we have to take their `mentioned_items` in return. This does
         // some extra work here to save the monomorphization collector work later. It helps a lot,
@@ -747,8 +741,9 @@ impl<'tcx> Inliner<'tcx> {
             caller_body.mentioned_items.remove(idx);
             caller_body.mentioned_items.extend(callee_body.mentioned_items);
         } else {
-            // If we can't find the callee, there's no point in adding its items.
-            // Probably it already got removed by being inlined elsewhere in the same function.
+            // If we can't find the callee, there's no point in adding its items. Probably it
+            // already got removed by being inlined elsewhere in the same function, so we already
+            // took its items.
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index e477c068229..b308a80f7ba 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -333,6 +333,8 @@ fn mir_promoted(
         body.tainted_by_errors = Some(error_reported);
     }
 
+    // Collect `required_consts` *before* promotion, so if there are any consts being promoted
+    // we still add them to the list in the outer MIR body.
     let mut required_consts = Vec::new();
     let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
     for (bb, bb_data) in traversal::reverse_postorder(&body) {
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 8137525a332..2267a621a83 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -21,7 +21,7 @@ impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls {
 pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let language_items = tcx.lang_items();
     let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
-        // there is no language item to compare to :)
+        // there is no lang item to compare to :)
         return;
     };
 
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 1f4af0ec63d..689a547689a 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -13,6 +13,7 @@
 //! move analysis runs after promotion on broken MIR.
 
 use either::{Left, Right};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_middle::mir;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
@@ -175,6 +176,12 @@ fn collect_temps_and_candidates<'tcx>(
 struct Validator<'a, 'tcx> {
     ccx: &'a ConstCx<'a, 'tcx>,
     temps: &'a mut IndexSlice<Local, TempState>,
+    /// For backwards compatibility, we are promoting function calls in `const`/`static`
+    /// initializers. But we want to avoid evaluating code that might panic and that otherwise would
+    /// not have been evaluated, so we only promote such calls in basic blocks that are guaranteed
+    /// to execute. In other words, we only promote such calls in basic blocks that are definitely
+    /// not dead code. Here we cache the result of computing that set of basic blocks.
+    promotion_safe_blocks: Option<FxHashSet<BasicBlock>>,
 }
 
 impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> {
@@ -260,7 +267,9 @@ impl<'tcx> Validator<'_, 'tcx> {
                     self.validate_rvalue(rhs)
                 }
                 Right(terminator) => match &terminator.kind {
-                    TerminatorKind::Call { func, args, .. } => self.validate_call(func, args),
+                    TerminatorKind::Call { func, args, .. } => {
+                        self.validate_call(func, args, loc.block)
+                    }
                     TerminatorKind::Yield { .. } => Err(Unpromotable),
                     kind => {
                         span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
@@ -384,7 +393,7 @@ impl<'tcx> Validator<'_, 'tcx> {
         match kind {
             // Reject these borrow types just to be safe.
             // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
-            BorrowKind::Fake | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
+            BorrowKind::Fake(_) | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
                 return Err(Unpromotable);
             }
 
@@ -588,29 +597,79 @@ impl<'tcx> Validator<'_, 'tcx> {
         Ok(())
     }
 
+    /// Computes the sets of blocks of this MIR that are definitely going to be executed
+    /// if the function returns successfully. That makes it safe to promote calls in them
+    /// that might fail.
+    fn promotion_safe_blocks(body: &mir::Body<'tcx>) -> FxHashSet<BasicBlock> {
+        let mut safe_blocks = FxHashSet::default();
+        let mut safe_block = START_BLOCK;
+        loop {
+            safe_blocks.insert(safe_block);
+            // Let's see if we can find another safe block.
+            safe_block = match body.basic_blocks[safe_block].terminator().kind {
+                TerminatorKind::Goto { target } => target,
+                TerminatorKind::Call { target: Some(target), .. }
+                | TerminatorKind::Drop { target, .. } => {
+                    // This calls a function or the destructor. `target` does not get executed if
+                    // the callee loops or panics. But in both cases the const already fails to
+                    // evaluate, so we are fine considering `target` a safe block for promotion.
+                    target
+                }
+                TerminatorKind::Assert { target, .. } => {
+                    // Similar to above, we only consider successful execution.
+                    target
+                }
+                _ => {
+                    // No next safe block.
+                    break;
+                }
+            };
+        }
+        safe_blocks
+    }
+
+    /// Returns whether the block is "safe" for promotion, which means it cannot be dead code.
+    /// We use this to avoid promoting operations that can fail in dead code.
+    fn is_promotion_safe_block(&mut self, block: BasicBlock) -> bool {
+        let body = self.body;
+        let safe_blocks =
+            self.promotion_safe_blocks.get_or_insert_with(|| Self::promotion_safe_blocks(body));
+        safe_blocks.contains(&block)
+    }
+
     fn validate_call(
         &mut self,
         callee: &Operand<'tcx>,
         args: &[Spanned<Operand<'tcx>>],
+        block: BasicBlock,
     ) -> Result<(), Unpromotable> {
+        // Validate the operands. If they fail, there's no question -- we cannot promote.
+        self.validate_operand(callee)?;
+        for arg in args {
+            self.validate_operand(&arg.node)?;
+        }
+
+        // Functions marked `#[rustc_promotable]` are explicitly allowed to be promoted, so we can
+        // accept them at this point.
         let fn_ty = callee.ty(self.body, self.tcx);
+        if let ty::FnDef(def_id, _) = *fn_ty.kind() {
+            if self.tcx.is_promotable_const_fn(def_id) {
+                return Ok(());
+            }
+        }
 
-        // Inside const/static items, we promote all (eligible) function calls.
-        // Everywhere else, we require `#[rustc_promotable]` on the callee.
-        let promote_all_const_fn = matches!(
+        // Ideally, we'd stop here and reject the rest.
+        // But for backward compatibility, we have to accept some promotion in const/static
+        // initializers. Inline consts are explicitly excluded, they are more recent so we have no
+        // backwards compatibility reason to allow more promotion inside of them.
+        let promote_all_fn = matches!(
             self.const_kind,
             Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { inline: false })
         );
-        if !promote_all_const_fn {
-            if let ty::FnDef(def_id, _) = *fn_ty.kind() {
-                // Never promote runtime `const fn` calls of
-                // functions without `#[rustc_promotable]`.
-                if !self.tcx.is_promotable_const_fn(def_id) {
-                    return Err(Unpromotable);
-                }
-            }
+        if !promote_all_fn {
+            return Err(Unpromotable);
         }
-
+        // Make sure the callee is a `const fn`.
         let is_const_fn = match *fn_ty.kind() {
             ty::FnDef(def_id, _) => self.tcx.is_const_fn_raw(def_id),
             _ => false,
@@ -618,23 +677,23 @@ impl<'tcx> Validator<'_, 'tcx> {
         if !is_const_fn {
             return Err(Unpromotable);
         }
-
-        self.validate_operand(callee)?;
-        for arg in args {
-            self.validate_operand(&arg.node)?;
+        // The problem is, this may promote calls to functions that panic.
+        // We don't want to introduce compilation errors if there's a panic in a call in dead code.
+        // So we ensure that this is not dead code.
+        if !self.is_promotion_safe_block(block) {
+            return Err(Unpromotable);
         }
-
+        // This passed all checks, so let's accept.
         Ok(())
     }
 }
 
-// FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`.
 fn validate_candidates(
     ccx: &ConstCx<'_, '_>,
     temps: &mut IndexSlice<Local, TempState>,
     candidates: &[Candidate],
 ) -> Vec<Candidate> {
-    let mut validator = Validator { ccx, temps };
+    let mut validator = Validator { ccx, temps, promotion_safe_blocks: None };
 
     candidates
         .iter()
@@ -653,6 +712,10 @@ struct Promoter<'a, 'tcx> {
     /// If true, all nested temps are also kept in the
     /// source MIR, not moved to the promoted MIR.
     keep_original: bool,
+
+    /// If true, add the new const (the promoted) to the required_consts of the parent MIR.
+    /// This is initially false and then set by the visitor when it encounters a `Call` terminator.
+    add_to_required: bool,
 }
 
 impl<'a, 'tcx> Promoter<'a, 'tcx> {
@@ -755,6 +818,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 TerminatorKind::Call {
                     mut func, mut args, call_source: desugar, fn_span, ..
                 } => {
+                    // This promoted involves a function call, so it may fail to evaluate.
+                    // Let's make sure it is added to `required_consts` so that that failure cannot get lost.
+                    self.add_to_required = true;
+
                     self.visit_operand(&mut func, loc);
                     for arg in &mut args {
                         self.visit_operand(&mut arg.node, loc);
@@ -789,7 +856,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
 
     fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
         let def = self.source.source.def_id();
-        let mut rvalue = {
+        let (mut rvalue, promoted_op) = {
             let promoted = &mut self.promoted;
             let promoted_id = Promoted::new(next_promoted_id);
             let tcx = self.tcx;
@@ -799,11 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def));
                 let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) };
 
-                Operand::Constant(Box::new(ConstOperand {
-                    span,
-                    user_ty: None,
-                    const_: Const::Unevaluated(uneval, ty),
-                }))
+                ConstOperand { span, user_ty: None, const_: Const::Unevaluated(uneval, ty) }
             };
 
             let blocks = self.source.basic_blocks.as_mut();
@@ -836,22 +899,26 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             let promoted_ref = local_decls.push(promoted_ref);
             assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);
 
+            let promoted_operand = promoted_operand(ref_ty, span);
             let promoted_ref_statement = Statement {
                 source_info: statement.source_info,
                 kind: StatementKind::Assign(Box::new((
                     Place::from(promoted_ref),
-                    Rvalue::Use(promoted_operand(ref_ty, span)),
+                    Rvalue::Use(Operand::Constant(Box::new(promoted_operand))),
                 ))),
             };
             self.extra_statements.push((loc, promoted_ref_statement));
 
-            Rvalue::Ref(
-                tcx.lifetimes.re_erased,
-                *borrow_kind,
-                Place {
-                    local: mem::replace(&mut place.local, promoted_ref),
-                    projection: List::empty(),
-                },
+            (
+                Rvalue::Ref(
+                    tcx.lifetimes.re_erased,
+                    *borrow_kind,
+                    Place {
+                        local: mem::replace(&mut place.local, promoted_ref),
+                        projection: List::empty(),
+                    },
+                ),
+                promoted_operand,
             )
         };
 
@@ -863,6 +930,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
 
         let span = self.promoted.span;
         self.assign(RETURN_PLACE, rvalue, span);
+
+        // Now that we did promotion, we know whether we'll want to add this to `required_consts`.
+        if self.add_to_required {
+            self.source.required_consts.push(promoted_op);
+        }
+
         self.promoted
     }
 }
@@ -878,6 +951,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
             *local = self.promote_temp(*local);
         }
     }
+
+    fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) {
+        if constant.const_.is_required_const() {
+            self.promoted.required_consts.push(*constant);
+        }
+
+        // Skipping `super_constant` as the visitor is otherwise only looking for locals.
+    }
 }
 
 fn promote_candidates<'tcx>(
@@ -931,8 +1012,10 @@ fn promote_candidates<'tcx>(
             temps: &mut temps,
             extra_statements: &mut extra_statements,
             keep_original: false,
+            add_to_required: false,
         };
 
+        // `required_consts` of the promoted itself gets filled while building the MIR body.
         let mut promoted = promoter.promote_candidate(candidate, promotions.len());
         promoted.source.promoted = Some(promotions.next_index());
         promotions.push(promoted);
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index abde6a47e83..71ac929d35e 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,6 +1,5 @@
 use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{Const, ConstOperand, Location};
-use rustc_middle::ty::ConstKind;
+use rustc_middle::mir::{ConstOperand, Location};
 
 pub struct RequiredConstsVisitor<'a, 'tcx> {
     required_consts: &'a mut Vec<ConstOperand<'tcx>>,
@@ -14,14 +13,8 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
 
 impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
     fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
-        let const_ = constant.const_;
-        match const_ {
-            Const::Ty(c) => match c.kind() {
-                ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {}
-                _ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
-            },
-            Const::Unevaluated(..) => self.required_consts.push(*constant),
-            Const::Val(..) => {}
+        if constant.const_.is_required_const() {
+            self.required_consts.push(*constant);
         }
     }
 }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index e2436759c22..873095dca87 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -230,6 +230,10 @@ parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$tok
 
 parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
 
+parse_expr_rarrow_call = `->` used for field access or method call
+    .suggestion = try using `.` instead
+    .help = the `.` operator will dereference the value if needed
+
 parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
     .label = dash-separated idents are not valid
     .suggestion = if the original crate name uses dashes you need to use underscores in the code
@@ -620,6 +624,8 @@ parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allo
 parse_out_of_range_hex_escape = out of range hex escape
     .label = must be a character in the range [\x00-\x7f]
 
+parse_outer_attr_ambiguous = ambiguous outer attributes
+
 parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
 
 parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index eae2d904c35..d06f03a7c17 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -496,6 +496,15 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_outer_attr_ambiguous)]
+pub(crate) struct AmbiguousOuterAttributes {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: WrapInParentheses,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_missing_in_in_for_loop)]
 pub(crate) struct MissingInInForLoop {
     #[primary_span]
@@ -1463,7 +1472,7 @@ impl Subdiagnostic for FnTraitMissingParen {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
         let applicability = if self.machine_applicable {
@@ -2988,3 +2997,12 @@ pub(crate) struct AsyncImpl {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_expr_rarrow_call)]
+#[help]
+pub(crate) struct ExprRArrowCall {
+    #[primary_span]
+    #[suggestion(style = "short", applicability = "machine-applicable", code = ".")]
+    pub span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 00947a4c585..8ed2a6edf1a 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -327,7 +327,9 @@ impl<'a> Parser<'a> {
                 this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
             })?;
 
-            let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
+            self.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
+            let span = lhs_span.to(rhs.span);
+
             lhs = match op {
                 AssocOp::Add
                 | AssocOp::Subtract
@@ -426,6 +428,18 @@ impl<'a> Parser<'a> {
         });
     }
 
+    fn error_ambiguous_outer_attrs(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) {
+        if let Some(attr) = lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer) {
+            self.dcx().emit_err(errors::AmbiguousOuterAttributes {
+                span: attr.span.to(rhs_span),
+                sugg: errors::WrapInParentheses::Expression {
+                    left: attr.span.shrink_to_lo(),
+                    right: lhs_span.shrink_to_hi(),
+                },
+            });
+        }
+    }
+
     /// Possibly translate the current token to an associative operator.
     /// The method does not advance the current token.
     ///
@@ -506,7 +520,8 @@ impl<'a> Parser<'a> {
             None
         };
         let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
-        let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
+        self.error_ambiguous_outer_attrs(&lhs, lhs.span, rhs_span);
+        let span = lhs.span.to(rhs_span);
         let limits =
             if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
         let range = self.mk_range(Some(lhs), rhs, limits);
@@ -722,7 +737,8 @@ impl<'a> Parser<'a> {
         expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
     ) -> PResult<'a, P<Expr>> {
         let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
-            this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
+            this.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
+            this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs))
         };
 
         // Save the state of the parser before parsing type normally, in case there is a
@@ -979,6 +995,12 @@ impl<'a> Parser<'a> {
                 // we are using noexpect here because we don't expect a `.` directly after a `return`
                 // which could be suggested otherwise
                 self.eat_noexpect(&token::Dot)
+            } else if self.token.kind == TokenKind::RArrow && self.may_recover() {
+                // Recovery for `expr->suffix`.
+                self.bump();
+                let span = self.prev_token.span;
+                self.dcx().emit_err(errors::ExprRArrowCall { span });
+                true
             } else {
                 self.eat(&token::Dot)
             };
@@ -3807,16 +3829,6 @@ impl<'a> Parser<'a> {
         self.mk_expr(span, ExprKind::Err(guar))
     }
 
-    /// Create expression span ensuring the span of the parent node
-    /// is larger than the span of lhs and rhs, including the attributes.
-    fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
-        lhs.attrs
-            .iter()
-            .find(|a| a.style == AttrStyle::Outer)
-            .map_or(lhs_span, |a| a.span)
-            .to(rhs_span)
-    }
-
     fn collect_tokens_for_expr(
         &mut self,
         attrs: AttrWrapper,
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4a996f89a9a..742f4bd3c83 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -162,7 +162,6 @@ pub struct Parser<'a> {
     ///
     /// See the comments in the `parse_path_segment` function for more details.
     unmatched_angle_bracket_count: u16,
-    max_angle_bracket_count: u16,
     angle_bracket_nesting: u16,
 
     last_unexpected_token_span: Option<Span>,
@@ -430,7 +429,6 @@ impl<'a> Parser<'a> {
             num_bump_calls: 0,
             break_last_token: false,
             unmatched_angle_bracket_count: 0,
-            max_angle_bracket_count: 0,
             angle_bracket_nesting: 0,
             last_unexpected_token_span: None,
             subparser_name,
@@ -778,7 +776,6 @@ impl<'a> Parser<'a> {
         if ate {
             // See doc comment for `unmatched_angle_bracket_count`.
             self.unmatched_angle_bracket_count += 1;
-            self.max_angle_bracket_count += 1;
             debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count);
         }
         ate
@@ -898,6 +895,7 @@ impl<'a> Parser<'a> {
                             }
 
                             // Attempt to keep parsing if it was an omitted separator.
+                            self.last_unexpected_token_span = None;
                             match f(self) {
                                 Ok(t) => {
                                     // Parsed successfully, therefore most probably the code only
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 0f410772dd9..b97ec8c613d 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -299,7 +299,6 @@ impl<'a> Parser<'a> {
                 // parsing a new path.
                 if style == PathStyle::Expr {
                     self.unmatched_angle_bracket_count = 0;
-                    self.max_angle_bracket_count = 0;
                 }
 
                 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 7fc523ffe0d..a545c170297 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -353,7 +353,7 @@ passes_incorrect_meta_item = expected a quoted string literal
 passes_incorrect_meta_item_suggestion = consider surrounding this with quotes
 
 passes_incorrect_target =
-    `{$name}` language item must be applied to a {$kind} with {$at_least ->
+    `{$name}` lang item must be applied to a {$kind} with {$at_least ->
         [true] at least {$num}
         *[false] {$num}
     } generic {$num ->
@@ -394,12 +394,21 @@ passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]
 
 passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
 
+passes_lang_item_fn = {$name ->
+    [panic_impl] `#[panic_handler]`
+    *[other] `{$name}` lang item
+} function
+
 passes_lang_item_fn_with_target_feature =
-    `{$name}` language item function is not allowed to have `#[target_feature]`
-    .label = `{$name}` language item function is not allowed to have `#[target_feature]`
+    {passes_lang_item_fn} is not allowed to have `#[target_feature]`
+    .label = {passes_lang_item_fn} is not allowed to have `#[target_feature]`
+
+passes_lang_item_fn_with_track_caller =
+    {passes_lang_item_fn} is not allowed to have `#[track_caller]`
+    .label = {passes_lang_item_fn} is not allowed to have `#[target_feature]`
 
 passes_lang_item_on_incorrect_target =
-    `{$name}` language item must be applied to a {$expected_target}
+    `{$name}` lang item must be applied to a {$expected_target}
     .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
 
 passes_layout_abi =
@@ -455,7 +464,7 @@ passes_missing_const_stab_attr =
     {$descr} has missing const stability attribute
 
 passes_missing_lang_item =
-    language item required, but not found: `{$name}`
+    lang item required, but not found: `{$name}`
     .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
     .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
 
@@ -696,8 +705,8 @@ passes_unknown_feature =
     unknown feature `{$feature}`
 
 passes_unknown_lang_item =
-    definition of an unknown language item: `{$name}`
-    .label = definition of unknown language item `{$name}`
+    definition of an unknown lang item: `{$name}`
+    .label = definition of unknown lang item `{$name}`
 
 passes_unlabeled_cf_in_while_condition =
     `break` or `continue` with no label in the condition of a `while` loop
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1254ae8cfc8..a2388b3bd52 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -11,9 +11,9 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::StashKey;
 use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
-use rustc_hir as hir;
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir};
 use rustc_hir::{
     self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
 };
@@ -519,7 +519,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 self.dcx().emit_err(errors::NakedTrackedCaller { attr_span });
                 false
             }
-            Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => true,
+            Target::Fn => {
+                // `#[track_caller]` is not valid on weak lang items because they are called via
+                // `extern` declarations and `#[track_caller]` would alter their ABI.
+                if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
+                    && let Some(item) = hir::LangItem::from_name(lang_item)
+                    && item.is_weak()
+                {
+                    let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
+
+                    self.dcx().emit_err(errors::LangItemWithTrackCaller {
+                        attr_span,
+                        name: lang_item,
+                        sig_span: sig.span,
+                    });
+                    false
+                } else {
+                    true
+                }
+            }
+            Target::Method(..) | Target::ForeignFn | Target::Closure => true,
             // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
             // `#[track_caller]` attribute with just a lint, because we previously
             // erroneously allowed it and some crates used it accidentally, to be compatible
@@ -602,7 +621,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     ) -> bool {
         match target {
             Target::Fn => {
-                // `#[target_feature]` is not allowed in language items.
+                // `#[target_feature]` is not allowed in lang items.
                 if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
                     // Calling functions with `#[target_feature]` is
                     // not unsafe on WASM, see #84988
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 3f26ea4507d..03a607348e8 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -820,6 +820,16 @@ pub struct MissingLangItem {
 }
 
 #[derive(Diagnostic)]
+#[diag(passes_lang_item_fn_with_track_caller)]
+pub struct LangItemWithTrackCaller {
+    #[primary_span]
+    pub attr_span: Span,
+    pub name: Symbol,
+    #[label]
+    pub sig_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(passes_lang_item_fn_with_target_feature)]
 pub struct LangItemWithTargetFeature {
     #[primary_span]
@@ -1755,7 +1765,7 @@ impl Subdiagnostic for UnusedVariableStringInterp {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation);
         diag.multipart_suggestion(
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index d1368267224..c1da8928f30 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -1,4 +1,4 @@
-//! Detecting language items.
+//! Detecting lang items.
 //!
 //! Language items are items that represent concepts intrinsic to the language
 //! itself. Examples are:
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 4eb0c6c275e..90691ca1790 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -14,7 +14,7 @@ use crate::errors::{
 };
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
-/// language items required by this crate, but not defined yet.
+/// lang items required by this crate, but not defined yet.
 pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems, krate: &ast::Crate) {
     // These are never called by user code, they're generated by the compiler.
     // They will never implicitly be added to the `missing` array unless we do
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index 75b7b7c8f67..27f227e6d9c 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -65,7 +65,7 @@ impl<'tcx> Subdiagnostic for Overlap<'tcx> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         let Overlap { span, range } = self;
 
@@ -113,7 +113,7 @@ impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _: F,
+        _: &F,
     ) {
         let GappedRange { span, gap, first_range } = self;
 
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index b0329702d11..edfeacec7e3 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{codes::*, Applicability, MultiSpan};
+use rustc_errors::{codes::*, Applicability, ElidedLifetimeInPathSubdiag, MultiSpan};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{
     symbol::{Ident, Symbol},
@@ -907,6 +907,8 @@ pub(crate) struct ExplicitAnonymousLivetimeReportError {
 pub(crate) struct ImplicitElidedLifetimeNotAllowedHere {
     #[primary_span]
     pub(crate) span: Span,
+    #[subdiagnostic]
+    pub(crate) subdiag: ElidedLifetimeInPathSubdiag,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 753ba09d886..c877ae5e21f 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1883,20 +1883,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     //     async fn foo(_: std::cell::Ref<u32>) { ... }
                     LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
                     | LifetimeRibKind::AnonymousWarn(_) => {
-                        let mut err =
-                            self.r.dcx().create_err(errors::ImplicitElidedLifetimeNotAllowedHere {
-                                span: path_span,
-                            });
                         let sess = self.r.tcx.sess;
-                        rustc_errors::add_elided_lifetime_in_path_suggestion(
+                        let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
                             sess.source_map(),
-                            &mut err,
                             expected_lifetimes,
                             path_span,
                             !segment.has_generic_args,
                             elided_lifetime_span,
                         );
-                        err.emit();
+                        self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere {
+                            span: path_span,
+                            subdiag,
+                        });
                         should_lint = false;
 
                         for id in node_ids {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b8221d9d7f9..b5b6d899cc5 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1042,7 +1042,7 @@ pub struct Resolver<'a, 'tcx> {
     block_map: NodeMap<Module<'a>>,
     /// A fake module that contains no definition and no prelude. Used so that
     /// some AST passes can generate identifiers that only resolve to local or
-    /// language items.
+    /// lang items.
     empty_module: Module<'a>,
     module_map: FxHashMap<DefId, Module<'a>>,
     binding_parent_modules: FxHashMap<NameBinding<'a>, Module<'a>>,
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index d5b22f841d2..07c11663173 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2548,7 +2548,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
 
     let mut search_paths = vec![];
     for s in &matches.opt_strs("L") {
-        search_paths.push(SearchPath::from_cli_opt(&sysroot, &target_triple, early_dcx, s));
+        search_paths.push(SearchPath::from_cli_opt(
+            &sysroot,
+            &target_triple,
+            early_dcx,
+            s,
+            unstable_opts.unstable_options,
+        ));
     }
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index cb6656bae06..83377b66095 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,7 +6,9 @@ use crate::search_paths::PathKind;
 use crate::utils::NativeLibKind;
 use rustc_ast as ast;
 use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
+use rustc_hir::def_id::{
+    CrateNum, DefId, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE,
+};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -217,7 +219,6 @@ pub trait CrateStore: std::fmt::Debug {
     // incr. comp. uses to identify a CrateNum.
     fn crate_name(&self, cnum: CrateNum) -> Symbol;
     fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId;
-    fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum;
 }
 
 pub type CrateStoreDyn = dyn CrateStore + sync::DynSync + sync::DynSend;
@@ -227,4 +228,6 @@ pub struct Untracked {
     /// Reference span for definitions.
     pub source_span: AppendOnlyIndexVec<LocalDefId, Span>,
     pub definitions: FreezeLock<Definitions>,
+    /// The interned [StableCrateId]s.
+    pub stable_crate_ids: FreezeLock<StableCrateIdMap>,
 }
diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs
index 16dd40acef0..bc2f2a8af1f 100644
--- a/compiler/rustc_session/src/search_paths.rs
+++ b/compiler/rustc_session/src/search_paths.rs
@@ -52,6 +52,7 @@ impl SearchPath {
         triple: &TargetTriple,
         early_dcx: &EarlyDiagCtxt,
         path: &str,
+        is_unstable_enabled: bool,
     ) -> Self {
         let (kind, path) = if let Some(stripped) = path.strip_prefix("native=") {
             (PathKind::Native, stripped)
@@ -68,6 +69,14 @@ impl SearchPath {
         };
         let dir = match path.strip_prefix("@RUSTC_BUILTIN") {
             Some(stripped) => {
+                if !is_unstable_enabled {
+                    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
+                    early_dcx.early_fatal(
+                        "the `-Z unstable-options` flag must also be passed to \
+                         enable the use of `@RUSTC_BUILTIN`",
+                    );
+                }
+
                 make_target_lib_path(sysroot, triple.triple()).join("builtin").join(stripped)
             }
             None => PathBuf::from(path),
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 7c021621103..452ab04c44c 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -229,7 +229,7 @@ impl<'tcx> Stable<'tcx> for mir::BorrowKind {
         use rustc_middle::mir::BorrowKind::*;
         match *self {
             Shared => stable_mir::mir::BorrowKind::Shared,
-            Fake => stable_mir::mir::BorrowKind::Fake,
+            Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables)),
             Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
         }
     }
@@ -247,6 +247,17 @@ impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
     }
 }
 
+impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
+    type T = stable_mir::mir::FakeBorrowKind;
+    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+        use rustc_middle::mir::FakeBorrowKind::*;
+        match *self {
+            Deep => stable_mir::mir::FakeBorrowKind::Deep,
+            Shallow => stable_mir::mir::FakeBorrowKind::Shallow,
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
     type T = stable_mir::mir::NullOp;
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 1df2b357ac1..61234a97e16 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1251,7 +1251,7 @@ struct HygieneDecodeContextInner {
     // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create
     // a new id in the global `HygieneData`. This map tracks the ID we end up picking,
     // so that multiple occurrences of the same serialized id are decoded to the same
-    // `SyntaxContext`. This only stores `SyntaxContext`s which are completly decoded.
+    // `SyntaxContext`. This only stores `SyntaxContext`s which are completely decoded.
     remapped_ctxts: Vec<Option<SyntaxContext>>,
 
     /// Maps serialized `SyntaxContext` ids that are currently being decoded to a `SyntaxContext`.
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index e3e76caebaf..33bd11cc807 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, R
 use rustc_data_structures::unhash::UnhashMap;
 use std::fs;
 use std::io::{self, BorrowedBuf, Read};
-use std::path::{self};
+use std::path;
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2d3053ccee6..8abf42e2c13 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1348,7 +1348,7 @@ symbols! {
         panic_misaligned_pointer_dereference,
         panic_nounwind,
         panic_runtime,
-        panic_str,
+        panic_str_2015,
         panic_unwind,
         panicking,
         param_attrs,
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index b126062102e..9b08a86ef16 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -104,7 +104,7 @@ impl Subdiagnostic for AdjustSignatureBorrow {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        _f: F,
+        _f: &F,
     ) {
         match self {
             AdjustSignatureBorrow::Borrow { to_borrow } => {
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index f9e7ed9dcbb..053de2c673b 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -784,7 +784,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
 
                     match (evaluate(c1), evaluate(c2)) {
                         (Ok(c1), Ok(c2)) => {
-                            match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::No,c1, c2)
+                            match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::Yes,c1, c2)
                             {
                                 Ok(_) => (),
                                 Err(_) => return false,
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
index 96596de32aa..0e309689680 100644
--- 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
@@ -2938,17 +2938,28 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
             _ => {}
         };
+
         // 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, " +")
+        let (span, separator, open_paren_sp) =
+            if let Some((s, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
+                (s, " +", open_paren_sp)
+            } else {
+                (param.name.ident().span.shrink_to_hi(), ":", None)
+            };
+
+        let mut suggs = vec![];
+        let suggestion = format!("{separator} ?Sized");
+
+        if let Some(open_paren_sp) = open_paren_sp {
+            suggs.push((open_paren_sp, "(".to_string()));
+            suggs.push((span, format!("){suggestion}")));
         } else {
-            (param.name.ident().span.shrink_to_hi(), ":")
-        };
-        err.span_suggestion_verbose(
-            span,
+            suggs.push((span, suggestion));
+        }
+
+        err.multipart_suggestion_verbose(
             "consider relaxing the implicit `Sized` restriction",
-            format!("{separator} ?Sized"),
+            suggs,
             Applicability::MachineApplicable,
         );
     }
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 397e104512f..3be0be83e09 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -227,7 +227,7 @@ pub enum TyKind<I: Interner> {
     /// A placeholder type, used during higher ranked subtyping to instantiate
     /// bound variables.
     ///
-    /// It is conventional to render anonymous placeholer types like `!N` or `!U_N`,
+    /// It is conventional to render anonymous placeholder types like `!N` or `!U_N`,
     /// where `N` is the placeholder variable's anonymous index (which corresponds
     /// to the bound variable's index from the binder from which it was instantiated),
     /// and `U` is the universe index in which it is instantiated, or totally omitted
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 6f666406c22..e077c580318 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -867,11 +867,9 @@ pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
     Shared,
 
-    /// The immediately borrowed place must be immutable, but projections from
-    /// it don't need to be. This is used to prevent match guards from replacing
-    /// the scrutinee. For example, a fake borrow of `a.b` doesn't
-    /// conflict with a mutable borrow of `a.b.c`.
-    Fake,
+    /// An immutable, aliasable borrow that is discarded after borrow-checking. Can behave either
+    /// like a normal shared borrow or like a special shallow borrow (see [`FakeBorrowKind`]).
+    Fake(FakeBorrowKind),
 
     /// Data is mutable and not aliasable.
     Mut {
@@ -886,7 +884,7 @@ impl BorrowKind {
             BorrowKind::Mut { .. } => Mutability::Mut,
             BorrowKind::Shared => Mutability::Not,
             // FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation.
-            BorrowKind::Fake => Mutability::Not,
+            BorrowKind::Fake(_) => Mutability::Not,
         }
     }
 }
@@ -898,6 +896,17 @@ pub enum MutBorrowKind {
     ClosureCapture,
 }
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum FakeBorrowKind {
+    /// A shared (deep) borrow. Data must be immutable and is aliasable.
+    Deep,
+    /// The immediately borrowed place must be immutable, but projections from
+    /// it don't need to be. This is used to prevent match guards from replacing
+    /// the scrutinee. For example, a fake borrow of `a.b` doesn't
+    /// conflict with a mutable borrow of `a.b.c`.
+    Shallow,
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum Mutability {
     Not,
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 4ac4833add7..bbca3965852 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -8,7 +8,7 @@ use std::{fmt, io, iter};
 
 use super::{AssertMessage, BinOp, TerminatorKind};
 
-use super::BorrowKind;
+use super::{BorrowKind, FakeBorrowKind};
 
 impl Display for Ty {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
@@ -352,7 +352,8 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
         Rvalue::Ref(_, borrowkind, place) => {
             let kind = match borrowkind {
                 BorrowKind::Shared => "&",
-                BorrowKind::Fake => "&fake ",
+                BorrowKind::Fake(FakeBorrowKind::Deep) => "&fake ",
+                BorrowKind::Fake(FakeBorrowKind::Shallow) => "&fake shallow ",
                 BorrowKind::Mut { .. } => "&mut ",
             };
             write!(writer, "{kind}{:?}", place)
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 2a02870e30b..0b92767c932 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -25,7 +25,9 @@ const fn size_align<T>() -> (usize, usize) {
 /// An instance of `Layout` describes a particular layout of memory.
 /// You build a `Layout` up as an input to give to an allocator.
 ///
-/// All layouts have an associated size and a power-of-two alignment.
+/// All layouts have an associated size and a power-of-two alignment. The size, when rounded up to
+/// the nearest multiple of `align`, does not overflow isize (i.e., the rounded value will always be
+/// less than or equal to `isize::MAX`).
 ///
 /// (Note that layouts are *not* required to have non-zero size,
 /// even though `GlobalAlloc` requires that all memory requests
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 5e4dac8f49b..92626feabf3 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -153,7 +153,7 @@ impl<'a> Argument<'a> {
     ///
     /// # Safety
     ///
-    /// This argument must actually be a placeholer argument.
+    /// This argument must actually be a placeholder argument.
     ///
     // FIXME: Transmuting formatter in new and indirectly branching to/calling
     // it here is an explicit CFI violation.
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 92f1bd27408..7ace874fa90 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1987,6 +1987,13 @@ extern "rust-intrinsic" {
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `count_ones` method. For example,
     /// [`u32::count_ones`]
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
+    #[rustc_safe_intrinsic]
+    #[rustc_nounwind]
+    pub fn ctpop<T: Copy>(x: T) -> u32;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
@@ -2028,6 +2035,13 @@ extern "rust-intrinsic" {
     /// let num_leading = ctlz(x);
     /// assert_eq!(num_leading, 16);
     /// ```
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
+    #[rustc_safe_intrinsic]
+    #[rustc_nounwind]
+    pub fn ctlz<T: Copy>(x: T) -> u32;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
@@ -2050,6 +2064,12 @@ extern "rust-intrinsic" {
     /// let num_leading = unsafe { ctlz_nonzero(x) };
     /// assert_eq!(num_leading, 3);
     /// ```
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
+    #[rustc_nounwind]
+    pub fn ctlz_nonzero<T: Copy>(x: T) -> u32;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
     #[rustc_nounwind]
     pub fn ctlz_nonzero<T: Copy>(x: T) -> T;
@@ -2090,6 +2110,13 @@ extern "rust-intrinsic" {
     /// let num_trailing = cttz(x);
     /// assert_eq!(num_trailing, 16);
     /// ```
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
+    #[rustc_safe_intrinsic]
+    #[rustc_nounwind]
+    pub fn cttz<T: Copy>(x: T) -> u32;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
@@ -2112,6 +2139,12 @@ extern "rust-intrinsic" {
     /// let num_trailing = unsafe { cttz_nonzero(x) };
     /// assert_eq!(num_trailing, 3);
     /// ```
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
+    #[rustc_nounwind]
+    pub fn cttz_nonzero<T: Copy>(x: T) -> u32;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
     #[rustc_nounwind]
     pub fn cttz_nonzero<T: Copy>(x: T) -> T;
@@ -2288,6 +2321,13 @@ extern "rust-intrinsic" {
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
     /// [`u32::rotate_left`]
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+    #[rustc_safe_intrinsic]
+    #[rustc_nounwind]
+    pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
@@ -2303,6 +2343,13 @@ extern "rust-intrinsic" {
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_right` method. For example,
     /// [`u32::rotate_right`]
+    #[cfg(not(bootstrap))]
+    #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+    #[rustc_safe_intrinsic]
+    #[rustc_nounwind]
+    pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
+
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index b9d771ba359..5a0958fdc89 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -527,7 +527,12 @@ macro_rules! nonzero_integer {
             #[inline]
             pub const fn leading_zeros(self) -> u32 {
                 // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
-                unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
+                unsafe {
+                    #[cfg(not(bootstrap))]
+                    return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive);
+                    #[cfg(bootstrap)]
+                    return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32;
+                }
             }
 
             /// Returns the number of trailing zeros in the binary representation
@@ -551,7 +556,12 @@ macro_rules! nonzero_integer {
             #[inline]
             pub const fn trailing_zeros(self) -> u32 {
                 // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
-                unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
+                unsafe {
+                    #[cfg(not(bootstrap))]
+                    return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive);
+                    #[cfg(bootstrap)]
+                    return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32;
+                }
             }
 
             /// Returns the number of ones in the binary representation of `self`.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index c13763243f0..ea14d769cc1 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -77,7 +77,10 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn count_ones(self) -> u32 {
-            intrinsics::ctpop(self as $ActualT) as u32
+            #[cfg(not(bootstrap))]
+            return intrinsics::ctpop(self as $ActualT);
+            #[cfg(bootstrap)]
+            return intrinsics::ctpop(self as $ActualT) as u32;
         }
 
         /// Returns the number of zeros in the binary representation of `self`.
@@ -119,7 +122,10 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn leading_zeros(self) -> u32 {
-            intrinsics::ctlz(self as $ActualT) as u32
+            #[cfg(not(bootstrap))]
+            return intrinsics::ctlz(self as $ActualT);
+            #[cfg(bootstrap)]
+            return intrinsics::ctlz(self as $ActualT) as u32;
         }
 
         /// Returns the number of trailing zeros in the binary representation
@@ -140,7 +146,10 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn trailing_zeros(self) -> u32 {
-            intrinsics::cttz(self) as u32
+            #[cfg(not(bootstrap))]
+            return intrinsics::cttz(self);
+            #[cfg(bootstrap)]
+            return intrinsics::cttz(self) as u32;
         }
 
         /// Returns the number of leading ones in the binary representation of `self`.
@@ -205,7 +214,10 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn rotate_left(self, n: u32) -> Self {
-            intrinsics::rotate_left(self, n as $SelfT)
+            #[cfg(not(bootstrap))]
+            return intrinsics::rotate_left(self, n);
+            #[cfg(bootstrap)]
+            return intrinsics::rotate_left(self, n as $SelfT);
         }
 
         /// Shifts the bits to the right by a specified amount, `n`,
@@ -230,7 +242,10 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline(always)]
         pub const fn rotate_right(self, n: u32) -> Self {
-            intrinsics::rotate_right(self, n as $SelfT)
+            #[cfg(not(bootstrap))]
+            return intrinsics::rotate_right(self, n);
+            #[cfg(bootstrap)]
+            return intrinsics::rotate_right(self, n as $SelfT);
         }
 
         /// Reverses the byte order of the integer.
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 631e1654ce0..1e3ed0f7c49 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -554,7 +554,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::iter::{self, FusedIterator, TrustedLen};
-use crate::panicking::{panic, panic_str};
+use crate::panicking::{panic, panic_display};
 use crate::pin::Pin;
 use crate::{
     cmp, convert, hint, mem,
@@ -1991,7 +1991,7 @@ const fn unwrap_failed() -> ! {
 #[track_caller]
 #[rustc_const_unstable(feature = "const_option", issue = "67441")]
 const fn expect_failed(msg: &str) -> ! {
-    panic_str(msg)
+    panic_display(&msg)
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index b520efe93f9..8771f40f9b4 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -27,9 +27,9 @@ pub macro panic_2015 {
     ($msg:literal $(,)?) => (
         $crate::panicking::panic($msg)
     ),
-    // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
+    // Use `panic_str_2015` instead of `panic_display::<&str>` for non_fmt_panic lint.
     ($msg:expr $(,)?) => ({
-        $crate::panicking::panic_str($msg);
+        $crate::panicking::panic_str_2015($msg);
     }),
     // Special-case the single-argument case for const_panic.
     ("{}", $arg:expr $(,)?) => ({
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index cbb0a7d61db..3ee56e6c579 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -124,8 +124,8 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
 // above.
 
 /// The underlying implementation of core's `panic!` macro when no formatting is used.
-// never inline unless panic_immediate_abort to avoid code
-// bloat at the call sites as much as possible
+// Never inline unless panic_immediate_abort to avoid code
+// bloat at the call sites as much as possible.
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
 #[track_caller]
@@ -138,6 +138,11 @@ pub const fn panic(expr: &'static str) -> ! {
     // truncation and padding (even though none is used here). Using
     // Arguments::new_const may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
+    // However, this optimization only works for `'static` strings: `new_const` also makes this
+    // message return `Some` from `Arguments::as_str`, which means it can become part of the panic
+    // payload without any allocation or copying. Shorter-lived strings would become invalid as
+    // stack frames get popped during unwinding, and couldn't be directly referenced from the
+    // payload.
     panic_fmt(fmt::Arguments::new_const(&[expr]));
 }
 
@@ -223,14 +228,6 @@ pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! {
     panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true);
 }
 
-#[inline]
-#[track_caller]
-#[rustc_diagnostic_item = "panic_str"]
-#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
-pub const fn panic_str(expr: &str) -> ! {
-    panic_display(&expr);
-}
-
 #[track_caller]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
@@ -246,6 +243,16 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
     panic_fmt(format_args!("internal error: entered unreachable code: {}", *x));
 }
 
+/// This exists solely for the 2015 edition `panic!` macro to trigger
+/// a lint on `panic!(my_str_variable);`.
+#[inline]
+#[track_caller]
+#[rustc_diagnostic_item = "panic_str_2015"]
+#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
+pub const fn panic_str_2015(expr: &str) -> ! {
+    panic_display(&expr);
+}
+
 #[inline]
 #[track_caller]
 #[rustc_do_not_const_check] // hooked by const-eval
diff --git a/library/std/src/sync/reentrant_lock/tests.rs b/library/std/src/sync/reentrant_lock/tests.rs
index d4c1d440c61..aeef0289d28 100644
--- a/library/std/src/sync/reentrant_lock/tests.rs
+++ b/library/std/src/sync/reentrant_lock/tests.rs
@@ -1,4 +1,4 @@
-use super::{ReentrantLock, ReentrantLockGuard};
+use super::ReentrantLock;
 use crate::cell::RefCell;
 use crate::sync::Arc;
 use crate::thread;
@@ -51,10 +51,3 @@ fn trylock_works() {
     .unwrap();
     let _lock3 = l.try_lock();
 }
-
-pub struct Answer<'a>(pub ReentrantLockGuard<'a, RefCell<u32>>);
-impl Drop for Answer<'_> {
-    fn drop(&mut self) {
-        *self.0.borrow_mut() = 42;
-    }
-}
diff --git a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
index 9fd0ac49881..2e827535862 100644
--- a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
+++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
@@ -73,7 +73,7 @@ Tests can be run on AArch64 Windows 11 devices.
 
 ## Cross-compilation toolchains and C code
 
-C code can be built using the Arm64-targetting MSVC or Clang toolchain.
+C code can be built using the Arm64-targeting MSVC or Clang toolchain.
 
 To compile:
 
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
index 77efa9c3282..4faa1988735 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
@@ -59,7 +59,7 @@ languages compiled to WebAssembly, for example C/C++. Any ABI differences or
 mismatches are considered bugs that need to be fixed.
 
 By default the WASI targets in Rust ship in rustup with a precompiled copy of
-[`wasi-libc`] meaning that a WebAssembly-targetting-Clang is not required to
+[`wasi-libc`] meaning that a WebAssembly-targeting-Clang is not required to
 use the WASI targets from Rust.  If there is no actual interoperation with C
 then `rustup target add wasm32-wasip1` is all that's needed to get
 started with WASI.
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index 7d573ac950d..c05077befdb 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -417,7 +417,7 @@ warning: 1 warning emitted
 
 This lint is **warn-by-default**. It detects explicit links that are the same
 as computed automatic links.
-This usually means the explicit links are removeable. For example:
+This usually means the explicit links are removable. For example:
 
 ```rust
 #![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default.
diff --git a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
index 56c14b1638a..1a367b8274b 100644
--- a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
+++ b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
@@ -168,4 +168,4 @@ render differently in this case:
 ```
 
 `1.` and `2.` will be displayed as is in the rendered documentation (ie, `[a]` and `[b][c]`)
-whereas `3.` and `4.` will be replaced by a link targetting `e` for `[d](e)` and `g` for `[f]`.
+whereas `3.` and `4.` will be replaced by a link targeting `e` for `[d](e)` and `g` for `[f]`.
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index f078ad2fb53..465f969435d 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -635,7 +635,16 @@ impl Options {
         let libs = matches
             .opt_strs("L")
             .iter()
-            .map(|s| SearchPath::from_cli_opt(&sysroot, &target, early_dcx, s))
+            .map(|s| {
+                SearchPath::from_cli_opt(
+                    &sysroot,
+                    &target,
+                    early_dcx,
+                    s,
+                    #[allow(rustc::bad_opt_access)] // we have no `Session` here
+                    unstable_opts.unstable_options,
+                )
+            })
             .collect();
 
         let show_coverage = matches.opt_present("show-coverage");
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index f78743a7917..dd2bb47e592 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -187,7 +187,7 @@ declare_rustdoc_lint! {
 
 declare_rustdoc_lint! {
     /// This lint is **warn-by-default**. It detects explicit links that are the same
-    /// as computed automatic links. This usually means the explicit links are removeable.
+    /// as computed automatic links. This usually means the explicit links are removable.
     /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book].
     ///
     /// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 89d6f8d67f1..e788069ea80 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -314,7 +314,7 @@ pub enum StructKind {
     /// All [`Id`]'s will point to [`ItemEnum::StructField`]. Private and
     /// `#[doc(hidden)]` fields will be given as `None`
     Tuple(Vec<Option<Id>>),
-    /// A struct with nammed fields.
+    /// A struct with named fields.
     ///
     /// ```rust
     /// pub struct PlainStruct { x: i32 }
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 80d5b607dde6ef97dfff4e23923822c01d2bb03
+Subproject c9392675917adc2edab269eea27c222b5359c63
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index d0c66900c00..e7ec2b3151e 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -185,7 +185,7 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
     if let hir::PatKind::Wild = pat.kind {
         return false; // ignore `_` patterns
     }
-    if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
+    if cx.tcx.has_typeck_results(pat.hir_id.owner.def_id) {
         is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), tys)
     } else {
         false
@@ -233,7 +233,7 @@ fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bo
             Call(_, args) => {
                 let mut tys = DefIdSet::default();
                 for arg in args {
-                    if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                    if cx.tcx.has_typeck_results(arg.hir_id.owner.def_id)
                         && is_mutable_ty(cx, cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), &mut tys)
                         && is_mutated_static(arg)
                     {
@@ -246,7 +246,7 @@ fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bo
             MethodCall(_, receiver, args, _) => {
                 let mut tys = DefIdSet::default();
                 for arg in std::iter::once(receiver).chain(args.iter()) {
-                    if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                    if cx.tcx.has_typeck_results(arg.hir_id.owner.def_id)
                         && is_mutable_ty(cx, cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), &mut tys)
                         && is_mutated_static(arg)
                     {
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
index 05d5b3d10ea..84dac431169 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
@@ -16,7 +16,7 @@ fn foo(
 
 fn skip_on_statements() {
     #[rustfmt::skip]
-    5+3;
+    { 5+3; }
 }
 
 #[rustfmt::skip]
@@ -33,11 +33,11 @@ mod foo {
 #[clippy::msrv = "1.29"]
 fn msrv_1_29() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    1+29;
+    { 1+29; }
 }
 
 #[clippy::msrv = "1.30"]
 fn msrv_1_30() {
     #[rustfmt::skip]
-    1+30;
+    { 1+30; }
 }
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
index bc29e20210e..4ab5c70e13b 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
@@ -16,7 +16,7 @@ fn foo(
 
 fn skip_on_statements() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    5+3;
+    { 5+3; }
 }
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
@@ -33,11 +33,11 @@ mod foo {
 #[clippy::msrv = "1.29"]
 fn msrv_1_29() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    1+29;
+    { 1+29; }
 }
 
 #[clippy::msrv = "1.30"]
 fn msrv_1_30() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    1+30;
+    { 1+30; }
 }
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 0c39f2fa601..73f5738469e 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -20,6 +20,10 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
         "refining-impl-trait",
         "Detects refinement of `impl Trait` return types by trait implementations",
     ),
+    (
+        "keyword-idents",
+        "Lints that detect identifiers which will be come keywords in later editions",
+    ),
 ];
 
 type LintGroups = BTreeMap<String, BTreeSet<String>>;
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index aca780e33f0..22ab576b077 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -25,6 +25,7 @@ static RENAMES: &[(Level, &[(&str, &str)])] = &[
             ("elided-lifetime-in-path", "elided-lifetimes-in-paths"),
             ("async-idents", "keyword-idents"),
             ("disjoint-capture-migration", "rust-2021-incompatible-closure-captures"),
+            ("keyword-idents", "keyword-idents-2018"),
             ("or-patterns-back-compat", "rust-2021-incompatible-or-patterns"),
         ],
     ),
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 9b0b1c8d230..3191355ccbe 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-aca749eefceaed0cda19a7ec5e472fce9387bc00
+c1feb3eceef7d5f0126c309a87062cf413fe0a25
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index a2fc4f0f761..9a0671430d4 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -163,7 +163,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             }
                         }
                         Op::Numeric(name) => {
-                            this.numeric_intrinsic(name, op.to_scalar(), op.layout)?
+                            this.numeric_intrinsic(name, op.to_scalar(), op.layout, op.layout)?
                         }
                     };
                     this.write_scalar(val, &dest)?;
diff --git a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs
index 13f913454dc..f71df9a1c90 100644
--- a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs
+++ b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs
@@ -1,3 +1,6 @@
+// Validation stops this too early.
+//@compile-flags: -Zmiri-disable-validation
+
 trait T1 {
     #[allow(dead_code)]
     fn method1(self: Box<Self>);
@@ -13,5 +16,5 @@ impl T1 for i32 {
 fn main() {
     let r = Box::new(0) as Box<dyn T1>;
     let r2: Box<dyn T2> = unsafe { std::mem::transmute(r) };
-    r2.method2(); //~ERROR: call on a pointer whose vtable does not match its type
+    r2.method2(); //~ERROR: using vtable for trait `T1` but trait `T2` was expected
 }
diff --git a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr
index 365186bcc4b..019a55bcdcb 100644
--- a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr
+++ b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `dyn` call on a pointer whose vtable does not match its type
+error: Undefined Behavior: using vtable for trait `T1` but trait `T2` was expected
   --> $DIR/dyn-call-trait-mismatch.rs:LL:CC
    |
 LL |     r2.method2();
-   |     ^^^^^^^^^^^^ `dyn` call on a pointer whose vtable does not match its type
+   |     ^^^^^^^^^^^^ using vtable for trait `T1` but trait `T2` was expected
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.rs b/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.rs
new file mode 100644
index 00000000000..dff5a21c4c7
--- /dev/null
+++ b/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.rs
@@ -0,0 +1,15 @@
+// This upcast is currently forbidden because it involves an invalid value.
+// However, if in the future we relax the validity requirements for raw pointer vtables,
+// we could consider allowing this again -- the cast itself isn't doing anything wrong,
+// only the transmutes needed to set up the testcase are wrong.
+
+use std::fmt;
+
+fn main() {
+    // vtable_mismatch_nop_cast
+    let ptr: &dyn fmt::Display = &0;
+    let ptr: *const (dyn fmt::Debug + Send + Sync) = unsafe { std::mem::transmute(ptr) }; //~ERROR: wrong trait
+    // Even though the vtable is for the wrong trait, this cast doesn't actually change the needed
+    // vtable so it should still be allowed -- if we ever allow the line above.
+    let _ptr2 = ptr as *const dyn fmt::Debug;
+}
diff --git a/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr b/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr
new file mode 100644
index 00000000000..4165d5ea15d
--- /dev/null
+++ b/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug + std::marker::Send + std::marker::Sync`, but encountered `std::fmt::Display`
+  --> $DIR/dyn-upcast-nop-wrong-trait.rs:LL:CC
+   |
+LL |     let ptr: *const (dyn fmt::Debug + Send + Sync) = unsafe { std::mem::transmute(ptr) };
+   |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug + std::marker::Send + std::marker::Sync`, but encountered `std::fmt::Display`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/dyn-upcast-nop-wrong-trait.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
index 982f33b0a31..1d6b6777032 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
+++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
@@ -1,3 +1,6 @@
+// Validation stops this too early.
+//@compile-flags: -Zmiri-disable-validation
+
 #![feature(trait_upcasting)]
 #![allow(incomplete_features)]
 
@@ -57,7 +60,7 @@ impl Baz for i32 {
 
 fn main() {
     let baz: &dyn Baz = &1;
-    let baz_fake: &dyn Bar = unsafe { std::mem::transmute(baz) };
-    let _err = baz_fake as &dyn Foo;
-    //~^ERROR: upcast on a pointer whose vtable does not match its type
+    let baz_fake: *const dyn Bar = unsafe { std::mem::transmute(baz) };
+    let _err = baz_fake as *const dyn Foo;
+    //~^ERROR: using vtable for trait `Baz` but trait `Bar` was expected
 }
diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr
index 8bac908b864..6a2415cf57e 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr
+++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: upcast on a pointer whose vtable does not match its type
+error: Undefined Behavior: using vtable for trait `Baz` but trait `Bar` was expected
   --> $DIR/dyn-upcast-trait-mismatch.rs:LL:CC
    |
-LL |     let _err = baz_fake as &dyn Foo;
-   |                ^^^^^^^^ upcast on a pointer whose vtable does not match its type
+LL |     let _err = baz_fake as *const dyn Foo;
+   |                ^^^^^^^^ using vtable for trait `Baz` but trait `Bar` was expected
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
index c26cd4cadb5..0b34afc6090 100644
--- a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
@@ -2,7 +2,7 @@
 
 mod rusti {
     extern "rust-intrinsic" {
-        pub fn ctlz_nonzero<T>(x: T) -> T;
+        pub fn ctlz_nonzero<T>(x: T) -> u32;
     }
 }
 
diff --git a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
index 25a0501fdd8..e220411f585 100644
--- a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
+++ b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
@@ -2,7 +2,7 @@
 
 mod rusti {
     extern "rust-intrinsic" {
-        pub fn cttz_nonzero<T>(x: T) -> T;
+        pub fn cttz_nonzero<T>(x: T) -> u32;
     }
 }
 
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.rs b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.rs
new file mode 100644
index 00000000000..9b1cefc4b1d
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.rs
@@ -0,0 +1,12 @@
+use std::mem;
+
+// Make sure we notice the mismatch also if the difference is "only" in the generic
+// parameters of the trait.
+
+trait Trait<T> {}
+impl<T> Trait<T> for T {}
+
+fn main() {
+    let x: &dyn Trait<i32> = &0;
+    let _y: *const dyn Trait<u32> = unsafe { mem::transmute(x) }; //~ERROR: wrong trait
+}
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr
new file mode 100644
index 00000000000..1219f9f88cf
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<u32>`, but encountered `Trait<i32>`
+  --> $DIR/wrong-dyn-trait-generic.rs:LL:CC
+   |
+LL |     let _y: *const dyn Trait<u32> = unsafe { mem::transmute(x) };
+   |                                              ^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<u32>`, but encountered `Trait<i32>`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/wrong-dyn-trait-generic.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait.rs b/src/tools/miri/tests/fail/validity/wrong-dyn-trait.rs
new file mode 100644
index 00000000000..d6049196f26
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait.rs
@@ -0,0 +1,6 @@
+use std::{fmt, mem};
+
+fn main() {
+    let x: &dyn Send = &0;
+    let _y: *const dyn fmt::Debug = unsafe { mem::transmute(x) }; //~ERROR: wrong trait
+}
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr b/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr
new file mode 100644
index 00000000000..e3503323b31
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `<trivial>`
+  --> $DIR/wrong-dyn-trait.rs:LL:CC
+   |
+LL |     let _y: *const dyn fmt::Debug = unsafe { mem::transmute(x) };
+   |                                              ^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `<trivial>`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/wrong-dyn-trait.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs
index 2491bda0917..adbf5df62cc 100644
--- a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs
+++ b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs
@@ -25,7 +25,7 @@ impl Foo<u32> for u32 {
 impl Bar for () {}
 
 unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo<u32> + 'a)) -> u32 {
-    let foo_e: *const dyn Foo<u16> = t as *const _;
+    let foo_e: *const dyn Foo<u32> = t as *const _;
     let r_1 = foo_e as *mut dyn Foo<u32>;
 
     (&*r_1).foo(0)
diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs
index 529b9c471d4..ddc4bdcf082 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.rs
+++ b/src/tools/miri/tests/pass/dyn-upcast.rs
@@ -1,24 +1,26 @@
 #![feature(trait_upcasting)]
 #![allow(incomplete_features)]
 
+use std::fmt;
+
 fn main() {
     basic();
     diamond();
     struct_();
     replace_vptr();
-    vtable_mismatch_nop_cast();
+    vtable_nop_cast();
 }
 
-fn vtable_mismatch_nop_cast() {
-    let ptr: &dyn std::fmt::Display = &0;
-    // Even though the vtable is for the wrong trait, this cast doesn't actually change the needed
-    // vtable so it should still be allowed.
-    let ptr: *const (dyn std::fmt::Debug + Send + Sync) = unsafe { std::mem::transmute(ptr) };
-    let _ptr2 = ptr as *const dyn std::fmt::Debug;
+fn vtable_nop_cast() {
+    let ptr: &dyn fmt::Debug = &0;
+    // We transmute things around, but the principal trait does not change, so this is allowed.
+    let ptr: *const (dyn fmt::Debug + Send + Sync) = unsafe { std::mem::transmute(ptr) };
+    // This cast is a NOP and should be allowed.
+    let _ptr2 = ptr as *const dyn fmt::Debug;
 }
 
 fn basic() {
-    trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+    trait Foo: PartialEq<i32> + fmt::Debug + Send + Sync {
         fn a(&self) -> i32 {
             10
         }
@@ -67,7 +69,7 @@ fn basic() {
     }
 
     let baz: &dyn Baz = &1;
-    let _: &dyn std::fmt::Debug = baz;
+    let _: &dyn fmt::Debug = baz;
     assert_eq!(*baz, 1);
     assert_eq!(baz.a(), 100);
     assert_eq!(baz.b(), 200);
@@ -77,7 +79,7 @@ fn basic() {
     assert_eq!(baz.w(), 21);
 
     let bar: &dyn Bar = baz;
-    let _: &dyn std::fmt::Debug = bar;
+    let _: &dyn fmt::Debug = bar;
     assert_eq!(*bar, 1);
     assert_eq!(bar.a(), 100);
     assert_eq!(bar.b(), 200);
@@ -86,14 +88,14 @@ fn basic() {
     assert_eq!(bar.w(), 21);
 
     let foo: &dyn Foo = baz;
-    let _: &dyn std::fmt::Debug = foo;
+    let _: &dyn fmt::Debug = foo;
     assert_eq!(*foo, 1);
     assert_eq!(foo.a(), 100);
     assert_eq!(foo.z(), 11);
     assert_eq!(foo.y(), 12);
 
     let foo: &dyn Foo = bar;
-    let _: &dyn std::fmt::Debug = foo;
+    let _: &dyn fmt::Debug = foo;
     assert_eq!(*foo, 1);
     assert_eq!(foo.a(), 100);
     assert_eq!(foo.z(), 11);
@@ -101,7 +103,7 @@ fn basic() {
 }
 
 fn diamond() {
-    trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+    trait Foo: PartialEq<i32> + fmt::Debug + Send + Sync {
         fn a(&self) -> i32 {
             10
         }
@@ -166,7 +168,7 @@ fn diamond() {
     }
 
     let baz: &dyn Baz = &1;
-    let _: &dyn std::fmt::Debug = baz;
+    let _: &dyn fmt::Debug = baz;
     assert_eq!(*baz, 1);
     assert_eq!(baz.a(), 100);
     assert_eq!(baz.b(), 200);
@@ -178,7 +180,7 @@ fn diamond() {
     assert_eq!(baz.v(), 31);
 
     let bar1: &dyn Bar1 = baz;
-    let _: &dyn std::fmt::Debug = bar1;
+    let _: &dyn fmt::Debug = bar1;
     assert_eq!(*bar1, 1);
     assert_eq!(bar1.a(), 100);
     assert_eq!(bar1.b(), 200);
@@ -187,7 +189,7 @@ fn diamond() {
     assert_eq!(bar1.w(), 21);
 
     let bar2: &dyn Bar2 = baz;
-    let _: &dyn std::fmt::Debug = bar2;
+    let _: &dyn fmt::Debug = bar2;
     assert_eq!(*bar2, 1);
     assert_eq!(bar2.a(), 100);
     assert_eq!(bar2.c(), 300);
@@ -196,17 +198,17 @@ fn diamond() {
     assert_eq!(bar2.v(), 31);
 
     let foo: &dyn Foo = baz;
-    let _: &dyn std::fmt::Debug = foo;
+    let _: &dyn fmt::Debug = foo;
     assert_eq!(*foo, 1);
     assert_eq!(foo.a(), 100);
 
     let foo: &dyn Foo = bar1;
-    let _: &dyn std::fmt::Debug = foo;
+    let _: &dyn fmt::Debug = foo;
     assert_eq!(*foo, 1);
     assert_eq!(foo.a(), 100);
 
     let foo: &dyn Foo = bar2;
-    let _: &dyn std::fmt::Debug = foo;
+    let _: &dyn fmt::Debug = foo;
     assert_eq!(*foo, 1);
     assert_eq!(foo.a(), 100);
 }
@@ -215,7 +217,7 @@ fn struct_() {
     use std::rc::Rc;
     use std::sync::Arc;
 
-    trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
+    trait Foo: PartialEq<i32> + fmt::Debug + Send + Sync {
         fn a(&self) -> i32 {
             10
         }
diff --git a/src/tools/rustfmt/tests/source/attrib.rs b/src/tools/rustfmt/tests/source/attrib.rs
index d45fba55224..fc13cd02b03 100644
--- a/src/tools/rustfmt/tests/source/attrib.rs
+++ b/src/tools/rustfmt/tests/source/attrib.rs
@@ -214,8 +214,8 @@ type Os = NoSource;
 // #3313
 fn stmt_expr_attributes() {
     let foo ;
-    #[must_use]
-   foo = false ;
+    (#[must_use]
+   foo) = false ;
 }
 
 // #3509
diff --git a/src/tools/rustfmt/tests/target/attrib.rs b/src/tools/rustfmt/tests/target/attrib.rs
index 7e61f68d76a..7b3309676de 100644
--- a/src/tools/rustfmt/tests/target/attrib.rs
+++ b/src/tools/rustfmt/tests/target/attrib.rs
@@ -248,8 +248,8 @@ type Os = NoSource;
 // #3313
 fn stmt_expr_attributes() {
     let foo;
-    #[must_use]
-    foo = false;
+    (#[must_use]
+    foo) = false;
 }
 
 // #3509
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index f380513f4ef..1d24c59b356 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -491,6 +491,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "windows_aarch64_gnullvm",
     "windows_aarch64_msvc",
     "windows_i686_gnu",
+    "windows_i686_gnullvm",
     "windows_i686_msvc",
     "windows_x86_64_gnu",
     "windows_x86_64_gnullvm",
diff --git a/tests/codegen/intrinsics/ctlz.rs b/tests/codegen/intrinsics/ctlz.rs
new file mode 100644
index 00000000000..0d54d21ce12
--- /dev/null
+++ b/tests/codegen/intrinsics/ctlz.rs
@@ -0,0 +1,56 @@
+//@ compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{ctlz, ctlz_nonzero};
+
+// CHECK-LABEL: @ctlz_u16
+#[no_mangle]
+pub unsafe fn ctlz_u16(x: u16) -> u32 {
+    // CHECK: %[[tmp:.*]] = call i16 @llvm.ctlz.i16(i16 %x, i1 false)
+    // CHECK: zext i16 %[[tmp]] to i32
+    ctlz(x)
+}
+
+// CHECK-LABEL: @ctlz_nzu16
+#[no_mangle]
+pub unsafe fn ctlz_nzu16(x: u16) -> u32 {
+    // CHECK: %[[tmp:.*]] = call i16 @llvm.ctlz.i16(i16 %x, i1 true)
+    // CHECK: zext i16 %[[tmp]] to i32
+    ctlz_nonzero(x)
+}
+
+// CHECK-LABEL: @ctlz_u32
+#[no_mangle]
+pub unsafe fn ctlz_u32(x: u32) -> u32 {
+    // CHECK: call i32 @llvm.ctlz.i32(i32 %x, i1 false)
+    // CHECK-NOT: zext
+    // CHECK-NOT: trunc
+    ctlz(x)
+}
+
+// CHECK-LABEL: @ctlz_nzu32
+#[no_mangle]
+pub unsafe fn ctlz_nzu32(x: u32) -> u32 {
+    // CHECK: call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+    // CHECK-NOT: zext
+    // CHECK-NOT: trunc
+    ctlz_nonzero(x)
+}
+
+// CHECK-LABEL: @ctlz_u64
+#[no_mangle]
+pub unsafe fn ctlz_u64(x: u64) -> u32 {
+    // CHECK: %[[tmp:.*]] = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+    // CHECK: trunc i64 %[[tmp]] to i32
+    ctlz(x)
+}
+
+// CHECK-LABEL: @ctlz_nzu64
+#[no_mangle]
+pub unsafe fn ctlz_nzu64(x: u64) -> u32 {
+    // CHECK: %[[tmp:.*]] = call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+    // CHECK: trunc i64 %[[tmp]] to i32
+    ctlz_nonzero(x)
+}
diff --git a/tests/codegen/intrinsics/ctpop.rs b/tests/codegen/intrinsics/ctpop.rs
new file mode 100644
index 00000000000..f4043325de9
--- /dev/null
+++ b/tests/codegen/intrinsics/ctpop.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::ctpop;
+
+// CHECK-LABEL: @ctpop_u16
+#[no_mangle]
+pub unsafe fn ctpop_u16(x: u16) -> u32 {
+    // CHECK: %[[tmp:.*]] = call i16 @llvm.ctpop.i16(i16 %x)
+    // CHECK: zext i16 %[[tmp]] to i32
+    ctpop(x)
+}
+
+// CHECK-LABEL: @ctpop_u32
+#[no_mangle]
+pub unsafe fn ctpop_u32(x: u32) -> u32 {
+    // CHECK: call i32 @llvm.ctpop.i32(i32 %x)
+    // CHECK-NOT: zext
+    // CHECK-NOT: trunc
+    ctpop(x)
+}
+
+// CHECK-LABEL: @ctpop_u64
+#[no_mangle]
+pub unsafe fn ctpop_u64(x: u64) -> u32 {
+    // CHECK: %[[tmp:.*]] = call i64 @llvm.ctpop.i64(i64 %x)
+    // CHECK: trunc i64 %[[tmp]] to i32
+    ctpop(x)
+}
diff --git a/tests/codegen/intrinsics/rotate_left.rs b/tests/codegen/intrinsics/rotate_left.rs
new file mode 100644
index 00000000000..4f6c5cbaed6
--- /dev/null
+++ b/tests/codegen/intrinsics/rotate_left.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::rotate_left;
+
+// CHECK-LABEL: @rotate_left_u16
+#[no_mangle]
+pub unsafe fn rotate_left_u16(x: u16, shift: u32) -> u16 {
+    // CHECK: %[[tmp:.*]] = trunc i32 %shift to i16
+    // CHECK: call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %[[tmp]])
+    rotate_left(x, shift)
+}
+
+// CHECK-LABEL: @rotate_left_u32
+#[no_mangle]
+pub unsafe fn rotate_left_u32(x: u32, shift: u32) -> u32 {
+    // CHECK-NOT: trunc
+    // CHECK-NOT: zext
+    // CHECK: call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %shift)
+    rotate_left(x, shift)
+}
+
+// CHECK-LABEL: @rotate_left_u64
+#[no_mangle]
+pub unsafe fn rotate_left_u64(x: u64, shift: u32) -> u64 {
+    // CHECK: %[[tmp:.*]] = zext i32 %shift to i64
+    // CHECK: call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %[[tmp]])
+    rotate_left(x, shift)
+}
diff --git a/tests/crashes/122552.rs b/tests/crashes/122552.rs
deleted file mode 100644
index 29566941e22..00000000000
--- a/tests/crashes/122552.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ known-bug: #122552
-//@ edition:2021
-
-trait X {
-    fn line_stream<'a, Repr>() -> Self::LineStreamFut<{ async {} }, Repr>;
-}
-
-struct Y;
-
-pub fn main() {}
diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
index 194afdf7dd8..bade0fa4b45 100644
--- a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
@@ -4,8 +4,8 @@ fn full_tested_match() -> () {
     let mut _0: ();
     let mut _1: (i32, i32);
     let mut _2: std::option::Option<i32>;
-    let mut _3: isize;
-    let mut _4: &std::option::Option<i32>;
+    let mut _3: &std::option::Option<i32>;
+    let mut _4: isize;
     let _5: i32;
     let _6: &i32;
     let mut _7: bool;
@@ -27,8 +27,8 @@ fn full_tested_match() -> () {
         StorageLive(_2);
         _2 = Option::<i32>::Some(const 42_i32);
         PlaceMention(_2);
-        _3 = discriminant(_2);
-        switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1];
+        _4 = discriminant(_2);
+        switchInt(move _4) -> [0: bb5, 1: bb2, otherwise: bb1];
     }
 
     bb1: {
@@ -60,7 +60,7 @@ fn full_tested_match() -> () {
     bb7: {
         StorageLive(_6);
         _6 = &((_2 as Some).0: i32);
-        _4 = &fake _2;
+        _3 = &fake shallow _2;
         StorageLive(_7);
         _7 = guard() -> [return: bb8, unwind: bb16];
     }
@@ -71,7 +71,7 @@ fn full_tested_match() -> () {
 
     bb9: {
         StorageDead(_7);
-        FakeRead(ForMatchGuard, _4);
+        FakeRead(ForMatchGuard, _3);
         FakeRead(ForGuardBinding, _6);
         StorageLive(_5);
         _5 = ((_2 as Some).0: i32);
diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
index ae83075434f..0d78bb8b235 100644
--- a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
@@ -4,8 +4,8 @@ fn full_tested_match2() -> () {
     let mut _0: ();
     let mut _1: (i32, i32);
     let mut _2: std::option::Option<i32>;
-    let mut _3: isize;
-    let mut _4: &std::option::Option<i32>;
+    let mut _3: &std::option::Option<i32>;
+    let mut _4: isize;
     let _5: i32;
     let _6: &i32;
     let mut _7: bool;
@@ -27,8 +27,8 @@ fn full_tested_match2() -> () {
         StorageLive(_2);
         _2 = Option::<i32>::Some(const 42_i32);
         PlaceMention(_2);
-        _3 = discriminant(_2);
-        switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1];
+        _4 = discriminant(_2);
+        switchInt(move _4) -> [0: bb5, 1: bb2, otherwise: bb1];
     }
 
     bb1: {
@@ -66,7 +66,7 @@ fn full_tested_match2() -> () {
     bb7: {
         StorageLive(_6);
         _6 = &((_2 as Some).0: i32);
-        _4 = &fake _2;
+        _3 = &fake shallow _2;
         StorageLive(_7);
         _7 = guard() -> [return: bb8, unwind: bb16];
     }
@@ -77,7 +77,7 @@ fn full_tested_match2() -> () {
 
     bb9: {
         StorageDead(_7);
-        FakeRead(ForMatchGuard, _4);
+        FakeRead(ForMatchGuard, _3);
         FakeRead(ForGuardBinding, _6);
         StorageLive(_5);
         _5 = ((_2 as Some).0: i32);
diff --git a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
index dfa31cfff6b..ebb75ae141a 100644
--- a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
@@ -4,9 +4,9 @@ fn main() -> () {
     let mut _0: ();
     let mut _1: i32;
     let mut _2: std::option::Option<i32>;
-    let mut _3: isize;
+    let mut _3: &std::option::Option<i32>;
     let mut _4: isize;
-    let mut _5: &std::option::Option<i32>;
+    let mut _5: isize;
     let _6: i32;
     let _7: &i32;
     let mut _8: bool;
@@ -38,8 +38,8 @@ fn main() -> () {
         StorageLive(_2);
         _2 = Option::<i32>::Some(const 1_i32);
         PlaceMention(_2);
-        _4 = discriminant(_2);
-        switchInt(move _4) -> [1: bb8, otherwise: bb2];
+        _5 = discriminant(_2);
+        switchInt(move _5) -> [1: bb8, otherwise: bb2];
     }
 
     bb1: {
@@ -52,8 +52,8 @@ fn main() -> () {
     }
 
     bb3: {
-        _3 = discriminant(_2);
-        switchInt(move _3) -> [1: bb6, otherwise: bb4];
+        _4 = discriminant(_2);
+        switchInt(move _4) -> [1: bb6, otherwise: bb4];
     }
 
     bb4: {
@@ -87,7 +87,7 @@ fn main() -> () {
     bb10: {
         StorageLive(_7);
         _7 = &((_2 as Some).0: i32);
-        _5 = &fake _2;
+        _3 = &fake shallow _2;
         StorageLive(_8);
         _8 = guard() -> [return: bb11, unwind: bb24];
     }
@@ -98,7 +98,7 @@ fn main() -> () {
 
     bb12: {
         StorageDead(_8);
-        FakeRead(ForMatchGuard, _5);
+        FakeRead(ForMatchGuard, _3);
         FakeRead(ForGuardBinding, _7);
         StorageLive(_6);
         _6 = ((_2 as Some).0: i32);
@@ -129,7 +129,7 @@ fn main() -> () {
     bb16: {
         StorageLive(_11);
         _11 = &((_2 as Some).0: i32);
-        _5 = &fake _2;
+        _3 = &fake shallow _2;
         StorageLive(_12);
         StorageLive(_13);
         _13 = (*_11);
@@ -143,7 +143,7 @@ fn main() -> () {
     bb18: {
         StorageDead(_13);
         StorageDead(_12);
-        FakeRead(ForMatchGuard, _5);
+        FakeRead(ForMatchGuard, _3);
         FakeRead(ForGuardBinding, _11);
         StorageLive(_10);
         _10 = ((_2 as Some).0: i32);
diff --git a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
index c3497c6989d..060cd6132e3 100644
--- a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
@@ -7,10 +7,10 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     let mut _3: (&str, bool);
     let mut _4: &str;
     let mut _5: bool;
-    let mut _6: bool;
-    let mut _7: bool;
-    let mut _8: &&str;
-    let mut _9: &bool;
+    let mut _6: &&str;
+    let mut _7: &bool;
+    let mut _8: bool;
+    let mut _9: bool;
     let mut _10: bool;
 
     bb0: {
@@ -23,7 +23,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
         StorageDead(_5);
         StorageDead(_4);
         PlaceMention(_3);
-        _7 = <str as PartialEq>::eq((_3.0: &str), const "a") -> [return: bb11, unwind: bb19];
+        _9 = <str as PartialEq>::eq((_3.0: &str), const "a") -> [return: bb11, unwind: bb19];
     }
 
     bb1: {
@@ -52,7 +52,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     }
 
     bb7: {
-        _6 = <str as PartialEq>::eq((_3.0: &str), const "b") -> [return: bb10, unwind: bb19];
+        _8 = <str as PartialEq>::eq((_3.0: &str), const "b") -> [return: bb10, unwind: bb19];
     }
 
     bb8: {
@@ -64,16 +64,16 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     }
 
     bb10: {
-        switchInt(move _6) -> [0: bb1, otherwise: bb8];
+        switchInt(move _8) -> [0: bb1, otherwise: bb8];
     }
 
     bb11: {
-        switchInt(move _7) -> [0: bb7, otherwise: bb4];
+        switchInt(move _9) -> [0: bb7, otherwise: bb4];
     }
 
     bb12: {
-        _8 = &fake (_3.0: &str);
-        _9 = &fake (_3.1: bool);
+        _6 = &fake shallow (_3.0: &str);
+        _7 = &fake shallow (_3.1: bool);
         StorageLive(_10);
         _10 = const true;
         switchInt(move _10) -> [0: bb14, otherwise: bb13];
@@ -81,8 +81,8 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
 
     bb13: {
         StorageDead(_10);
-        FakeRead(ForMatchGuard, _8);
-        FakeRead(ForMatchGuard, _9);
+        FakeRead(ForMatchGuard, _6);
+        FakeRead(ForMatchGuard, _7);
         _0 = const 1_u32;
         goto -> bb18;
     }
diff --git a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
index 4a1e4fb9ec5..07daa3eddfa 100644
--- a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
@@ -4,17 +4,17 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     debug x => _1;
     debug b => _2;
     let mut _0: u32;
-    let mut _3: bool;
+    let mut _3: &i32;
     let mut _4: bool;
     let mut _5: bool;
     let mut _6: bool;
-    let mut _7: &i32;
+    let mut _7: bool;
     let mut _8: bool;
 
     bb0: {
         PlaceMention(_1);
-        _5 = Le(const 0_i32, _1);
-        switchInt(move _5) -> [0: bb3, otherwise: bb8];
+        _6 = Le(const 0_i32, _1);
+        switchInt(move _6) -> [0: bb3, otherwise: bb8];
     }
 
     bb1: {
@@ -27,8 +27,8 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     }
 
     bb3: {
-        _3 = Le(const 10_i32, _1);
-        switchInt(move _3) -> [0: bb5, otherwise: bb7];
+        _4 = Le(const 10_i32, _1);
+        switchInt(move _4) -> [0: bb5, otherwise: bb7];
     }
 
     bb4: {
@@ -44,17 +44,17 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     }
 
     bb7: {
-        _4 = Le(_1, const 20_i32);
-        switchInt(move _4) -> [0: bb5, otherwise: bb4];
+        _5 = Le(_1, const 20_i32);
+        switchInt(move _5) -> [0: bb5, otherwise: bb4];
     }
 
     bb8: {
-        _6 = Lt(_1, const 10_i32);
-        switchInt(move _6) -> [0: bb3, otherwise: bb2];
+        _7 = Lt(_1, const 10_i32);
+        switchInt(move _7) -> [0: bb3, otherwise: bb2];
     }
 
     bb9: {
-        _7 = &fake _1;
+        _3 = &fake shallow _1;
         StorageLive(_8);
         _8 = _2;
         switchInt(move _8) -> [0: bb11, otherwise: bb10];
@@ -62,7 +62,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
 
     bb10: {
         StorageDead(_8);
-        FakeRead(ForMatchGuard, _7);
+        FakeRead(ForMatchGuard, _3);
         _0 = const 0_u32;
         goto -> bb14;
     }
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index ba333ba1a58..209f0d09c29 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -80,8 +80,8 @@
           _6 = &(_2.1: bool);
           StorageLive(_8);
           _8 = &(_2.2: std::string::String);
--         _3 = &fake (_2.0: bool);
--         _4 = &fake (_2.1: bool);
+-         _3 = &fake shallow (_2.0: bool);
+-         _4 = &fake shallow (_2.1: bool);
           StorageLive(_9);
           StorageLive(_10);
           _10 = _1;
@@ -137,8 +137,8 @@
           _6 = &(_2.0: bool);
           StorageLive(_8);
           _8 = &(_2.2: std::string::String);
--         _3 = &fake (_2.0: bool);
--         _4 = &fake (_2.1: bool);
+-         _3 = &fake shallow (_2.0: bool);
+-         _4 = &fake shallow (_2.1: bool);
           StorageLive(_12);
           StorageLive(_13);
           _13 = _1;
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index ba333ba1a58..209f0d09c29 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -80,8 +80,8 @@
           _6 = &(_2.1: bool);
           StorageLive(_8);
           _8 = &(_2.2: std::string::String);
--         _3 = &fake (_2.0: bool);
--         _4 = &fake (_2.1: bool);
+-         _3 = &fake shallow (_2.0: bool);
+-         _4 = &fake shallow (_2.1: bool);
           StorageLive(_9);
           StorageLive(_10);
           _10 = _1;
@@ -137,8 +137,8 @@
           _6 = &(_2.0: bool);
           StorageLive(_8);
           _8 = &(_2.2: std::string::String);
--         _3 = &fake (_2.0: bool);
--         _4 = &fake (_2.1: bool);
+-         _3 = &fake shallow (_2.0: bool);
+-         _4 = &fake shallow (_2.1: bool);
           StorageLive(_12);
           StorageLive(_13);
           _13 = _1;
diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff
index 54da6ee659f..d76d65a18a7 100644
--- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff
+++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff
@@ -5,17 +5,17 @@
       debug x => _1;
       debug c => _2;
       let mut _0: i32;
-      let mut _3: isize;
-      let mut _4: &std::option::Option<&&i32>;
+      let mut _3: &std::option::Option<&&i32>;
+      let mut _4: &i32;
       let mut _5: &&i32;
       let mut _6: &&&i32;
-      let mut _7: &i32;
+      let mut _7: isize;
       let mut _8: bool;
   
       bb0: {
           PlaceMention(_1);
-          _3 = discriminant(_1);
-          switchInt(move _3) -> [1: bb2, otherwise: bb1];
+          _7 = discriminant(_1);
+          switchInt(move _7) -> [1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -33,10 +33,10 @@
       }
   
       bb4: {
--         _4 = &fake _1;
--         _5 = &fake (*((_1 as Some).0: &&i32));
--         _6 = &fake ((_1 as Some).0: &&i32);
--         _7 = &fake (*(*((_1 as Some).0: &&i32)));
+-         _3 = &fake shallow _1;
+-         _4 = &fake shallow (*(*((_1 as Some).0: &&i32)));
+-         _5 = &fake shallow (*((_1 as Some).0: &&i32));
+-         _6 = &fake shallow ((_1 as Some).0: &&i32);
 +         nop;
 +         nop;
 +         nop;
@@ -48,10 +48,10 @@
   
       bb5: {
           StorageDead(_8);
+-         FakeRead(ForMatchGuard, _3);
 -         FakeRead(ForMatchGuard, _4);
 -         FakeRead(ForMatchGuard, _5);
 -         FakeRead(ForMatchGuard, _6);
--         FakeRead(ForMatchGuard, _7);
 +         nop;
 +         nop;
 +         nop;
diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff
index 54da6ee659f..d76d65a18a7 100644
--- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff
+++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff
@@ -5,17 +5,17 @@
       debug x => _1;
       debug c => _2;
       let mut _0: i32;
-      let mut _3: isize;
-      let mut _4: &std::option::Option<&&i32>;
+      let mut _3: &std::option::Option<&&i32>;
+      let mut _4: &i32;
       let mut _5: &&i32;
       let mut _6: &&&i32;
-      let mut _7: &i32;
+      let mut _7: isize;
       let mut _8: bool;
   
       bb0: {
           PlaceMention(_1);
-          _3 = discriminant(_1);
-          switchInt(move _3) -> [1: bb2, otherwise: bb1];
+          _7 = discriminant(_1);
+          switchInt(move _7) -> [1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -33,10 +33,10 @@
       }
   
       bb4: {
--         _4 = &fake _1;
--         _5 = &fake (*((_1 as Some).0: &&i32));
--         _6 = &fake ((_1 as Some).0: &&i32);
--         _7 = &fake (*(*((_1 as Some).0: &&i32)));
+-         _3 = &fake shallow _1;
+-         _4 = &fake shallow (*(*((_1 as Some).0: &&i32)));
+-         _5 = &fake shallow (*((_1 as Some).0: &&i32));
+-         _6 = &fake shallow ((_1 as Some).0: &&i32);
 +         nop;
 +         nop;
 +         nop;
@@ -48,10 +48,10 @@
   
       bb5: {
           StorageDead(_8);
+-         FakeRead(ForMatchGuard, _3);
 -         FakeRead(ForMatchGuard, _4);
 -         FakeRead(ForMatchGuard, _5);
 -         FakeRead(ForMatchGuard, _6);
--         FakeRead(ForMatchGuard, _7);
 +         nop;
 +         nop;
 +         nop;
diff --git a/tests/pretty/ast-stmt-expr-attr.rs b/tests/pretty/ast-stmt-expr-attr.rs
index fd7272a1b1f..899f7173f70 100644
--- a/tests/pretty/ast-stmt-expr-attr.rs
+++ b/tests/pretty/ast-stmt-expr-attr.rs
@@ -13,17 +13,17 @@ fn syntax() {
     let _ = #[attr] ();
     let _ = #[attr] (#[attr] 0,);
     let _ = #[attr] (#[attr] 0, 0);
-    let _ = #[attr] 0 + #[attr] 0;
-    let _ = #[attr] 0 / #[attr] 0;
-    let _ = #[attr] 0 & #[attr] 0;
-    let _ = #[attr] 0 % #[attr] 0;
+    let _ = (#[attr] 0) + #[attr] 0;
+    let _ = (#[attr] 0) / #[attr] 0;
+    let _ = (#[attr] 0) & #[attr] 0;
+    let _ = (#[attr] 0) % #[attr] 0;
     let _ = #[attr] (0 + 0);
     let _ = #[attr] !0;
     let _ = #[attr] -0;
     let _ = #[attr] false;
     let _ = #[attr] 0;
     let _ = #[attr] 'c';
-    let _ = #[attr] x as Y;
+    let _ = (#[attr] x) as Y;
     let _ = #[attr] (x as Y);
     let _ =
         #[attr] while true {
@@ -88,9 +88,9 @@ fn syntax() {
             let _ = ();
             foo
         };
-    let _ = #[attr] x = y;
+    let _ = (#[attr] x) = y;
     let _ = #[attr] (x = y);
-    let _ = #[attr] x += y;
+    let _ = (#[attr] x) += y;
     let _ = #[attr] (x += y);
     let _ = #[attr] foo.bar;
     let _ = (#[attr] foo).bar;
@@ -98,8 +98,8 @@ fn syntax() {
     let _ = (#[attr] foo).0;
     let _ = #[attr] foo[bar];
     let _ = (#[attr] foo)[bar];
-    let _ = #[attr] 0..#[attr] 0;
-    let _ = #[attr] 0..;
+    let _ = (#[attr] 0)..#[attr] 0;
+    let _ = (#[attr] 0)..;
     let _ = #[attr] (0..0);
     let _ = #[attr] (0..);
     let _ = #[attr] (..0);
diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs
index 98ad98b863a..5076adf5aa4 100644
--- a/tests/pretty/stmt_expr_attributes.rs
+++ b/tests/pretty/stmt_expr_attributes.rs
@@ -148,13 +148,13 @@ fn _11() {
     let _ = #[rustc_dummy] (0);
     let _ = #[rustc_dummy] (0,);
     let _ = #[rustc_dummy] (0, 0);
-    let _ = #[rustc_dummy] 0 + #[rustc_dummy] 0;
+    let _ = (#[rustc_dummy] 0) + #[rustc_dummy] 0;
     let _ = #[rustc_dummy] !0;
     let _ = #[rustc_dummy] -0i32;
     let _ = #[rustc_dummy] false;
     let _ = #[rustc_dummy] 'c';
     let _ = #[rustc_dummy] 0;
-    let _ = #[rustc_dummy] 0 as usize;
+    let _ = (#[rustc_dummy] 0) as usize;
     let _ =
         #[rustc_dummy] while false {
             #![rustc_dummy]
@@ -214,8 +214,8 @@ fn _11() {
                 #![rustc_dummy]
             };
     let mut x = 0;
-    let _ = #[rustc_dummy] x = 15;
-    let _ = #[rustc_dummy] x += 15;
+    let _ = (#[rustc_dummy] x) = 15;
+    let _ = (#[rustc_dummy] x) += 15;
     let s = Foo { data: () };
     let _ = #[rustc_dummy] s.data;
     let _ = (#[rustc_dummy] s).data;
@@ -225,8 +225,8 @@ fn _11() {
     let v = vec!(0);
     let _ = #[rustc_dummy] v[0];
     let _ = (#[rustc_dummy] v)[0];
-    let _ = #[rustc_dummy] 0..#[rustc_dummy] 0;
-    let _ = #[rustc_dummy] 0..;
+    let _ = (#[rustc_dummy] 0)..#[rustc_dummy] 0;
+    let _ = (#[rustc_dummy] 0)..;
     let _ = #[rustc_dummy] (0..0);
     let _ = #[rustc_dummy] (0..);
     let _ = #[rustc_dummy] (..0);
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index 34fafe9a141..6ee810c5768 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -2,47 +2,70 @@
 include: "utils.goml"
 go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
 show-text: true
-// We start with a wide screen.
-set-window-size: (1100, 600)
-// Checking they have the same y position.
-compare-elements-position: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    ["y"],
-)
-// Checking they don't have the same x position.
-compare-elements-position-false: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    ["x"],
-)
-// The `i` should be *after* the type.
-assert-position: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    {"x": 677},
-)
-assert-position: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    {"x": 955},
-)
-// The tooltip should be below the `i`
-// Also, clicking the tooltip should bring its text into the DOM
-assert-count: ("//*[@class='tooltip popover']", 0)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-assert-count: ("//*[@class='tooltip popover']", 1)
-compare-elements-position-near: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    "//*[@class='tooltip popover']",
-    {"y": 30}
+
+define-function: (
+    "check-notable-tooltip-position",
+    [x, i_x],
+    block {
+        // Checking they have the same y position.
+        compare-elements-position: (
+            "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+            "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+            ["y"],
+        )
+        // Checking they don't have the same x position.
+        compare-elements-position-false: (
+            "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+            "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+            ["x"],
+        )
+        // The `i` should be *after* the type.
+        assert-position: (
+            "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+            {"x": |x|},
+        )
+        assert-position: (
+            "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+            {"x": |i_x|},
+        )
+    },
 )
-compare-elements-position-false: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    "//*[@class='tooltip popover']",
-    ["x"]
+
+define-function: (
+    "check-notable-tooltip-position-complete",
+    [x, i_x, popover_x],
+    block {
+        call-function: ("check-notable-tooltip-position", {"x": |x|, "i_x": |i_x|})
+        assert-count: ("//*[@class='tooltip popover']", 0)
+        click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+        assert-count: ("//*[@class='tooltip popover']", 1)
+        compare-elements-position-near: (
+            "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+            "//*[@class='tooltip popover']",
+            {"y": 30}
+        )
+        compare-elements-position-false: (
+            "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+            "//*[@class='tooltip popover']",
+            ["x"]
+        )
+        assert-position: (
+            "//*[@class='tooltip popover']",
+            {"x": |popover_x|}
+        )
+        click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+        move-cursor-to: "//h1"
+        assert-count: ("//*[@class='tooltip popover']", 0)
+    },
 )
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-move-cursor-to: "//h1"
-assert-count: ("//*[@class='tooltip popover']", 0)
+
+// We start with a wide screen.
+set-window-size: (1100, 600)
+call-function: ("check-notable-tooltip-position-complete", {
+    "x": 677,
+    "i_x": 955,
+    "popover_x": 463,
+})
 
 // Now only the `i` should be on the next line.
 set-window-size: (1055, 600)
@@ -54,71 +77,18 @@ compare-elements-position-false: (
 
 // Now both the `i` and the struct name should be on the next line.
 set-window-size: (980, 600)
-// Checking they have the same y position.
-compare-elements-position: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    ["y"],
-)
-// Checking they don't have the same x position.
-compare-elements-position-false: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    ["x"],
-)
-// The `i` should be *after* the type.
-assert-position: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    {"x": 245},
-)
-assert-position: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    {"x": 523},
-)
+call-function: ("check-notable-tooltip-position", {
+    "x": 245,
+    "i_x": 523,
+})
 
 // Checking on mobile now.
 set-window-size: (650, 600)
-// Checking they have the same y position.
-compare-elements-position: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    ["y"],
-)
-// Checking they don't have the same x position.
-compare-elements-position-false: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    ["x"],
-)
-// The `i` should be *after* the type.
-assert-position: (
-    "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
-    {"x": 15},
-)
-assert-position: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    {"x": 293},
-)
-// The tooltip should STILL be below `i`
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-assert-count: ("//*[@class='tooltip popover']", 1)
-compare-elements-position-near: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    "//*[@class='tooltip popover']",
-    {"y": 30}
-)
-compare-elements-position-false: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
-    "//*[@class='tooltip popover']",
-    ["x"]
-)
-assert-position: (
-    "//*[@class='tooltip popover']",
-    {"x": 0}
-)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-move-cursor-to: "//h1"
-assert-count: ("//*[@class='tooltip popover']", 0)
+call-function: ("check-notable-tooltip-position-complete", {
+    "x": 15,
+    "i_x": 293,
+    "popover_x": 0,
+})
 
 // Now check the colors.
 define-function: (
@@ -236,31 +206,31 @@ press-key: "Tab"
 assert-count: ("//*[@class='tooltip popover']", 0)
 assert: "#method\.create_an_iterator_from_read .tooltip:focus"
 
+define-function: (
+    "setup-popup",
+    [],
+    block {
+        store-window-property: {"scrollY": scroll}
+        click: "#method\.create_an_iterator_from_read .fn"
+        // We ensure that the scroll position changed.
+        assert-window-property-false: {"scrollY": |scroll|}
+        // Store the new position.
+        store-window-property: {"scrollY": scroll}
+        click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+        wait-for: "//*[@class='tooltip popover']"
+        click: "#settings-menu a"
+    }
+)
+
 // Now we check that the focus isn't given back to the wrong item when opening
 // another popover.
-store-window-property: {"scrollY": scroll}
-click: "#method\.create_an_iterator_from_read .fn"
-// We ensure that the scroll position changed.
-assert-window-property-false: {"scrollY": |scroll|}
-// Store the new position.
-store-window-property: {"scrollY": scroll}
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-wait-for: "//*[@class='tooltip popover']"
-click: "#settings-menu a"
+call-function: ("setup-popup", {})
 click: ".search-input"
 // We ensure we didn't come back to the previous focused item.
 assert-window-property-false: {"scrollY": |scroll|}
 
 // Same but with Escape handling.
-store-window-property: {"scrollY": scroll}
-click: "#method\.create_an_iterator_from_read .fn"
-// We ensure that the scroll position changed.
-assert-window-property-false: {"scrollY": |scroll|}
-// Store the new position.
-store-window-property: {"scrollY": scroll}
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-wait-for: "//*[@class='tooltip popover']"
-click: "#settings-menu a"
+call-function: ("setup-popup", {})
 press-key: "Escape"
 // We ensure we didn't come back to the previous focused item.
 assert-window-property-false: {"scrollY": |scroll|}
diff --git a/tests/rustdoc-ui/invalid_associated_const.stderr b/tests/rustdoc-ui/invalid_associated_const.stderr
index 1eb6d2714e3..5eaddc2b8c9 100644
--- a/tests/rustdoc-ui/invalid_associated_const.stderr
+++ b/tests/rustdoc-ui/invalid_associated_const.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/invalid_associated_const.rs:4:17
@@ -11,6 +16,10 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/rustdoc-ui/issue-102467.stderr b/tests/rustdoc-ui/issue-102467.stderr
index f54a50a4e19..119ca949e99 100644
--- a/tests/rustdoc-ui/issue-102467.stderr
+++ b/tests/rustdoc-ui/issue-102467.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102467.rs:7:17
@@ -11,6 +16,10 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs
index 1d7417be58c..380b2b6c431 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs
@@ -59,7 +59,7 @@ impl Subdiagnostic for UntranslatableInAddtoDiag {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         diag.note("untranslatable diagnostic");
         //~^ ERROR diagnostics should be created using translatable messages
@@ -72,7 +72,7 @@ impl Subdiagnostic for TranslatableInAddtoDiag {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
-        f: F,
+        f: &F,
     ) {
         diag.note(crate::fluent_generated::no_crate_note);
     }
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 163af7ff0e2..659ae54f7a3 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -827,3 +827,13 @@ struct PrimarySpanOnVec {
     //~| NOTE there must be exactly one primary span
     sub: Vec<Span>,
 }
+
+#[derive(Subdiagnostic)]
+struct NestedParent {
+    #[subdiagnostic]
+    single_sub: A,
+    #[subdiagnostic]
+    option_sub: Option<A>,
+    #[subdiagnostic]
+    vec_sub: Vec<A>,
+}
diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs
index e7d852a27df..6345ee24f78 100644
--- a/tests/ui-fulldeps/stable-mir/check_transform.rs
+++ b/tests/ui-fulldeps/stable-mir/check_transform.rs
@@ -137,9 +137,9 @@ fn generate_input(path: &str) -> std::io::Result<()> {
     write!(
         file,
         r#"
-        #![feature(panic_internals)]
+        fn panic_str(msg: &str) {{ panic!("{{}}", msg); }}
         pub fn dummy() {{
-            core::panicking::panic_str("oops");
+            panic_str("oops");
         }}
         "#
     )?;
diff --git a/tests/ui/assoc-lang-items.stderr b/tests/ui/assoc-lang-items.stderr
index 040792fb1cd..59aec8e3fdc 100644
--- a/tests/ui/assoc-lang-items.stderr
+++ b/tests/ui/assoc-lang-items.stderr
@@ -1,26 +1,26 @@
-error[E0522]: definition of an unknown language item: `dummy_lang_item_1`
+error[E0522]: definition of an unknown lang item: `dummy_lang_item_1`
   --> $DIR/assoc-lang-items.rs:4:5
    |
 LL |     #[lang = "dummy_lang_item_1"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_1`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_1`
 
-error[E0522]: definition of an unknown language item: `dummy_lang_item_2`
+error[E0522]: definition of an unknown lang item: `dummy_lang_item_2`
   --> $DIR/assoc-lang-items.rs:7:5
    |
 LL |     #[lang = "dummy_lang_item_2"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_2`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_2`
 
-error[E0522]: definition of an unknown language item: `dummy_lang_item_3`
+error[E0522]: definition of an unknown lang item: `dummy_lang_item_3`
   --> $DIR/assoc-lang-items.rs:10:5
    |
 LL |     #[lang = "dummy_lang_item_3"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_3`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_3`
 
-error[E0522]: definition of an unknown language item: `dummy_lang_item_4`
+error[E0522]: definition of an unknown lang item: `dummy_lang_item_4`
   --> $DIR/assoc-lang-items.rs:17:5
    |
 LL |     #[lang = "dummy_lang_item_4"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_4`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_4`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr
index 2a70425a3cc..905d7c75c20 100644
--- a/tests/ui/associated-consts/issue-102335-const.stderr
+++ b/tests/ui/associated-consts/issue-102335-const.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-const.rs:4:17
@@ -11,6 +16,10 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.rs b/tests/ui/associated-type-bounds/issue-102335-ty.rs
index 5fd8b71e679..b2df68b18ae 100644
--- a/tests/ui/associated-type-bounds/issue-102335-ty.rs
+++ b/tests/ui/associated-type-bounds/issue-102335-ty.rs
@@ -1,5 +1,11 @@
 trait T {
-    type A: S<C<i32 = u32> = ()>;
+    type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+    //~^ ERROR associated type bindings are not allowed here
+    //~| ERROR associated type bindings are not allowed here
+}
+
+trait T2 {
+    type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
     //~^ ERROR associated type bindings are not allowed here
     //~| ERROR associated type bindings are not allowed here
 }
diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr
index 3bd7566ad1e..cf30b0a4f6c 100644
--- a/tests/ui/associated-type-bounds/issue-102335-ty.stderr
+++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr
@@ -1,17 +1,49 @@
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-ty.rs:2:17
    |
-LL |     type A: S<C<i32 = u32> = ()>;
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
    |                 ^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+   |                ~~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-ty.rs:2:17
    |
-LL |     type A: S<C<i32 = u32> = ()>;
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+   |                 ^^^^^^^^^ associated type not allowed here
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+   |                ~~~~~~~~~~~
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-102335-ty.rs:8:17
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+   |                 ^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+   |                 ~~~~~~~~~~
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-102335-ty.rs:8:17
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
    |                 ^^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+   |                 ~~~~~~~~~~
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0229`.
diff --git a/tests/ui/associated-types/associated-types-eq-2.rs b/tests/ui/associated-types/associated-types-eq-2.rs
index 18e38d44667..d71697e9a83 100644
--- a/tests/ui/associated-types/associated-types-eq-2.rs
+++ b/tests/ui/associated-types/associated-types-eq-2.rs
@@ -1,19 +1,125 @@
 // Test equality constraints on associated types. Check we get an error when an
-// equality constraint is used in a qualified path.
+// equality constraint is used in an invalid context
 
-pub trait Foo {
+struct Bar;
+struct Qux;
+
+// Tests for a a non generic trait
+pub trait Tr1 {
     type A;
-    fn boo(&self) -> <Self as Foo>::A;
+    fn boo(&self) -> <Self as Tr1>::A;
 }
 
-struct Bar;
-
-impl Foo for isize {
+impl Tr1 for isize {
     type A = usize;
     fn boo(&self) -> usize { 42 }
 }
 
-fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
+// Test for when the assoc type is
+// specified as an equality constraint
+impl Tr1<A = usize> for usize {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR not all trait items implemented, missing: `A`
+    fn boo(&self) -> usize { 42 }
+}
+
+// Test for a wronngly used equality constraint in a func arg
+fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+//~^ ERROR associated type bindings are not allowed here
+
+
+
+// Tests for a generic trait
+trait Tr2<T1, T2, T3> {
+}
+
+// Test for when wrongly specifed equality constraint's ident
+// matches some generic param's ident
+// (Note: E0229 is emitted only for the first erroneous equality
+// constraint (T2) not for any subequent ones (e.g. T3))
+impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when equality constraint's ident matches a
+// generic param's ident but has different case
+impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when equality constraint's ident
+// matches none of the generic param idents
+impl Tr2<i32, X = Qux, Y = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when the term in equality constraint is itself generic
+struct GenericTerm<T> { _t: T }
+impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 2 generic arguments were supplied
+}
+
+
+
+// Tests for a trait with a const param
+trait Tr3<const N: i32, T2, T3> {
+}
+
+// Test for when equality constraint's ident
+// matches the const param's ident
+// (Deliberately spread over multiple lines to test that
+// our suggestion spans are kosher in the face of such formatting)
+impl Tr3<N
 //~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+= 42, T2 = Qux, T3 = usize> for Bar {
+}
+
+// Test for when equality constraint's ident
+// matches the const param's ident but has a different case
+impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+}
+
+// Test for when equality constraint's ident
+// matches the const param ident but the constraint is a type arg
+impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+}
+
+// Test for when equality constraint's ident
+// matches a type param ident but the constraint is a const arg
+impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when equality constraint's ident
+// matches none of the param idents
+impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+}
+
+
+
+// Test for the case when lifetimes are present
+struct St<'a, T> { v: &'a T }
+
+impl<'a, T> St<'a , T = Qux> {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied
+}
+
 
 pub fn main() {}
diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr
index 447b8413ee2..b68c82f590c 100644
--- a/tests/ui/associated-types/associated-types-eq-2.stderr
+++ b/tests/ui/associated-types/associated-types-eq-2.stderr
@@ -1,9 +1,365 @@
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:76:10
+   |
+LL |   impl Tr3<N
+   |  __________^
+LL | |
+LL | |
+LL | |
+LL | | = 42, T2 = Qux, T3 = usize> for Bar {
+   | |____^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:85:10
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ^^^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:100:14
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |              ^^^^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:108:10
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |          ^^^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error[E0229]: associated type bindings are not allowed here
-  --> $DIR/associated-types-eq-2.rs:16:30
+  --> $DIR/associated-types-eq-2.rs:20:10
+   |
+LL | impl Tr1<A = usize> for usize {
+   |          ^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr1<A = usize> for usize {
+   |         ~~~~~~~~~~~
+
+error[E0046]: not all trait items implemented, missing: `A`
+  --> $DIR/associated-types-eq-2.rs:20:1
+   |
+LL |     type A;
+   |     ------ `A` from trait
+...
+LL | impl Tr1<A = usize> for usize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `A` in implementation
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:27:31
+   |
+LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+   |                               ^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+   |                              ~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:40:6
+   |
+LL | impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
+   |      ^^^ --- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr2<i32, T2, T3, T2 = Qux, T3 = usize> for Bar {
+   |             ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:40:15
+   |
+LL | impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
+   |               ^^^^^^^^ associated type not allowed here
+   |
+help: to use `Qux` as a generic argument specify it directly
+   |
+LL | impl Tr2<i32, Qux, T3 = usize> for Bar {
+   |               ~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:47:6
+   |
+LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+   |      ^^^ --- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr2<i32, T2, T3, t2 = Qux, T3 = usize> for Qux {
+   |             ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:47:15
+   |
+LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+   |               ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+   |             ~~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:54:6
+   |
+LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
+   |      ^^^ --- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr2<i32, T2, T3, X = Qux, Y = usize> for Bar {
+   |             ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:54:15
+   |
+LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
+   |               ^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
+   |             ~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 2 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:61:6
+   |
+LL | impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
+   |      ^^^ ---  --- supplied 2 generic arguments
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic argument
+   |
+LL | impl Tr2<i32, Qux, T3, T3 = GenericTerm<i32>> for Bar {
+   |                  ++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:61:20
+   |
+LL | impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
+   |                    ^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here
+   |
+help: to use `GenericTerm<i32>` as a generic argument specify it directly
+   |
+LL | impl Tr2<i32, Qux, GenericTerm<i32>> for Bar {
+   |                    ~~~~~~~~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:76:6
+   |
+LL | impl Tr3<N
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, N
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:76:10
+   |
+LL |   impl Tr3<N
+   |  __________^
+LL | |
+LL | |
+LL | |
+LL | | = 42, T2 = Qux, T3 = usize> for Bar {
+   | |____^ associated type not allowed here
+   |
+help: to use `42` as a generic argument specify it directly
+   |
+LL | impl Tr3<42, T2 = Qux, T3 = usize> for Bar {
+   |          ~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:85:6
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:85:10
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:93:6
+   |
+LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, N = u32, T2 = Qux, T3 = usize> for Bar {
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:93:10
+   |
+LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+   |          ^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+   |          ~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:100:6
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |      ^^^ -- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar {
+   |            ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:100:14
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |              ^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |            ~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:108:6
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, X = 42, Y = Qux, Z = usize> for Bar {
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:108:10
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |          ^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |          ~~~~~~~
+
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:119:13
+   |
+LL | impl<'a, T> St<'a , T = Qux> {
+   |             ^^ expected 1 generic argument
+   |
+note: struct defined here, with 1 generic parameter: `T`
+  --> $DIR/associated-types-eq-2.rs:117:8
+   |
+LL | struct St<'a, T> { v: &'a T }
+   |        ^^     -
+help: add missing generic argument
+   |
+LL | impl<'a, T> St<'a, T , T = Qux> {
+   |                  +++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:119:21
+   |
+LL | impl<'a, T> St<'a , T = Qux> {
+   |                     ^^^^^^^ associated type not allowed here
+   |
+help: to use `Qux` as a generic argument specify it directly
    |
-LL | fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
-   |                              ^^^^^ associated type not allowed here
+LL | impl<'a, T> St<'a , Qux> {
+   |                     ~~~
 
-error: aborting due to 1 previous error
+error: aborting due to 27 previous errors
 
-For more information about this error, try `rustc --explain E0229`.
+Some errors have detailed explanations: E0046, E0107, E0229, E0658.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
index d99967eb23c..8cea73f8651 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
+++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `await` is a keyword in the 2018 edition
   --> $DIR/2015-edition-error-various-positions.rs:7:20
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
index bf5c4d8d6aa..70b7fa52a19 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `await` is a keyword in the 2018 edition
   --> $DIR/2015-edition-warning.rs:10:20
diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
index 410e15d024f..0d8f92f013f 100644
--- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
+++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
@@ -17,7 +17,7 @@ impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
 impl Bar for () {}
 
 unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo<u32>+'a)) -> u32 {
-    let foo_e : *const dyn Foo<u16> = t as *const _;
+    let foo_e : *const dyn Foo<u32> = t as *const _;
     let r_1 = foo_e as *mut dyn Foo<u32>;
 
     (&*r_1).foo(0)
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
index 92dedd74feb..941764a575e 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
@@ -29,6 +29,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl Foo<N = 3> for Bar {
    |          ^^^^^ associated type not allowed here
+   |
+help: to use `3` as a generic argument specify it directly
+   |
+LL | impl Foo<3> for Bar {
+   |          ~
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
index 801d14b3950..a4c9e065c15 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
@@ -41,6 +41,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl Foo<N = const 3> for Bar {
    |          ^^^^^^^^^^^ associated type not allowed here
+   |
+help: to use `3` as a generic argument specify it directly
+   |
+LL | impl Foo<3> for Bar {
+   |          ~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/consts/const-eval/promoted_errors.noopt.stderr b/tests/ui/consts/const-eval/promoted_errors.noopt.stderr
deleted file mode 100644
index 2a254bfde82..00000000000
--- a/tests/ui/consts/const-eval/promoted_errors.noopt.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-warning: this arithmetic operation will overflow
-  --> $DIR/promoted_errors.rs:15:5
-   |
-LL |     0 - 1
-   |     ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:11:9
-   |
-LL | #![warn(arithmetic_overflow, unconditional_panic)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:19:5
-   |
-LL |     1 / 0
-   |     ^^^^^ attempt to divide `1_i32` by zero
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:11:30
-   |
-LL | #![warn(arithmetic_overflow, unconditional_panic)]
-   |                              ^^^^^^^^^^^^^^^^^^^
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:23:5
-   |
-LL |     1 / (1 - 1)
-   |     ^^^^^^^^^^^ attempt to divide `1_i32` by zero
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:27:5
-   |
-LL |     1 / (false as i32)
-   |     ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:31:5
-   |
-LL |     [1, 2, 3][4]
-   |     ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
-
-warning: 5 warnings emitted
-
diff --git a/tests/ui/consts/const-eval/promoted_errors.opt.stderr b/tests/ui/consts/const-eval/promoted_errors.opt.stderr
deleted file mode 100644
index 2a254bfde82..00000000000
--- a/tests/ui/consts/const-eval/promoted_errors.opt.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-warning: this arithmetic operation will overflow
-  --> $DIR/promoted_errors.rs:15:5
-   |
-LL |     0 - 1
-   |     ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:11:9
-   |
-LL | #![warn(arithmetic_overflow, unconditional_panic)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:19:5
-   |
-LL |     1 / 0
-   |     ^^^^^ attempt to divide `1_i32` by zero
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:11:30
-   |
-LL | #![warn(arithmetic_overflow, unconditional_panic)]
-   |                              ^^^^^^^^^^^^^^^^^^^
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:23:5
-   |
-LL |     1 / (1 - 1)
-   |     ^^^^^^^^^^^ attempt to divide `1_i32` by zero
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:27:5
-   |
-LL |     1 / (false as i32)
-   |     ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:31:5
-   |
-LL |     [1, 2, 3][4]
-   |     ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
-
-warning: 5 warnings emitted
-
diff --git a/tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
deleted file mode 100644
index 2a254bfde82..00000000000
--- a/tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-warning: this arithmetic operation will overflow
-  --> $DIR/promoted_errors.rs:15:5
-   |
-LL |     0 - 1
-   |     ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:11:9
-   |
-LL | #![warn(arithmetic_overflow, unconditional_panic)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:19:5
-   |
-LL |     1 / 0
-   |     ^^^^^ attempt to divide `1_i32` by zero
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:11:30
-   |
-LL | #![warn(arithmetic_overflow, unconditional_panic)]
-   |                              ^^^^^^^^^^^^^^^^^^^
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:23:5
-   |
-LL |     1 / (1 - 1)
-   |     ^^^^^^^^^^^ attempt to divide `1_i32` by zero
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:27:5
-   |
-LL |     1 / (false as i32)
-   |     ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero
-
-warning: this operation will panic at runtime
-  --> $DIR/promoted_errors.rs:31:5
-   |
-LL |     [1, 2, 3][4]
-   |     ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
-
-warning: 5 warnings emitted
-
diff --git a/tests/ui/consts/const-eval/promoted_errors.rs b/tests/ui/consts/const-eval/promoted_errors.rs
deleted file mode 100644
index e806d4a3246..00000000000
--- a/tests/ui/consts/const-eval/promoted_errors.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-//@ revisions: noopt opt opt_with_overflow_checks
-//@[noopt]compile-flags: -C opt-level=0
-//@[opt]compile-flags: -O
-//@[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
-
-//@ build-pass
-//@ ignore-pass (test emits codegen-time warnings and verifies that they are not errors)
-
-//! This test ensures that when we promote code that fails to evaluate, the build still succeeds.
-
-#![warn(arithmetic_overflow, unconditional_panic)]
-
-// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
-const fn overflow() -> u32 {
-    0 - 1
-    //~^ WARN this arithmetic operation will overflow
-}
-const fn div_by_zero1() -> i32 {
-    1 / 0
-    //~^ WARN this operation will panic at runtime
-}
-const fn div_by_zero2() -> i32 {
-    1 / (1 - 1)
-    //~^ WARN this operation will panic at runtime
-}
-const fn div_by_zero3() -> i32 {
-    1 / (false as i32)
-    //~^ WARN this operation will panic at runtime
-}
-const fn oob() -> i32 {
-    [1, 2, 3][4]
-    //~^ WARN this operation will panic at runtime
-}
-
-const fn mk_false() -> bool { false }
-
-// An actually used constant referencing failing promoteds in dead code.
-// This needs to always work.
-const Y: () = {
-    if mk_false() {
-        let _x: &'static u32 = &overflow();
-        let _x: &'static i32 = &div_by_zero1();
-        let _x: &'static i32 = &div_by_zero2();
-        let _x: &'static i32 = &div_by_zero3();
-        let _x: &'static i32 = &oob();
-    }
-    ()
-};
-
-fn main() {
-    Y;
-}
diff --git a/tests/ui/consts/promote-not.rs b/tests/ui/consts/promote-not.rs
index 9b16f32532a..80912937f31 100644
--- a/tests/ui/consts/promote-not.rs
+++ b/tests/ui/consts/promote-not.rs
@@ -51,6 +51,15 @@ const TEST_DROP_NOT_PROMOTE: &String = {
 };
 
 
+// We do not promote function calls in `const` initializers in dead code.
+const fn mk_panic() -> u32 { panic!() }
+const fn mk_false() -> bool { false }
+const Y: () = {
+    if mk_false() {
+        let _x: &'static u32 = &mk_panic(); //~ ERROR temporary value dropped while borrowed
+    }
+};
+
 fn main() {
     // We must not promote things with interior mutability. Not even if we "project it away".
     let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed
diff --git a/tests/ui/consts/promote-not.stderr b/tests/ui/consts/promote-not.stderr
index 07d4a135ed4..d8b6091dc9a 100644
--- a/tests/ui/consts/promote-not.stderr
+++ b/tests/ui/consts/promote-not.stderr
@@ -48,6 +48,16 @@ LL | };
    | - value is dropped here
 
 error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:59:33
+   |
+LL |         let _x: &'static u32 = &mk_panic();
+   |                 ------------    ^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |                 |
+   |                 type annotation requires that borrow lasts for `'static`
+LL |     }
+   |     - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:21:32
    |
 LL |         let _x: &'static () = &foo();
@@ -68,7 +78,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:56:29
+  --> $DIR/promote-not.rs:65:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).0;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -79,7 +89,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:57:29
+  --> $DIR/promote-not.rs:66:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -90,7 +100,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:60:29
+  --> $DIR/promote-not.rs:69:29
    |
 LL |     let _val: &'static _ = &(1/0);
    |               ----------    ^^^^^ creates a temporary value which is freed while still in use
@@ -101,7 +111,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:61:29
+  --> $DIR/promote-not.rs:70:29
    |
 LL |     let _val: &'static _ = &(1/(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -112,7 +122,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:62:29
+  --> $DIR/promote-not.rs:71:29
    |
 LL |     let _val: &'static _ = &((1+1)/(1-1));
    |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -123,7 +133,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:63:29
+  --> $DIR/promote-not.rs:72:29
    |
 LL |     let _val: &'static _ = &(i32::MIN/-1);
    |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -134,7 +144,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:64:29
+  --> $DIR/promote-not.rs:73:29
    |
 LL |     let _val: &'static _ = &(i32::MIN/(0-1));
    |               ----------    ^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -145,7 +155,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:65:29
+  --> $DIR/promote-not.rs:74:29
    |
 LL |     let _val: &'static _ = &(-128i8/-1);
    |               ----------    ^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -156,7 +166,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:66:29
+  --> $DIR/promote-not.rs:75:29
    |
 LL |     let _val: &'static _ = &(1%0);
    |               ----------    ^^^^^ creates a temporary value which is freed while still in use
@@ -167,7 +177,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:67:29
+  --> $DIR/promote-not.rs:76:29
    |
 LL |     let _val: &'static _ = &(1%(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -178,7 +188,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:68:29
+  --> $DIR/promote-not.rs:77:29
    |
 LL |     let _val: &'static _ = &([1,2,3][4]+1);
    |               ----------    ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -189,7 +199,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:72:29
+  --> $DIR/promote-not.rs:81:29
    |
 LL |     let _val: &'static _ = &TEST_DROP;
    |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -200,7 +210,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:74:29
+  --> $DIR/promote-not.rs:83:29
    |
 LL |     let _val: &'static _ = &&TEST_DROP;
    |               ----------    ^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -211,7 +221,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:74:30
+  --> $DIR/promote-not.rs:83:30
    |
 LL |     let _val: &'static _ = &&TEST_DROP;
    |               ----------     ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -222,7 +232,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:77:29
+  --> $DIR/promote-not.rs:86:29
    |
 LL |     let _val: &'static _ = &(&TEST_DROP,);
    |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -233,7 +243,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:77:31
+  --> $DIR/promote-not.rs:86:31
    |
 LL |     let _val: &'static _ = &(&TEST_DROP,);
    |               ----------      ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -244,7 +254,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:80:29
+  --> $DIR/promote-not.rs:89:29
    |
 LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               ----------    ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -255,7 +265,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:80:31
+  --> $DIR/promote-not.rs:89:31
    |
 LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               ----------      ^^^^^^^^^    - temporary value is freed at the end of this statement
@@ -264,7 +274,7 @@ LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               type annotation requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:89:26
+  --> $DIR/promote-not.rs:98:26
    |
 LL |     let x: &'static _ = &UnionWithCell { f1: 0 };
    |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -274,7 +284,7 @@ LL |
 LL | }
    | - temporary value is freed at the end of this statement
 
-error: aborting due to 26 previous errors
+error: aborting due to 27 previous errors
 
 Some errors have detailed explanations: E0493, E0716.
 For more information about an error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/promotion.rs b/tests/ui/consts/promotion.rs
index b18495a4a6b..457e807c970 100644
--- a/tests/ui/consts/promotion.rs
+++ b/tests/ui/consts/promotion.rs
@@ -5,28 +5,30 @@
 
 //@ build-pass
 
+#![allow(arithmetic_overflow)]
+
+use std::mem;
+
 const fn assert_static<T>(_: &'static T) {}
 
-#[allow(unconditional_panic)]
-const fn fail() -> i32 {
-    1/0
-}
-const C: i32 = {
-    // Promoted that fails to evaluate in dead code -- this must work
-    // (for backwards compatibility reasons).
-    if false {
-        assert_static(&fail());
-    }
+// Function calls in const on the "main path" (not inside conditionals)
+// do get promoted.
+const fn make_thing() -> i32 {
     42
+}
+const C: () = {
+    assert_static(&make_thing());
+    // Make sure this works even when there's other stuff (like function calls) above the relevant
+    // call in the const initializer.
+    assert_static(&make_thing());
 };
 
 fn main() {
     assert_static(&["a", "b", "c"]);
     assert_static(&["d", "e", "f"]);
-    assert_eq!(C, 42);
 
     // make sure that this does not cause trouble despite overflowing
-    assert_static(&(0-1));
+    assert_static(&(0u32 - 1));
 
     // div-by-non-0 (and also not MIN/-1) is okay
     assert_static(&(1/1));
@@ -36,12 +38,16 @@ fn main() {
     assert_static(&(1%1));
 
     // in-bounds array access is okay
-    assert_static(&([1,2,3][0] + 1));
-    assert_static(&[[1,2][1]]);
+    assert_static(&([1, 2, 3][0] + 1));
+    assert_static(&[[1, 2][1]]);
 
     // Top-level projections are not part of the promoted, so no error here.
     if false {
         #[allow(unconditional_panic)]
-        assert_static(&[1,2,3][4]);
+        assert_static(&[1, 2, 3][4]);
     }
+
+    // More complicated case involving control flow and a `#[rustc_promotable]` function
+    let decision = std::hint::black_box(true);
+    let x: &'static usize = if decision { &mem::size_of::<usize>() } else { &0 };
 }
diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr b/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr
new file mode 100644
index 00000000000..a50c49d5362
--- /dev/null
+++ b/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr
@@ -0,0 +1,23 @@
+error[E0080]: evaluation of `Fail::<i32>::C` failed
+  --> $DIR/collect-in-promoted-const.rs:9:19
+   |
+LL |     const C: () = panic!();
+   |                   ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-promoted-const.rs:9:19
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: erroneous constant encountered
+  --> $DIR/collect-in-promoted-const.rs:20:21
+   |
+LL |         let _val = &Fail::<T>::C;
+   |                     ^^^^^^^^^^^^
+
+note: the above error was encountered while instantiating `fn f::<i32>`
+  --> $DIR/collect-in-promoted-const.rs:25:5
+   |
+LL |     f::<i32>();
+   |     ^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr b/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr
new file mode 100644
index 00000000000..cf0aa8ef7a7
--- /dev/null
+++ b/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr
@@ -0,0 +1,39 @@
+error[E0080]: evaluation of `Fail::<T>::C` failed
+  --> $DIR/collect-in-promoted-const.rs:9:19
+   |
+LL |     const C: () = panic!();
+   |                   ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-promoted-const.rs:9:19
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: erroneous constant encountered
+  --> $DIR/collect-in-promoted-const.rs:20:21
+   |
+LL |         let _val = &Fail::<T>::C;
+   |                     ^^^^^^^^^^^^
+
+error[E0080]: evaluation of `Fail::<i32>::C` failed
+  --> $DIR/collect-in-promoted-const.rs:9:19
+   |
+LL |     const C: () = panic!();
+   |                   ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/collect-in-promoted-const.rs:9:19
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: erroneous constant encountered
+  --> $DIR/collect-in-promoted-const.rs:20:21
+   |
+LL |         let _val = &Fail::<T>::C;
+   |                     ^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+note: the above error was encountered while instantiating `fn f::<i32>`
+  --> $DIR/collect-in-promoted-const.rs:25:5
+   |
+LL |     f::<i32>();
+   |     ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.rs b/tests/ui/consts/required-consts/collect-in-promoted-const.rs
new file mode 100644
index 00000000000..4a3ce92e8f9
--- /dev/null
+++ b/tests/ui/consts/required-consts/collect-in-promoted-const.rs
@@ -0,0 +1,26 @@
+//@revisions: noopt opt
+//@ build-fail
+//@[noopt] compile-flags: -Copt-level=0
+//@[opt] compile-flags: -O
+//! Make sure we error on erroneous consts even if they get promoted.
+
+struct Fail<T>(T);
+impl<T> Fail<T> {
+    const C: () = panic!(); //~ERROR evaluation of `Fail::<i32>::C` failed
+    //[opt]~^ ERROR evaluation of `Fail::<T>::C` failed
+    // (Not sure why optimizations lead to this being emitted twice, but as long as compilation
+    // fails either way it's fine.)
+}
+
+#[inline(never)]
+fn f<T>() {
+    if false {
+        // If promotion moved `C` from our required_consts to its own, without adding itself to
+        // our required_consts, then we'd miss the const-eval failure here.
+        let _val = &Fail::<T>::C;
+    }
+}
+
+fn main() {
+    f::<i32>();
+}
diff --git a/tests/ui/consts/required-consts/interpret-in-promoted.rs b/tests/ui/consts/required-consts/interpret-in-promoted.rs
index 187494180ad..48caece6ff5 100644
--- a/tests/ui/consts/required-consts/interpret-in-promoted.rs
+++ b/tests/ui/consts/required-consts/interpret-in-promoted.rs
@@ -1,7 +1,7 @@
 //@revisions: noopt opt
 //@[noopt] compile-flags: -Copt-level=0
 //@[opt] compile-flags: -O
-//! Make sure we error on erroneous consts even if they are unused.
+//! Make sure we evaluate const fn calls even if they get promoted and their result ignored.
 
 const unsafe fn ub() {
     std::hint::unreachable_unchecked();
diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs
index eed6f851bd0..fffdae632ef 100644
--- a/tests/ui/coroutine/clone-impl.rs
+++ b/tests/ui/coroutine/clone-impl.rs
@@ -6,18 +6,18 @@
 
 struct NonClone;
 
-fn main() {
+fn test1() {
     let copyable: u32 = 123;
-    let clonable_0: Vec<u32> = Vec::new();
-    let clonable_1: Vec<u32> = Vec::new();
-    let non_clonable: NonClone = NonClone;
-
     let gen_copy_0 = move || {
         yield;
         drop(copyable);
     };
     check_copy(&gen_copy_0);
     check_clone(&gen_copy_0);
+}
+
+fn test2() {
+    let copyable: u32 = 123;
     let gen_copy_1 = move || {
         /*
         let v = vec!['a'];
@@ -33,6 +33,10 @@ fn main() {
     };
     check_copy(&gen_copy_1);
     check_clone(&gen_copy_1);
+}
+
+fn test3() {
+    let clonable_0: Vec<u32> = Vec::new();
     let gen_clone_0 = move || {
         let v = vec!['a'];
         yield;
@@ -43,6 +47,10 @@ fn main() {
     //~^ ERROR the trait bound `Vec<u32>: Copy` is not satisfied
     //~| ERROR the trait bound `Vec<char>: Copy` is not satisfied
     check_clone(&gen_clone_0);
+}
+
+fn test4() {
+    let clonable_1: Vec<u32> = Vec::new();
     let gen_clone_1 = move || {
         let v = vec!['a'];
         /*
@@ -59,6 +67,10 @@ fn main() {
     //~^ ERROR the trait bound `Vec<u32>: Copy` is not satisfied
     //~| ERROR the trait bound `Vec<char>: Copy` is not satisfied
     check_clone(&gen_clone_1);
+}
+
+fn test5() {
+    let non_clonable: NonClone = NonClone;
     let gen_non_clone = move || {
         yield;
         drop(non_clonable);
@@ -71,3 +83,5 @@ fn main() {
 
 fn check_copy<T: Copy>(_x: &T) {}
 fn check_clone<T: Clone>(_x: &T) {}
+
+fn main() {}
diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr
index 1d4804501d8..b454846faac 100644
--- a/tests/ui/coroutine/clone-impl.stderr
+++ b/tests/ui/coroutine/clone-impl.stderr
@@ -1,76 +1,76 @@
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
-  --> $DIR/clone-impl.rs:42:5
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
+  --> $DIR/clone-impl.rs:46:5
    |
 LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:40:14
+  --> $DIR/clone-impl.rs:44:14
    |
 LL |         drop(clonable_0);
    |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
-  --> $DIR/clone-impl.rs:42:5
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
+  --> $DIR/clone-impl.rs:46:5
    |
 LL |     let gen_clone_0 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
 ...
 LL |     check_copy(&gen_clone_0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:38:9
+  --> $DIR/clone-impl.rs:42:9
    |
 LL |         let v = vec!['a'];
    |             - has type `Vec<char>` which does not implement `Copy`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `v` maybe used later
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
-  --> $DIR/clone-impl.rs:58:5
+error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
+  --> $DIR/clone-impl.rs:66:5
    |
 LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:56:14
+  --> $DIR/clone-impl.rs:64:14
    |
 LL |         drop(clonable_1);
    |              ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
-  --> $DIR/clone-impl.rs:58:5
+error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
+  --> $DIR/clone-impl.rs:66:5
    |
 LL |     let gen_clone_1 = move || {
-   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`
+   |                       ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
 ...
 LL |     check_copy(&gen_clone_1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
    |
 note: coroutine does not implement `Copy` as this value is used across a yield
-  --> $DIR/clone-impl.rs:52:9
+  --> $DIR/clone-impl.rs:60:9
    |
 LL |         let v = vec!['a'];
    |             - has type `Vec<char>` which does not implement `Copy`
@@ -78,27 +78,27 @@ LL |         let v = vec!['a'];
 LL |         yield;
    |         ^^^^^ yield occurs here, with `v` maybe used later
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
-  --> $DIR/clone-impl.rs:66:5
+error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
+  --> $DIR/clone-impl.rs:78:5
    |
 LL |     let gen_non_clone = move || {
-   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
+   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
 ...
 LL |     check_copy(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Copy`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Copy`
    |
 note: captured value does not implement `Copy`
-  --> $DIR/clone-impl.rs:64:14
+  --> $DIR/clone-impl.rs:76:14
    |
 LL |         drop(non_clonable);
    |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy`
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl.rs:72:18
+  --> $DIR/clone-impl.rs:84:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -108,22 +108,22 @@ LL + #[derive(Copy)]
 LL | struct NonClone;
    |
 
-error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
-  --> $DIR/clone-impl.rs:68:5
+error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
+  --> $DIR/clone-impl.rs:80:5
    |
 LL |     let gen_non_clone = move || {
-   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`
+   |                         ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
 ...
 LL |     check_clone(&gen_non_clone);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Clone`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Clone`
    |
 note: captured value does not implement `Clone`
-  --> $DIR/clone-impl.rs:64:14
+  --> $DIR/clone-impl.rs:76:14
    |
 LL |         drop(non_clonable);
    |              ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone`
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl.rs:73:19
+  --> $DIR/clone-impl.rs:85:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
new file mode 100644
index 00000000000..07c13239a2c
--- /dev/null
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
@@ -0,0 +1,10 @@
+//@ edition:2021
+
+trait X {
+    fn test() -> Self::Assoc<{ async {} }>;
+    //~^ ERROR associated type `Assoc` not found for `Self`
+    //~| ERROR associated type `Assoc` not found for `Self`
+
+}
+
+pub fn main() {}
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
new file mode 100644
index 00000000000..864c6556d79
--- /dev/null
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
@@ -0,0 +1,17 @@
+error[E0220]: associated type `Assoc` not found for `Self`
+  --> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
+   |
+LL |     fn test() -> Self::Assoc<{ async {} }>;
+   |                        ^^^^^ associated type `Assoc` not found
+
+error[E0220]: associated type `Assoc` not found for `Self`
+  --> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
+   |
+LL |     fn test() -> Self::Assoc<{ async {} }>;
+   |                        ^^^^^ associated type `Assoc` not found
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr
index 9e171896718..4d637c97283 100644
--- a/tests/ui/derives/issue-91550.stderr
+++ b/tests/ui/derives/issue-91550.stderr
@@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
   --> $DIR/issue-91550.rs:8:8
    |
 LL | struct Value(u32);
-   | ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
+   | ------------ doesn't satisfy `Value: Eq` or `Value: Hash`
 ...
 LL |     hs.insert(Value(0));
    |        ^^^^^^
    |
    = note: the following trait bounds were not satisfied:
            `Value: Eq`
-           `Value: PartialEq`
-           which is required by `Value: Eq`
            `Value: Hash`
 help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
    |
@@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
   --> $DIR/issue-91550.rs:26:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
+   | -------------------- doesn't satisfy `NoDerives: Eq`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_eq` not found for this struct
@@ -37,9 +35,6 @@ LL | impl<T: Eq> Object<T> {
    |         ^^  ---------
    |         |
    |         unsatisfied trait bound introduced here
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: Eq`
 help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
    |
 LL + #[derive(Eq, PartialEq)]
@@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
   --> $DIR/issue-91550.rs:27:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
+   | -------------------- doesn't satisfy `NoDerives: Ord`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord` not found for this struct
@@ -65,13 +60,6 @@ LL | impl<T: Ord> Object<T> {
    |         ^^^  ---------
    |         |
    |         unsatisfied trait bound introduced here
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: PartialOrd`
-           which is required by `NoDerives: Ord`
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: Ord`
-           `NoDerives: Eq`
-           which is required by `NoDerives: Ord`
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
@@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
   --> $DIR/issue-91550.rs:28:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
+   | -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord_and_partial_ord` not found for this struct
@@ -100,13 +88,6 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
    |         |     |
    |         |     unsatisfied trait bound introduced here
    |         unsatisfied trait bound introduced here
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: Ord`
-           `NoDerives: Eq`
-           which is required by `NoDerives: Ord`
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: PartialOrd`
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
diff --git a/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
index 89aded9134f..0d53fb024ac 100644
--- a/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
+++ b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `dyn` is a keyword in the 2018 edition
   --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:17:20
diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr
index bd8e1955ac6..ae7dc9ac265 100644
--- a/tests/ui/error-codes/E0229.stderr
+++ b/tests/ui/error-codes/E0229.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
    |                         ^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                        ~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/E0229.rs:13:25
@@ -11,6 +16,10 @@ LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
    |                         ^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                        ~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/E0229.rs:13:25
@@ -19,6 +28,10 @@ LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
    |                         ^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                        ~~~~~~~
 
 error[E0277]: the trait bound `I: Foo` is not satisfied
   --> $DIR/E0229.rs:13:15
diff --git a/tests/ui/error-codes/E0522.rs b/tests/ui/error-codes/E0522.rs
index 1414e82408c..ec9e6d25774 100644
--- a/tests/ui/error-codes/E0522.rs
+++ b/tests/ui/error-codes/E0522.rs
@@ -2,7 +2,7 @@
 
 #[lang = "cookie"]
 fn cookie() -> ! {
-//~^^ ERROR definition of an unknown language item: `cookie` [E0522]
+//~^^ ERROR definition of an unknown lang item: `cookie` [E0522]
     loop {}
 }
 
diff --git a/tests/ui/error-codes/E0522.stderr b/tests/ui/error-codes/E0522.stderr
index 66359cbacc8..82bbf079594 100644
--- a/tests/ui/error-codes/E0522.stderr
+++ b/tests/ui/error-codes/E0522.stderr
@@ -1,8 +1,8 @@
-error[E0522]: definition of an unknown language item: `cookie`
+error[E0522]: definition of an unknown lang item: `cookie`
   --> $DIR/E0522.rs:3:1
    |
 LL | #[lang = "cookie"]
-   | ^^^^^^^^^^^^^^^^^^ definition of unknown language item `cookie`
+   | ^^^^^^^^^^^^^^^^^^ definition of unknown lang item `cookie`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0718.rs b/tests/ui/error-codes/E0718.rs
index 909cae0ba25..358bc348ec7 100644
--- a/tests/ui/error-codes/E0718.rs
+++ b/tests/ui/error-codes/E0718.rs
@@ -1,7 +1,7 @@
 #![feature(lang_items)]
 
 // Box is expected to be a struct, so this will error.
-#[lang = "owned_box"] //~ ERROR language item must be applied to a struct
+#[lang = "owned_box"] //~ ERROR lang item must be applied to a struct
 static X: u32 = 42;
 
 fn main() {}
diff --git a/tests/ui/error-codes/E0718.stderr b/tests/ui/error-codes/E0718.stderr
index 9a3db136d23..ec7462765f8 100644
--- a/tests/ui/error-codes/E0718.stderr
+++ b/tests/ui/error-codes/E0718.stderr
@@ -1,4 +1,4 @@
-error[E0718]: `owned_box` language item must be applied to a struct
+error[E0718]: `owned_box` lang item must be applied to a struct
   --> $DIR/E0718.rs:4:1
    |
 LL | #[lang = "owned_box"]
diff --git a/tests/ui/feature-gates/feature-gate-lang-items.rs b/tests/ui/feature-gates/feature-gate-lang-items.rs
index 93262f2171b..d6fd5472a0c 100644
--- a/tests/ui/feature-gates/feature-gate-lang-items.rs
+++ b/tests/ui/feature-gates/feature-gate-lang-items.rs
@@ -1,5 +1,5 @@
-#[lang = "foo"] //~ ERROR language items are subject to change
-                //~^ ERROR definition of an unknown language item: `foo`
+#[lang = "foo"] //~ ERROR lang items are subject to change
+                //~^ ERROR definition of an unknown lang item: `foo`
 trait Foo {}
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-lang-items.stderr b/tests/ui/feature-gates/feature-gate-lang-items.stderr
index 54787e03784..c5caffbdc94 100644
--- a/tests/ui/feature-gates/feature-gate-lang-items.stderr
+++ b/tests/ui/feature-gates/feature-gate-lang-items.stderr
@@ -1,4 +1,4 @@
-error[E0658]: language items are subject to change
+error[E0658]: lang items are subject to change
   --> $DIR/feature-gate-lang-items.rs:1:1
    |
 LL | #[lang = "foo"]
@@ -7,11 +7,11 @@ LL | #[lang = "foo"]
    = help: add `#![feature(lang_items)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0522]: definition of an unknown language item: `foo`
+error[E0522]: definition of an unknown lang item: `foo`
   --> $DIR/feature-gate-lang-items.rs:1:1
    |
 LL | #[lang = "foo"]
-   | ^^^^^^^^^^^^^^^ definition of unknown language item `foo`
+   | ^^^^^^^^^^^^^^^ definition of unknown lang item `foo`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr
index f5e782e92fc..23b114a3a55 100644
--- a/tests/ui/generic-associated-types/issue-102335-gat.stderr
+++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<(), i32 = ()> = ()>;
    |                     ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<(), i32 = ()> = ()>;
+   |                   ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-gat.rs:2:21
@@ -11,6 +16,10 @@ LL |     type A: S<C<(), i32 = ()> = ()>;
    |                     ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<(), i32 = ()> = ()>;
+   |                   ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs
index 86da6ebfaaa..d7dff329df1 100644
--- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs
+++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs
@@ -29,5 +29,5 @@ where
 
 fn main() {
     let mut list = RcNode::<i32>::new();
-    //~^ ERROR trait bounds were not satisfied
+    //~^ ERROR the variant or associated item `new` exists for enum `Node<i32, RcFamily>`, but its trait bounds were not satisfied
 }
diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs
index 11a75737e55..56c63a1daa8 100644
--- a/tests/ui/impl-trait/issues/issue-62742.rs
+++ b/tests/ui/impl-trait/issues/issue-62742.rs
@@ -1,12 +1,17 @@
 use std::marker::PhantomData;
 
-fn _alias_check() {
+fn a() {
     WrongImpl::foo(0i32);
-    //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
-    //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
+    //~^ ERROR overflow assigning `_` to `[_]`
+}
+
+fn b() {
     WrongImpl::<()>::foo(0i32);
     //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
     //~| ERROR trait bounds were not satisfied
+}
+
+fn c() {
     CorrectImpl::foo(0i32);
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index 9ec581c231b..7a1bcfc70d5 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -1,33 +1,11 @@
-error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
-  --> $DIR/issue-62742.rs:4:5
+error[E0275]: overflow assigning `_` to `[_]`
+  --> $DIR/issue-62742.rs:4:16
    |
 LL |     WrongImpl::foo(0i32);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
-   |
-   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
-note: required by a bound in `SafeImpl::<T, A>::foo`
-  --> $DIR/issue-62742.rs:29:20
-   |
-LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
-   |                    ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
-LL |     pub fn foo(value: A::Value) {}
-   |            --- required by a bound in this associated function
-
-error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
-  --> $DIR/issue-62742.rs:4:5
-   |
-LL |     WrongImpl::foo(0i32);
-   |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
-   |
-   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
-note: required by a bound in `SafeImpl`
-  --> $DIR/issue-62742.rs:27:35
-   |
-LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
-   |                                   ^^^^^^ required by this bound in `SafeImpl`
+   |                ^^^
 
 error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
-  --> $DIR/issue-62742.rs:7:22
+  --> $DIR/issue-62742.rs:9:22
    |
 LL |     WrongImpl::<()>::foo(0i32);
    |                      ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
@@ -39,20 +17,20 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
    | ----------------------------------------- function or associated item `foo` not found for this struct
    |
 note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
-  --> $DIR/issue-62742.rs:29:20
+  --> $DIR/issue-62742.rs:34:20
    |
 LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
    |                    ^^^^^^  --------------
    |                    |
    |                    unsatisfied trait bound introduced here
 note: the trait `Raw` must be implemented
-  --> $DIR/issue-62742.rs:13:1
+  --> $DIR/issue-62742.rs:18:1
    |
 LL | pub trait Raw<T: ?Sized> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
-  --> $DIR/issue-62742.rs:7:5
+  --> $DIR/issue-62742.rs:9:5
    |
 LL |     WrongImpl::<()>::foo(0i32);
    |     ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
@@ -60,12 +38,12 @@ LL |     WrongImpl::<()>::foo(0i32);
    = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
    = help: for that trait implementation, expected `[()]`, found `()`
 note: required by a bound in `SafeImpl`
-  --> $DIR/issue-62742.rs:27:35
+  --> $DIR/issue-62742.rs:32:35
    |
 LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
    |                                   ^^^^^^ required by this bound in `SafeImpl`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0277, E0599.
-For more information about an error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0275, E0277, E0599.
+For more information about an error, try `rustc --explain E0275`.
diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs
index 85d9d461fd9..7acee44a722 100644
--- a/tests/ui/impl-trait/issues/issue-84073.rs
+++ b/tests/ui/impl-trait/issues/issue-84073.rs
@@ -29,5 +29,6 @@ where
 }
 
 fn main() {
-    Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>`
+    Race::new(|race| race.when());
+    //~^ ERROR overflow assigning `_` to `Option<_>`
 }
diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr
index ab119a8a4f4..0f4c6e83fbe 100644
--- a/tests/ui/impl-trait/issues/issue-84073.stderr
+++ b/tests/ui/impl-trait/issues/issue-84073.stderr
@@ -1,8 +1,8 @@
 error[E0275]: overflow assigning `_` to `Option<_>`
-  --> $DIR/issue-84073.rs:32:22
+  --> $DIR/issue-84073.rs:32:27
    |
 LL |     Race::new(|race| race.when());
-   |                      ^^^^
+   |                           ^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/precise-capturing/unexpected-token.rs b/tests/ui/impl-trait/precise-capturing/unexpected-token.rs
new file mode 100644
index 00000000000..39c8c0def6b
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/unexpected-token.rs
@@ -0,0 +1,9 @@
+// We used to fatal error without any useful diagnostic when we had an unexpected
+// token due to a strange interaction between the sequence parsing code and the
+// param/lifetime parsing code.
+
+fn hello() -> impl use<'a {}> Sized {}
+//~^ ERROR expected one of `,` or `>`, found `{`
+//~| ERROR expected item, found `>`
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr b/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr
new file mode 100644
index 00000000000..989c479b248
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr
@@ -0,0 +1,16 @@
+error: expected one of `,` or `>`, found `{`
+  --> $DIR/unexpected-token.rs:5:27
+   |
+LL | fn hello() -> impl use<'a {}> Sized {}
+   |                           ^ expected one of `,` or `>`
+
+error: expected item, found `>`
+  --> $DIR/unexpected-token.rs:5:29
+   |
+LL | fn hello() -> impl use<'a {}> Sized {}
+   |                             ^ expected item
+   |
+   = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs b/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs
index fa9cbe4400c..254ac24f0b9 100644
--- a/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs
+++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs
@@ -16,7 +16,7 @@ use std::intrinsics;
 #[derive(Copy, Clone)]
 pub struct Foo(i64);
 
-pub fn test_cttz(v: Foo) -> Foo {
+pub fn test_cttz(v: Foo) -> u32 {
     intrinsics::cttz(v)
     //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
 }
diff --git a/tests/ui/intrinsics/intrinsics-integer.rs b/tests/ui/intrinsics/intrinsics-integer.rs
index bfd7e4714fe..7dbc4b8b7ce 100644
--- a/tests/ui/intrinsics/intrinsics-integer.rs
+++ b/tests/ui/intrinsics/intrinsics-integer.rs
@@ -6,13 +6,13 @@
 mod rusti {
     extern "rust-intrinsic" {
         #[rustc_safe_intrinsic]
-        pub fn ctpop<T>(x: T) -> T;
+        pub fn ctpop<T>(x: T) -> u32;
         #[rustc_safe_intrinsic]
-        pub fn ctlz<T>(x: T) -> T;
-        pub fn ctlz_nonzero<T>(x: T) -> T;
+        pub fn ctlz<T>(x: T) -> u32;
+        pub fn ctlz_nonzero<T>(x: T) -> u32;
         #[rustc_safe_intrinsic]
-        pub fn cttz<T>(x: T) -> T;
-        pub fn cttz_nonzero<T>(x: T) -> T;
+        pub fn cttz<T>(x: T) -> u32;
+        pub fn cttz_nonzero<T>(x: T) -> u32;
         #[rustc_safe_intrinsic]
         pub fn bswap<T>(x: T) -> T;
         #[rustc_safe_intrinsic]
diff --git a/tests/ui/lang-items/issue-83471.rs b/tests/ui/lang-items/issue-83471.rs
index b32aa034151..6be345ac507 100644
--- a/tests/ui/lang-items/issue-83471.rs
+++ b/tests/ui/lang-items/issue-83471.rs
@@ -5,12 +5,12 @@
 #![no_core]
 
 #[lang = "sized"]
-//~^ ERROR: language items are subject to change [E0658]
+//~^ ERROR: lang items are subject to change [E0658]
 trait Sized {}
 
 #[lang = "fn"]
-//~^ ERROR: language items are subject to change [E0658]
-//~| ERROR: `fn` language item must be applied to a trait with 1 generic argument
+//~^ ERROR: lang items are subject to change [E0658]
+//~| ERROR: `fn` lang item must be applied to a trait with 1 generic argument
 trait Fn {
     fn call(export_name);
     //~^ ERROR: expected type
diff --git a/tests/ui/lang-items/issue-83471.stderr b/tests/ui/lang-items/issue-83471.stderr
index 1f22d966dd7..244b2efeaf1 100644
--- a/tests/ui/lang-items/issue-83471.stderr
+++ b/tests/ui/lang-items/issue-83471.stderr
@@ -4,7 +4,7 @@ error[E0573]: expected type, found built-in attribute `export_name`
 LL |     fn call(export_name);
    |             ^^^^^^^^^^^ not a type
 
-error[E0658]: language items are subject to change
+error[E0658]: lang items are subject to change
   --> $DIR/issue-83471.rs:7:1
    |
 LL | #[lang = "sized"]
@@ -13,7 +13,7 @@ LL | #[lang = "sized"]
    = help: add `#![feature(lang_items)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: language items are subject to change
+error[E0658]: lang items are subject to change
   --> $DIR/issue-83471.rs:11:1
    |
 LL | #[lang = "fn"]
@@ -32,7 +32,7 @@ LL |     fn call(export_name);
    = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
    = note: `#[warn(anonymous_parameters)]` on by default
 
-error[E0718]: `fn` language item must be applied to a trait with 1 generic argument
+error[E0718]: `fn` lang item must be applied to a trait with 1 generic argument
   --> $DIR/issue-83471.rs:11:1
    |
 LL | #[lang = "fn"]
diff --git a/tests/ui/lang-items/issue-87573.rs b/tests/ui/lang-items/issue-87573.rs
index aeb0c245a72..7b805e8b0cd 100644
--- a/tests/ui/lang-items/issue-87573.rs
+++ b/tests/ui/lang-items/issue-87573.rs
@@ -18,11 +18,11 @@ trait Sync {}
 impl Sync for bool {}
 
 #[lang = "drop_in_place"]
-//~^ ERROR: `drop_in_place` language item must be applied to a function with at least 1 generic argument
+//~^ ERROR: `drop_in_place` lang item must be applied to a function with at least 1 generic argument
 fn drop_fn() {
     while false {}
 }
 
 #[lang = "start"]
-//~^ ERROR: `start` language item must be applied to a function with 1 generic argument
+//~^ ERROR: `start` lang item must be applied to a function with 1 generic argument
 fn start(){}
diff --git a/tests/ui/lang-items/issue-87573.stderr b/tests/ui/lang-items/issue-87573.stderr
index 25560cfa0e6..7085bb8c339 100644
--- a/tests/ui/lang-items/issue-87573.stderr
+++ b/tests/ui/lang-items/issue-87573.stderr
@@ -1,4 +1,4 @@
-error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument
+error[E0718]: `drop_in_place` lang item must be applied to a function with at least 1 generic argument
   --> $DIR/issue-87573.rs:20:1
    |
 LL | #[lang = "drop_in_place"]
@@ -7,7 +7,7 @@ LL |
 LL | fn drop_fn() {
    |           - this function has 0 generic arguments
 
-error[E0718]: `start` language item must be applied to a function with 1 generic argument
+error[E0718]: `start` lang item must be applied to a function with 1 generic argument
   --> $DIR/issue-87573.rs:26:1
    |
 LL | #[lang = "start"]
diff --git a/tests/ui/lang-items/lang-item-generic-requirements.rs b/tests/ui/lang-items/lang-item-generic-requirements.rs
index 697790023d6..0f982df61e8 100644
--- a/tests/ui/lang-items/lang-item-generic-requirements.rs
+++ b/tests/ui/lang-items/lang-item-generic-requirements.rs
@@ -9,30 +9,30 @@ trait MySized {}
 
 #[lang = "add"]
 trait MyAdd<'a, T> {}
-//~^^ ERROR: `add` language item must be applied to a trait with 1 generic argument [E0718]
+//~^^ ERROR: `add` lang item must be applied to a trait with 1 generic argument [E0718]
 
 #[lang = "drop_in_place"]
-//~^ ERROR `drop_in_place` language item must be applied to a function with at least 1 generic
+//~^ ERROR `drop_in_place` lang item must be applied to a function with at least 1 generic
 fn my_ptr_drop() {}
 
 #[lang = "index"]
 trait MyIndex<'a, T> {}
-//~^^ ERROR: `index` language item must be applied to a trait with 1 generic argument [E0718]
+//~^^ ERROR: `index` lang item must be applied to a trait with 1 generic argument [E0718]
 
 #[lang = "phantom_data"]
-//~^ ERROR `phantom_data` language item must be applied to a struct with 1 generic argument
+//~^ ERROR `phantom_data` lang item must be applied to a struct with 1 generic argument
 struct MyPhantomData<T, U>;
 //~^ ERROR `T` is never used
 //~| ERROR `U` is never used
 
 #[lang = "owned_box"]
-//~^ ERROR `owned_box` language item must be applied to a struct with at least 1 generic argument
+//~^ ERROR `owned_box` lang item must be applied to a struct with at least 1 generic argument
 struct Foo;
 
 // When the `start` lang item is missing generics very odd things can happen, especially when
 // it comes to cross-crate monomorphization
 #[lang = "start"]
-//~^ ERROR `start` language item must be applied to a function with 1 generic argument [E0718]
+//~^ ERROR `start` lang item must be applied to a function with 1 generic argument [E0718]
 fn start(_: *const u8, _: isize, _: *const *const u8) -> isize {
     0
 }
diff --git a/tests/ui/lang-items/lang-item-generic-requirements.stderr b/tests/ui/lang-items/lang-item-generic-requirements.stderr
index 30abdf84046..3de67d65940 100644
--- a/tests/ui/lang-items/lang-item-generic-requirements.stderr
+++ b/tests/ui/lang-items/lang-item-generic-requirements.stderr
@@ -1,4 +1,4 @@
-error[E0718]: `add` language item must be applied to a trait with 1 generic argument
+error[E0718]: `add` lang item must be applied to a trait with 1 generic argument
   --> $DIR/lang-item-generic-requirements.rs:10:1
    |
 LL | #[lang = "add"]
@@ -6,7 +6,7 @@ LL | #[lang = "add"]
 LL | trait MyAdd<'a, T> {}
    |            ------- this trait has 2 generic arguments
 
-error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument
+error[E0718]: `drop_in_place` lang item must be applied to a function with at least 1 generic argument
   --> $DIR/lang-item-generic-requirements.rs:14:1
    |
 LL | #[lang = "drop_in_place"]
@@ -15,7 +15,7 @@ LL |
 LL | fn my_ptr_drop() {}
    |               - this function has 0 generic arguments
 
-error[E0718]: `index` language item must be applied to a trait with 1 generic argument
+error[E0718]: `index` lang item must be applied to a trait with 1 generic argument
   --> $DIR/lang-item-generic-requirements.rs:18:1
    |
 LL | #[lang = "index"]
@@ -23,7 +23,7 @@ LL | #[lang = "index"]
 LL | trait MyIndex<'a, T> {}
    |              ------- this trait has 2 generic arguments
 
-error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument
+error[E0718]: `phantom_data` lang item must be applied to a struct with 1 generic argument
   --> $DIR/lang-item-generic-requirements.rs:22:1
    |
 LL | #[lang = "phantom_data"]
@@ -32,7 +32,7 @@ LL |
 LL | struct MyPhantomData<T, U>;
    |                     ------ this struct has 2 generic arguments
 
-error[E0718]: `owned_box` language item must be applied to a struct with at least 1 generic argument
+error[E0718]: `owned_box` lang item must be applied to a struct with at least 1 generic argument
   --> $DIR/lang-item-generic-requirements.rs:28:1
    |
 LL | #[lang = "owned_box"]
@@ -41,7 +41,7 @@ LL |
 LL | struct Foo;
    |           - this struct has 0 generic arguments
 
-error[E0718]: `start` language item must be applied to a function with 1 generic argument
+error[E0718]: `start` lang item must be applied to a function with 1 generic argument
   --> $DIR/lang-item-generic-requirements.rs:34:1
    |
 LL | #[lang = "start"]
diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.rs b/tests/ui/lang-items/start_lang_item_with_target_feature.rs
index 4717304c5c6..eb712ba4092 100644
--- a/tests/ui/lang-items/start_lang_item_with_target_feature.rs
+++ b/tests/ui/lang-items/start_lang_item_with_target_feature.rs
@@ -11,7 +11,7 @@ pub trait Sized {}
 
 #[lang = "start"]
 #[target_feature(enable = "avx2")]
-//~^ ERROR `start` language item function is not allowed to have `#[target_feature]`
+//~^ ERROR `start` lang item function is not allowed to have `#[target_feature]`
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
     0
 }
diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr
index bb0583dfde0..6214e3f8bc7 100644
--- a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr
+++ b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr
@@ -1,11 +1,11 @@
-error: `start` language item function is not allowed to have `#[target_feature]`
+error: `start` lang item function is not allowed to have `#[target_feature]`
   --> $DIR/start_lang_item_with_target_feature.rs:13:1
    |
 LL | #[target_feature(enable = "avx2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   | ------------------------------------------------------------------------------------------- `start` language item function is not allowed to have `#[target_feature]`
+   | ------------------------------------------------------------------------------------------- `start` lang item function is not allowed to have `#[target_feature]`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/crashes/124031.rs b/tests/ui/layout/ice-type-error-in-tail-124031.rs
index bdc66fbafe4..0a2be117403 100644
--- a/tests/crashes/124031.rs
+++ b/tests/ui/layout/ice-type-error-in-tail-124031.rs
@@ -1,10 +1,13 @@
-//@ known-bug: #124031
+// Regression test for issue #124031
+// Checks that we don't ICE when the tail
+// of an ADT has a type error
 
 trait Trait {
     type RefTarget;
 }
 
 impl Trait for () {}
+//~^ ERROR not all trait items implemented, missing: `RefTarget`
 
 struct Other {
     data: <() as Trait>::RefTarget,
diff --git a/tests/ui/layout/ice-type-error-in-tail-124031.stderr b/tests/ui/layout/ice-type-error-in-tail-124031.stderr
new file mode 100644
index 00000000000..57dc83f92df
--- /dev/null
+++ b/tests/ui/layout/ice-type-error-in-tail-124031.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `RefTarget`
+  --> $DIR/ice-type-error-in-tail-124031.rs:9:1
+   |
+LL |     type RefTarget;
+   |     -------------- `RefTarget` from trait
+...
+LL | impl Trait for () {}
+   | ^^^^^^^^^^^^^^^^^ missing `RefTarget` in implementation
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
index d99ea6a0c30..d6da842e6ab 100644
--- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
+++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     fn bar(foo: Foo<Target = usize>) {}
    |                     ^^^^^^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     fn bar(foo: Foo<Target = usize>) {}
+   |                    ~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.stderr b/tests/ui/lint/lint-pre-expansion-extern-module.stderr
index 8a6e1531d5f..32c76da98b5 100644
--- a/tests/ui/lint/lint-pre-expansion-extern-module.stderr
+++ b/tests/ui/lint/lint-pre-expansion-extern-module.stderr
@@ -6,8 +6,8 @@ LL | pub fn try() {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
-   = note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
-   = help: to override `-W rust-2018-compatibility` add `#[allow(keyword_idents)]`
+   = note: `-W keyword-idents-2018` implied by `-W rust-2018-compatibility`
+   = help: to override `-W rust-2018-compatibility` add `#[allow(keyword_idents_2018)]`
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
index ba32fb566e8..0f9eac93930 100644
--- a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
+++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
@@ -20,10 +20,10 @@ fn doc_comment_between_if_else(num: u8) -> bool {
 }
 
 fn doc_comment_on_expr(num: u8) -> bool {
-    /// useless doc comment
+    (/// useless doc comment
     //~^ ERROR: attributes on expressions are experimental
     //~| ERROR: unused doc comment
-    num == 3
+    num) == 3
 }
 
 fn doc_comment_on_expr_field() -> bool {
diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
index 55e4834e670..add85b2f5e0 100644
--- a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
+++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
@@ -5,10 +5,10 @@ LL |     else {
    |     ^^^^ expected expression
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:6
    |
-LL |     /// useless doc comment
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (/// useless doc comment
+   |      ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
@@ -32,12 +32,12 @@ LL | #![deny(unused_doc_comments)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unused doc comment
-  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:6
    |
-LL |     /// useless doc comment
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (/// useless doc comment
+   |      ^^^^^^^^^^^^^^^^^^^^^^^
 ...
-LL |     num == 3
+LL |     num) == 3
    |     --- rustdoc does not generate documentation for expressions
    |
    = help: use `//` for a plain comment
diff --git a/tests/ui/methods/fulfillment-disqualifies-method.rs b/tests/ui/methods/fulfillment-disqualifies-method.rs
new file mode 100644
index 00000000000..639e1c7fc5c
--- /dev/null
+++ b/tests/ui/methods/fulfillment-disqualifies-method.rs
@@ -0,0 +1,32 @@
+// Tests that using fulfillment in the trait solver means that we detect that a
+// method is impossible, leading to no ambiguity.
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#[derive(Default)]
+struct W<A, B>(A, B);
+
+trait Constrain {
+    type Output;
+}
+
+impl Constrain for i32 {
+    type Output = u32;
+}
+
+trait Impossible {}
+
+impl<A, B> W<A, B> where A: Constrain<Output = B>, B: Impossible {
+    fn method(&self) {}
+}
+
+impl W<i32, u32> {
+    fn method(&self) {}
+}
+
+fn main() {
+    let w: W<i32, _> = W::default();
+    w.method();
+}
diff --git a/tests/ui/methods/leak-check-disquality.rs b/tests/ui/methods/leak-check-disquality.rs
new file mode 100644
index 00000000000..d3b7dd4b807
--- /dev/null
+++ b/tests/ui/methods/leak-check-disquality.rs
@@ -0,0 +1,26 @@
+// Tests that using fulfillment in the trait solver means that we detect that a
+// method is impossible, leading to no ambiguity.
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+struct W<T, U>(Option<T>, Option<U>);
+
+impl<'a> W<fn(&'a ()), u32> {
+    fn method(&self) {}
+}
+
+trait Leak {}
+impl<T: Fn(&())> Leak for T {}
+
+impl<T: Leak> W<T, i32> {
+    fn method(&self) {}
+}
+
+fn test<'a>() {
+    let x: W<fn(&'a ()), _> = W(None, None);
+    x.method();
+}
+
+fn main() {}
diff --git a/tests/ui/methods/self-type-is-sup-no-eq.rs b/tests/ui/methods/self-type-is-sup-no-eq.rs
new file mode 100644
index 00000000000..ec28b964a05
--- /dev/null
+++ b/tests/ui/methods/self-type-is-sup-no-eq.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+// Test that we use `sup` not `eq` during method probe, since this has an effect
+// on the leak check. This is (conceptually) minimized from a crater run for
+// `wrend 0.3.6`.
+
+use std::ops::Deref;
+
+struct A;
+
+impl Deref for A {
+    type Target = B<dyn Fn(&())>;
+
+    fn deref(&self) -> &<Self as Deref>::Target { todo!() }
+}
+
+struct B<T: ?Sized>(T);
+impl<T> B<dyn Fn(T)> {
+    fn method(&self) {}
+}
+
+fn main() {
+    A.method();
+}
diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr
index f73bff51e7a..3bfdd4da6da 100644
--- a/tests/ui/missing-trait-bounds/issue-35677.stderr
+++ b/tests/ui/missing-trait-bounds/issue-35677.stderr
@@ -6,8 +6,6 @@ LL |     this.is_subset(other)
    |
    = note: the following trait bounds were not satisfied:
            `T: Eq`
-           `T: PartialEq`
-           which is required by `T: Eq`
            `T: Hash`
 help: consider restricting the type parameters to satisfy the trait bounds
    |
diff --git a/tests/ui/nll/issue-57362-2.rs b/tests/ui/nll/issue-57362-2.rs
index a0b0ea1d038..664cdf89a38 100644
--- a/tests/ui/nll/issue-57362-2.rs
+++ b/tests/ui/nll/issue-57362-2.rs
@@ -18,8 +18,10 @@ impl<'a> X for fn(&'a ()) {
     }
 }
 
+// FIXME(@compiler-errors): This error message is less than helpful.
 fn g() {
-    let x = <fn (&())>::make_g(); //~ ERROR the function
+    let x = <fn (&())>::make_g();
+    //~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
 }
 
 fn main() {}
diff --git a/tests/ui/nll/issue-57362-2.stderr b/tests/ui/nll/issue-57362-2.stderr
index 57477f5341e..24787b990e3 100644
--- a/tests/ui/nll/issue-57362-2.stderr
+++ b/tests/ui/nll/issue-57362-2.stderr
@@ -1,11 +1,9 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
-  --> $DIR/issue-57362-2.rs:22:25
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
+  --> $DIR/issue-57362-2.rs:23:25
    |
 LL |     let x = <fn (&())>::make_g();
-   |                         ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
+   |                         ^^^^^^ function or associated item not found in `fn(&())`
    |
-   = note: the following trait bounds were not satisfied:
-           `for<'a> fn(&'a ()): X`
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `X` defines an item `make_g`, perhaps you need to implement it
   --> $DIR/issue-57362-2.rs:8:1
diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs
index eba859cde22..69187cab342 100644
--- a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs
+++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs
@@ -28,7 +28,8 @@ impl<T> Y for fn(T) {
 }
 
 fn higher_ranked_region_has_lost_its_binder() {
-    let x = <fn (&())>::make_g(); //~ ERROR the function
+    let x = <fn (&())>::make_g();
+    //~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
 }
 
 fn magical() {
diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
index d1e94bc702c..998d06b7706 100644
--- a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
+++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
@@ -1,11 +1,9 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
   --> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
    |
 LL |     let x = <fn (&())>::make_g();
-   |                         ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
+   |                         ^^^^^^ function or associated item not found in `fn(&())`
    |
-   = note: the following trait bounds were not satisfied:
-           `for<'a> fn(&'a ()): X`
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `X` defines an item `make_g`, perhaps you need to implement it
   --> $DIR/issue-57642-higher-ranked-subtype.rs:4:1
@@ -14,7 +12,7 @@ LL | trait X {
    | ^^^^^^^
 
 error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope
-  --> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
+  --> $DIR/issue-57642-higher-ranked-subtype.rs:36:25
    |
 LL |     let x = <fn (&())>::make_f();
    |                         ^^^^^^ function or associated item not found in `fn(&())`
diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.rs b/tests/ui/panic-handler/panic-handler-with-target-feature.rs
index 3dfdd2847bf..8d5ea0703af 100644
--- a/tests/ui/panic-handler/panic-handler-with-target-feature.rs
+++ b/tests/ui/panic-handler/panic-handler-with-target-feature.rs
@@ -9,7 +9,7 @@ use core::panic::PanicInfo;
 
 #[panic_handler]
 #[target_feature(enable = "avx2")]
-//~^ ERROR `panic_impl` language item function is not allowed to have `#[target_feature]`
+//~^ ERROR `#[panic_handler]` function is not allowed to have `#[target_feature]`
 fn panic(info: &PanicInfo) -> ! {
     unimplemented!();
 }
diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr
index c38feab49c3..cb17da3a4ef 100644
--- a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr
+++ b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr
@@ -1,11 +1,11 @@
-error: `panic_impl` language item function is not allowed to have `#[target_feature]`
+error: `#[panic_handler]` function is not allowed to have `#[target_feature]`
   --> $DIR/panic-handler-with-target-feature.rs:11:1
    |
 LL | #[target_feature(enable = "avx2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | fn panic(info: &PanicInfo) -> ! {
-   | ------------------------------- `panic_impl` language item function is not allowed to have `#[target_feature]`
+   | ------------------------------- `#[panic_handler]` function is not allowed to have `#[target_feature]`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/panic-handler/panic-handler-with-track-caller.rs b/tests/ui/panic-handler/panic-handler-with-track-caller.rs
new file mode 100644
index 00000000000..09c94139e16
--- /dev/null
+++ b/tests/ui/panic-handler/panic-handler-with-track-caller.rs
@@ -0,0 +1,14 @@
+//@ compile-flags:-C panic=abort
+//@ only-x86_64
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+#[track_caller]
+//~^ ERROR `#[panic_handler]` function is not allowed to have `#[track_caller]`
+fn panic(info: &PanicInfo) -> ! {
+    unimplemented!();
+}
diff --git a/tests/ui/panic-handler/panic-handler-with-track-caller.stderr b/tests/ui/panic-handler/panic-handler-with-track-caller.stderr
new file mode 100644
index 00000000000..9ed387fc8d1
--- /dev/null
+++ b/tests/ui/panic-handler/panic-handler-with-track-caller.stderr
@@ -0,0 +1,11 @@
+error: `#[panic_handler]` function is not allowed to have `#[track_caller]`
+  --> $DIR/panic-handler-with-track-caller.rs:10:1
+   |
+LL | #[track_caller]
+   | ^^^^^^^^^^^^^^^
+LL |
+LL | fn panic(info: &PanicInfo) -> ! {
+   | ------------------------------- `#[panic_handler]` function is not allowed to have `#[target_feature]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.rs b/tests/ui/panic-handler/panic-handler-wrong-location.rs
index fc3ef401e3d..49685ee4592 100644
--- a/tests/ui/panic-handler/panic-handler-wrong-location.rs
+++ b/tests/ui/panic-handler/panic-handler-wrong-location.rs
@@ -3,6 +3,6 @@
 #![no_std]
 #![no_main]
 
-#[panic_handler] //~ ERROR `panic_impl` language item must be applied to a function
+#[panic_handler] //~ ERROR `panic_impl` lang item must be applied to a function
 #[no_mangle]
 static X: u32 = 42;
diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.stderr b/tests/ui/panic-handler/panic-handler-wrong-location.stderr
index ae3ed5ab12b..66ee91aa4c1 100644
--- a/tests/ui/panic-handler/panic-handler-wrong-location.stderr
+++ b/tests/ui/panic-handler/panic-handler-wrong-location.stderr
@@ -1,4 +1,4 @@
-error[E0718]: `panic_impl` language item must be applied to a function
+error[E0718]: `panic_impl` lang item must be applied to a function
   --> $DIR/panic-handler-wrong-location.rs:6:1
    |
 LL | #[panic_handler]
diff --git a/tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed b/tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed
new file mode 100644
index 00000000000..aae71ede771
--- /dev/null
+++ b/tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed
@@ -0,0 +1,15 @@
+//@ run-rustfix
+#![feature(stmt_expr_attributes)]
+#![allow(unused_assignments, unused_attributes)]
+
+fn main() {
+    let mut x = (#[deprecated] 1) + 2; //~ ERROR ambiguous
+
+    (#[deprecated] x) = 4; //~ ERROR ambiguous
+
+    x = (#[deprecated] 5) as i32; //~ ERROR ambiguous
+
+    let _r = (#[deprecated] 1)..6; //~ ERROR ambiguous
+
+    println!("{}", x);
+}
diff --git a/tests/ui/parser/attribute/attr-binary-expr-ambigous.rs b/tests/ui/parser/attribute/attr-binary-expr-ambigous.rs
new file mode 100644
index 00000000000..613e01d743b
--- /dev/null
+++ b/tests/ui/parser/attribute/attr-binary-expr-ambigous.rs
@@ -0,0 +1,15 @@
+//@ run-rustfix
+#![feature(stmt_expr_attributes)]
+#![allow(unused_assignments, unused_attributes)]
+
+fn main() {
+    let mut x = #[deprecated] 1 + 2; //~ ERROR ambiguous
+
+    #[deprecated] x = 4; //~ ERROR ambiguous
+
+    x = #[deprecated] 5 as i32; //~ ERROR ambiguous
+
+    let _r = #[deprecated] 1..6; //~ ERROR ambiguous
+
+    println!("{}", x);
+}
diff --git a/tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr b/tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr
new file mode 100644
index 00000000000..0430570fd49
--- /dev/null
+++ b/tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr
@@ -0,0 +1,46 @@
+error: ambiguous outer attributes
+  --> $DIR/attr-binary-expr-ambigous.rs:6:17
+   |
+LL |     let mut x = #[deprecated] 1 + 2;
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+help: wrap the expression in parentheses
+   |
+LL |     let mut x = (#[deprecated] 1) + 2;
+   |                 +               +
+
+error: ambiguous outer attributes
+  --> $DIR/attr-binary-expr-ambigous.rs:8:5
+   |
+LL |     #[deprecated] x = 4;
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+help: wrap the expression in parentheses
+   |
+LL |     (#[deprecated] x) = 4;
+   |     +               +
+
+error: ambiguous outer attributes
+  --> $DIR/attr-binary-expr-ambigous.rs:10:9
+   |
+LL |     x = #[deprecated] 5 as i32;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: wrap the expression in parentheses
+   |
+LL |     x = (#[deprecated] 5) as i32;
+   |         +               +
+
+error: ambiguous outer attributes
+  --> $DIR/attr-binary-expr-ambigous.rs:12:14
+   |
+LL |     let _r = #[deprecated] 1..6;
+   |              ^^^^^^^^^^^^^^^^^^
+   |
+help: wrap the expression in parentheses
+   |
+LL |     let _r = (#[deprecated] 1)..6;
+   |              +               +
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/parser/expr-rarrow-call.fixed b/tests/ui/parser/expr-rarrow-call.fixed
new file mode 100644
index 00000000000..9a05e20092d
--- /dev/null
+++ b/tests/ui/parser/expr-rarrow-call.fixed
@@ -0,0 +1,33 @@
+//@ run-rustfix
+#![allow(
+    dead_code,
+    unused_must_use
+)]
+
+struct Named {
+    foo: usize
+}
+
+struct Unnamed(usize);
+
+fn named_struct_field_access(named: &Named) {
+    named.foo; //~ ERROR `->` used for field access or method call
+}
+
+fn unnamed_struct_field_access(unnamed: &Unnamed) {
+    unnamed.0; //~ ERROR `->` used for field access or method call
+}
+
+fn tuple_field_access(t: &(u8, u8)) {
+    t.0; //~ ERROR `->` used for field access or method call
+    t.1; //~ ERROR `->` used for field access or method call
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn method_call(foo: &Foo) {
+    foo.clone(); //~ ERROR `->` used for field access or method call
+}
+
+fn main() {}
diff --git a/tests/ui/parser/expr-rarrow-call.rs b/tests/ui/parser/expr-rarrow-call.rs
new file mode 100644
index 00000000000..760b0f6f345
--- /dev/null
+++ b/tests/ui/parser/expr-rarrow-call.rs
@@ -0,0 +1,33 @@
+//@ run-rustfix
+#![allow(
+    dead_code,
+    unused_must_use
+)]
+
+struct Named {
+    foo: usize
+}
+
+struct Unnamed(usize);
+
+fn named_struct_field_access(named: &Named) {
+    named->foo; //~ ERROR `->` used for field access or method call
+}
+
+fn unnamed_struct_field_access(unnamed: &Unnamed) {
+    unnamed->0; //~ ERROR `->` used for field access or method call
+}
+
+fn tuple_field_access(t: &(u8, u8)) {
+    t->0; //~ ERROR `->` used for field access or method call
+    t->1; //~ ERROR `->` used for field access or method call
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn method_call(foo: &Foo) {
+    foo->clone(); //~ ERROR `->` used for field access or method call
+}
+
+fn main() {}
diff --git a/tests/ui/parser/expr-rarrow-call.stderr b/tests/ui/parser/expr-rarrow-call.stderr
new file mode 100644
index 00000000000..90082f98cb5
--- /dev/null
+++ b/tests/ui/parser/expr-rarrow-call.stderr
@@ -0,0 +1,42 @@
+error: `->` used for field access or method call
+  --> $DIR/expr-rarrow-call.rs:14:10
+   |
+LL |     named->foo;
+   |          ^^ help: try using `.` instead
+   |
+   = help: the `.` operator will dereference the value if needed
+
+error: `->` used for field access or method call
+  --> $DIR/expr-rarrow-call.rs:18:12
+   |
+LL |     unnamed->0;
+   |            ^^ help: try using `.` instead
+   |
+   = help: the `.` operator will dereference the value if needed
+
+error: `->` used for field access or method call
+  --> $DIR/expr-rarrow-call.rs:22:6
+   |
+LL |     t->0;
+   |      ^^ help: try using `.` instead
+   |
+   = help: the `.` operator will dereference the value if needed
+
+error: `->` used for field access or method call
+  --> $DIR/expr-rarrow-call.rs:23:6
+   |
+LL |     t->1;
+   |      ^^ help: try using `.` instead
+   |
+   = help: the `.` operator will dereference the value if needed
+
+error: `->` used for field access or method call
+  --> $DIR/expr-rarrow-call.rs:30:8
+   |
+LL |     foo->clone();
+   |        ^^ help: try using `.` instead
+   |
+   = help: the `.` operator will dereference the value if needed
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/parser/issues/issue-118530-ice.rs b/tests/ui/parser/issues/issue-118530-ice.rs
index e758e5af4d9..cf14eebec2b 100644
--- a/tests/ui/parser/issues/issue-118530-ice.rs
+++ b/tests/ui/parser/issues/issue-118530-ice.rs
@@ -3,8 +3,9 @@ fn bar() -> String {
     [1, 2, 3].iter() //~ ERROR expected `;`, found `#`
     #[feature]
     attr::fn bar() -> String { //~ ERROR expected identifier, found keyword `fn`
-    //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `->`
+    //~^ ERROR expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
     //~| ERROR expected `;`, found `bar`
+    //~| ERROR `->` used for field access or method call
     #[attr]
     [1, 2, 3].iter().map().collect::<String>()
     #[attr]
diff --git a/tests/ui/parser/issues/issue-118530-ice.stderr b/tests/ui/parser/issues/issue-118530-ice.stderr
index ef573fb7ba3..75c6a40c744 100644
--- a/tests/ui/parser/issues/issue-118530-ice.stderr
+++ b/tests/ui/parser/issues/issue-118530-ice.stderr
@@ -33,11 +33,19 @@ LL |     attr::fn bar() -> String {
    |             |
    |             help: add `;` here
 
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `->`
+error: `->` used for field access or method call
   --> $DIR/issue-118530-ice.rs:5:20
    |
 LL |     attr::fn bar() -> String {
-   |                    ^^ expected one of `.`, `;`, `?`, `}`, or an operator
+   |                    ^^ help: try using `.` instead
+   |
+   = help: the `.` operator will dereference the value if needed
+
+error: expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
+  --> $DIR/issue-118530-ice.rs:5:30
+   |
+LL |     attr::fn bar() -> String {
+   |                              ^ expected one of 7 possible tokens
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs
new file mode 100644
index 00000000000..5881e4166a4
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/bindings.rs
@@ -0,0 +1,64 @@
+//@ run-pass
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn simple_vec(vec: Vec<u32>) -> u32 {
+    match vec {
+        deref!([]) => 100,
+        deref!([x]) if x == 4 => x + 4,
+        deref!([x]) => x,
+        deref!([1, x]) => x + 200,
+        deref!(ref slice) => slice.iter().sum(),
+        _ => 2000,
+    }
+}
+
+fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
+    match vecvec {
+        deref!([]) => 0,
+        deref!([deref!([x])]) => x,
+        deref!([deref!([0, x]) | deref!([1, x])]) => x,
+        deref!([ref x]) => x.iter().sum(),
+        deref!([deref!([]), deref!([1, x, y])]) => y - x,
+        _ => 2000,
+    }
+}
+
+fn ref_mut(val: u32) -> u32 {
+    let mut b = Box::new(0u32);
+    match &mut b {
+        deref!(_x) if false => unreachable!(),
+        deref!(x) => {
+            *x = val;
+        }
+        _ => unreachable!(),
+    }
+    let deref!(x) = &b else { unreachable!() };
+    *x
+}
+
+#[rustfmt::skip]
+fn or_and_guard(tuple: (u32, u32)) -> u32 {
+    let mut sum = 0;
+    let b = Box::new(tuple);
+    match b {
+        deref!((x, _) | (_, x)) if { sum += x; false } => {},
+        _ => {},
+    }
+    sum
+}
+
+fn main() {
+    assert_eq!(simple_vec(vec![1]), 1);
+    assert_eq!(simple_vec(vec![1, 2]), 202);
+    assert_eq!(simple_vec(vec![1, 2, 3]), 6);
+    assert_eq!(simple_vec(vec![4]), 8);
+
+    assert_eq!(nested_vec(vec![vec![0, 42]]), 42);
+    assert_eq!(nested_vec(vec![vec![1, 42]]), 42);
+    assert_eq!(nested_vec(vec![vec![1, 2, 3]]), 6);
+    assert_eq!(nested_vec(vec![vec![], vec![1, 2, 3]]), 1);
+
+    assert_eq!(ref_mut(42), 42);
+    assert_eq!(or_and_guard((10, 32)), 42);
+}
diff --git a/tests/ui/pattern/deref-patterns/branch.rs b/tests/ui/pattern/deref-patterns/branch.rs
new file mode 100644
index 00000000000..1bac1006d9d
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/branch.rs
@@ -0,0 +1,40 @@
+//@ run-pass
+// Test the execution of deref patterns.
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn branch(vec: Vec<u32>) -> u32 {
+    match vec {
+        deref!([]) => 0,
+        deref!([1, _, 3]) => 1,
+        deref!([2, ..]) => 2,
+        _ => 1000,
+    }
+}
+
+fn nested(vec: Vec<Vec<u32>>) -> u32 {
+    match vec {
+        deref!([deref!([]), ..]) => 1,
+        deref!([deref!([0, ..]), deref!([1, ..])]) => 2,
+        _ => 1000,
+    }
+}
+
+fn main() {
+    assert!(matches!(Vec::<u32>::new(), deref!([])));
+    assert!(matches!(vec![1], deref!([1])));
+    assert!(matches!(&vec![1], deref!([1])));
+    assert!(matches!(vec![&1], deref!([1])));
+    assert!(matches!(vec![vec![1]], deref!([deref!([1])])));
+
+    assert_eq!(branch(vec![]), 0);
+    assert_eq!(branch(vec![1, 2, 3]), 1);
+    assert_eq!(branch(vec![3, 2, 1]), 1000);
+    assert_eq!(branch(vec![2]), 2);
+    assert_eq!(branch(vec![2, 3]), 2);
+    assert_eq!(branch(vec![3, 2]), 1000);
+
+    assert_eq!(nested(vec![vec![], vec![2]]), 1);
+    assert_eq!(nested(vec![vec![0], vec![1]]), 2);
+    assert_eq!(nested(vec![vec![0, 2], vec![1, 2]]), 2);
+}
diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
new file mode 100644
index 00000000000..84b5ec09dc7
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
@@ -0,0 +1,24 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+use std::rc::Rc;
+
+struct Struct;
+
+fn cant_move_out_box(b: Box<Struct>) -> Struct {
+    match b {
+        //~^ ERROR: cannot move out of a shared reference
+        deref!(x) => x,
+        _ => unreachable!(),
+    }
+}
+
+fn cant_move_out_rc(rc: Rc<Struct>) -> Struct {
+    match rc {
+        //~^ ERROR: cannot move out of a shared reference
+        deref!(x) => x,
+        _ => unreachable!(),
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
new file mode 100644
index 00000000000..108db6d9e4b
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
@@ -0,0 +1,27 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/cant_move_out_of_pattern.rs:9:11
+   |
+LL |     match b {
+   |           ^
+LL |
+LL |         deref!(x) => x,
+   |                -
+   |                |
+   |                data moved here
+   |                move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/cant_move_out_of_pattern.rs:17:11
+   |
+LL |     match rc {
+   |           ^^
+LL |
+LL |         deref!(x) => x,
+   |                -
+   |                |
+   |                data moved here
+   |                move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/deref-patterns/closure_capture.rs b/tests/ui/pattern/deref-patterns/closure_capture.rs
new file mode 100644
index 00000000000..fc0ddedac2b
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/closure_capture.rs
@@ -0,0 +1,21 @@
+//@ run-pass
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {
+    let b = Box::new("aaa".to_string());
+    let f = || {
+        let deref!(ref s) = b else { unreachable!() };
+        assert_eq!(s.len(), 3);
+    };
+    assert_eq!(b.len(), 3);
+    f();
+
+    let mut b = Box::new("aaa".to_string());
+    let mut f = || {
+        let deref!(ref mut s) = b else { unreachable!() };
+        s.push_str("aa");
+    };
+    f();
+    assert_eq!(b.len(), 5);
+}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.rs b/tests/ui/pattern/deref-patterns/fake_borrows.rs
new file mode 100644
index 00000000000..35fa9cbf7d8
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.rs
@@ -0,0 +1,14 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+#[rustfmt::skip]
+fn main() {
+    let mut b = Box::new(false);
+    match b {
+        deref!(true) => {}
+        _ if { *b = true; false } => {}
+        //~^ ERROR cannot assign `*b` in match guard
+        deref!(false) => {}
+        _ => {},
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.stderr b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
new file mode 100644
index 00000000000..6a591e6416c
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
@@ -0,0 +1,12 @@
+error[E0510]: cannot assign `*b` in match guard
+  --> $DIR/fake_borrows.rs:9:16
+   |
+LL |     match b {
+   |           - value is immutable in match guard
+LL |         deref!(true) => {}
+LL |         _ if { *b = true; false } => {}
+   |                ^^^^^^^^^ cannot assign
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0510`.
diff --git a/tests/ui/pattern/deref-patterns/typeck.rs b/tests/ui/pattern/deref-patterns/typeck.rs
index ead6dcdbaf0..f23f7042cd8 100644
--- a/tests/ui/pattern/deref-patterns/typeck.rs
+++ b/tests/ui/pattern/deref-patterns/typeck.rs
@@ -4,6 +4,8 @@
 
 use std::rc::Rc;
 
+struct Struct;
+
 fn main() {
     let vec: Vec<u32> = Vec::new();
     match vec {
@@ -22,10 +24,12 @@ fn main() {
         deref!(1..) => {}
         _ => {}
     }
-    // FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
-    // place of type `str`.
-    // match "foo".to_string() {
-    //     box "foo" => {}
-    //     _ => {}
-    // }
+    let _: &Struct = match &Rc::new(Struct) {
+        deref!(x) => x,
+        _ => unreachable!(),
+    };
+    let _: &[Struct] = match &Rc::new(vec![Struct]) {
+        deref!(deref!(x)) => x,
+        _ => unreachable!(),
+    };
 }
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs
new file mode 100644
index 00000000000..040118449ec
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs
@@ -0,0 +1,17 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {
+    // FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
+    // place of type `str`.
+    match "foo".to_string() {
+        deref!("foo") => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match &"foo".to_string() {
+        deref!("foo") => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
new file mode 100644
index 00000000000..1c14802745a
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/typeck_fail.rs:8:16
+   |
+LL |     match "foo".to_string() {
+   |           ----------------- this expression has type `String`
+LL |         deref!("foo") => {}
+   |                ^^^^^ expected `str`, found `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/typeck_fail.rs:13:16
+   |
+LL |     match &"foo".to_string() {
+   |           ------------------ this expression has type `&String`
+LL |         deref!("foo") => {}
+   |                ^^^^^ expected `str`, found `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/proc-macro/issue-81555.rs b/tests/ui/proc-macro/issue-81555.rs
index 7a61a31952f..b337ab7ce37 100644
--- a/tests/ui/proc-macro/issue-81555.rs
+++ b/tests/ui/proc-macro/issue-81555.rs
@@ -10,6 +10,5 @@ use test_macros::identity_attr;
 fn main() {
     let _x;
     let y = ();
-    #[identity_attr]
-    _x = y;
+    (#[identity_attr] _x) = y;
 }
diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
index 5d11941414f..97fc1276f61 100644
--- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.rs
@@ -4,7 +4,7 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
     a
 }
 
-// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs`
+// The incorrect case without `for<'a>` is tested for in `rfc1623-3.rs`
 static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
     &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
 
@@ -26,10 +26,10 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct {
     foo: &Foo { bools: &[false, true] },
     bar: &Bar { bools: &[true, true] },
     f: &id,
-    //~^ ERROR implementation of `Fn` is not general enough
-    //~| ERROR implementation of `Fn` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
+    //~^ ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `Fn` is not general enough
+    //~| ERROR implementation of `Fn` is not general enough
 };
 
 // very simple test for a 'static static with default lifetime
diff --git a/tests/ui/rust-2018/async-ident-allowed.stderr b/tests/ui/rust-2018/async-ident-allowed.stderr
index b413c0fd9ba..378c81d3c77 100644
--- a/tests/ui/rust-2018/async-ident-allowed.stderr
+++ b/tests/ui/rust-2018/async-ident-allowed.stderr
@@ -11,7 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]`
+   = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(rust_2018_compatibility)]`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rust-2018/async-ident.stderr b/tests/ui/rust-2018/async-ident.stderr
index d15250c54ec..5b8d8184f4f 100644
--- a/tests/ui/rust-2018/async-ident.stderr
+++ b/tests/ui/rust-2018/async-ident.stderr
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `async` is a keyword in the 2018 edition
   --> $DIR/async-ident.rs:12:7
diff --git a/tests/ui/rust-2018/dyn-keyword.stderr b/tests/ui/rust-2018/dyn-keyword.stderr
index 6f9a5ddb14f..f8245bc88f5 100644
--- a/tests/ui/rust-2018/dyn-keyword.stderr
+++ b/tests/ui/rust-2018/dyn-keyword.stderr
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rust-2018/try-ident.stderr b/tests/ui/rust-2018/try-ident.stderr
index 74015ac9da4..eaf4c235697 100644
--- a/tests/ui/rust-2018/try-ident.stderr
+++ b/tests/ui/rust-2018/try-ident.stderr
@@ -11,7 +11,7 @@ note: the lint level is defined here
    |
 LL | #![warn(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
+   = note: `#[warn(keyword_idents_2018)]` implied by `#[warn(rust_2018_compatibility)]`
 
 warning: `try` is a keyword in the 2018 edition
   --> $DIR/try-ident.rs:12:4
diff --git a/tests/ui/rust-2018/try-macro.stderr b/tests/ui/rust-2018/try-macro.stderr
index 760378f0955..095c755539d 100644
--- a/tests/ui/rust-2018/try-macro.stderr
+++ b/tests/ui/rust-2018/try-macro.stderr
@@ -11,7 +11,7 @@ note: the lint level is defined here
    |
 LL | #![warn(rust_2018_compatibility)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
+   = note: `#[warn(keyword_idents_2018)]` implied by `#[warn(rust_2018_compatibility)]`
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/rust-2024/gen-kw.e2015.stderr b/tests/ui/rust-2024/gen-kw.e2015.stderr
new file mode 100644
index 00000000000..b12363184b7
--- /dev/null
+++ b/tests/ui/rust-2024/gen-kw.e2015.stderr
@@ -0,0 +1,26 @@
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:6:4
+   |
+LL | fn gen() {}
+   |    ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+note: the lint level is defined here
+  --> $DIR/gen-kw.rs:4:9
+   |
+LL | #![deny(rust_2024_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2024)]` implied by `#[deny(rust_2024_compatibility)]`
+
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:12:9
+   |
+LL |     let gen = r#gen;
+   |         ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rust-2024/gen-kw.e2018.stderr b/tests/ui/rust-2024/gen-kw.e2018.stderr
new file mode 100644
index 00000000000..e10fc4c4512
--- /dev/null
+++ b/tests/ui/rust-2024/gen-kw.e2018.stderr
@@ -0,0 +1,26 @@
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:6:4
+   |
+LL | fn gen() {}
+   |    ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+note: the lint level is defined here
+  --> $DIR/gen-kw.rs:4:9
+   |
+LL | #![deny(rust_2024_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(keyword_idents_2024)]` implied by `#[deny(rust_2024_compatibility)]`
+
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:12:9
+   |
+LL |     let gen = r#gen;
+   |         ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rust-2024/gen-kw.rs b/tests/ui/rust-2024/gen-kw.rs
new file mode 100644
index 00000000000..3d2a3f95165
--- /dev/null
+++ b/tests/ui/rust-2024/gen-kw.rs
@@ -0,0 +1,16 @@
+//@ revisions: e2015 e2018
+//@[e2018] edition: 2018
+
+#![deny(rust_2024_compatibility)]
+
+fn gen() {}
+//~^ ERROR `gen` is a keyword in the 2024 edition
+//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+
+fn main() {
+    let gen = r#gen;
+    //~^ ERROR `gen` is a keyword in the 2024 edition
+    //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+    //[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr
index 9d6d29ec74e..ae3a0391eea 100644
--- a/tests/ui/suggestions/derive-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr
@@ -74,22 +74,30 @@ LL | struct Struct {
 error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
   --> $DIR/derive-trait-for-method-call.rs:40:15
    |
+LL | enum Enum {
+   | --------- doesn't satisfy `Enum: Clone`
+...
 LL | struct Foo<X, Y> (X, Y);
    | ---------------- method `test` not found for this struct
 ...
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied:
-      `Instant: Default`
-      `Vec<Enum>: Clone`
-  --> $DIR/derive-trait-for-method-call.rs:20:9
+note: trait bound `Instant: Default` was not satisfied
+  --> $DIR/derive-trait-for-method-call.rs:20:40
    |
 LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
-   |         ^^^^^                          ^^^^^^^  ---------
-   |         |                              |
-   |         |                              unsatisfied trait bound introduced here
-   |         unsatisfied trait bound introduced here
+   |                                        ^^^^^^^  ---------
+   |                                        |
+   |                                        unsatisfied trait bound introduced here
+   = note: the following trait bounds were not satisfied:
+           `Enum: Clone`
+           which is required by `Vec<Enum>: Clone`
+help: consider annotating `Enum` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | enum Enum {
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed
index 232d1dd8138..69780648ab6 100644
--- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed
+++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed
@@ -12,7 +12,18 @@ impl Foo for S {}
 impl Bar for S {}
 
 fn test(foo: impl Foo + Bar) {
-    foo.hello(); //~ ERROR E0599
+    foo.hello(); //~ ERROR no method named `hello` found
+}
+
+trait Trait {
+    fn method(&self) {}
+}
+
+impl Trait for fn() {}
+
+#[allow(dead_code)]
+fn test2(f: impl Fn() -> (dyn std::fmt::Debug) + Trait) {
+    f.method(); //~ ERROR no method named `method` found
 }
 
 fn main() {
diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs
index ab25b362fed..f49512bdd62 100644
--- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs
+++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs
@@ -12,7 +12,18 @@ impl Foo for S {}
 impl Bar for S {}
 
 fn test(foo: impl Foo) {
-    foo.hello(); //~ ERROR E0599
+    foo.hello(); //~ ERROR no method named `hello` found
+}
+
+trait Trait {
+    fn method(&self) {}
+}
+
+impl Trait for fn() {}
+
+#[allow(dead_code)]
+fn test2(f: impl Fn() -> dyn std::fmt::Debug) {
+    f.method(); //~ ERROR no method named `method` found
 }
 
 fn main() {
diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
index 3a6052448cb..0aced78ddac 100644
--- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
+++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
@@ -12,6 +12,20 @@ help: the following trait defines an item `hello`, perhaps you need to restrict
 LL | fn test(foo: impl Foo + Bar) {
    |                       +++++
 
-error: aborting due to 1 previous error
+error[E0599]: no method named `method` found for type parameter `impl Fn() -> dyn std::fmt::Debug` in the current scope
+  --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:26:7
+   |
+LL | fn test2(f: impl Fn() -> dyn std::fmt::Debug) {
+   |             -------------------------------- method `method` not found for this type parameter
+LL |     f.method();
+   |       ^^^^^^ method not found in `impl Fn() -> dyn std::fmt::Debug`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `method`, perhaps you need to restrict type parameter `impl Fn() -> dyn std::fmt::Debug` with it:
+   |
+LL | fn test2(f: impl Fn() -> (dyn std::fmt::Debug) + Trait) {
+   |                          +                   +++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/issue-85347.rs b/tests/ui/suggestions/issue-85347.rs
index d14cf07d915..95e76e76cfa 100644
--- a/tests/ui/suggestions/issue-85347.rs
+++ b/tests/ui/suggestions/issue-85347.rs
@@ -2,11 +2,13 @@ use std::ops::Deref;
 trait Foo {
     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
     //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
-    //~| ERROR associated type bindings are not allowed here
     //~| HELP add missing
-    //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
     //~| ERROR associated type bindings are not allowed here
+    //~| HELP consider removing this type binding
+    //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
     //~| HELP add missing
+    //~| ERROR associated type bindings are not allowed here
+    //~| HELP consider removing this type binding
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr
index 45f87e539b4..de0aa09ce49 100644
--- a/tests/ui/suggestions/issue-85347.stderr
+++ b/tests/ui/suggestions/issue-85347.stderr
@@ -19,6 +19,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
    |                                              ^^^^^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+   |                                             ~~~~~~~~~~~~~~~
 
 error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/issue-85347.rs:3:42
@@ -44,6 +49,10 @@ LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
    |                                              ^^^^^^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+   |                                             ~~~~~~~~~~~~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs
new file mode 100644
index 00000000000..6a273997ee6
--- /dev/null
+++ b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs
@@ -0,0 +1,35 @@
+#![feature(dyn_star)] //~ WARNING the feature `dyn_star` is incomplete
+
+use std::future::Future;
+
+pub fn dyn_func<T>(
+    executor: impl FnOnce(T) -> dyn Future<Output = ()>,
+) -> Box<dyn FnOnce(T) -> dyn Future<Output = ()>> {
+    Box::new(executor) //~ ERROR may not live long enough
+}
+
+pub fn dyn_star_func<T>(
+    executor: impl FnOnce(T) -> dyn* Future<Output = ()>,
+) -> Box<dyn FnOnce(T) -> dyn* Future<Output = ()>> {
+    Box::new(executor) //~ ERROR may not live long enough
+}
+
+trait Trait {
+    fn method(&self) {}
+}
+
+impl Trait for fn() {}
+
+pub fn in_ty_param<T: Fn() -> dyn std::fmt::Debug> (t: T) {
+    t.method();
+    //~^ ERROR no method named `method` found for type parameter `T`
+}
+
+fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {
+    without_sized::<T>();
+    //~^ ERROR the size for values of type `T` cannot be known at compilation time
+}
+
+fn without_sized<T: Fn() -> &'static dyn std::fmt::Debug>() {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr
new file mode 100644
index 00000000000..f7fc17ea24f
--- /dev/null
+++ b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr
@@ -0,0 +1,78 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:1:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0599]: no method named `method` found for type parameter `T` in the current scope
+  --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:24:7
+   |
+LL | pub fn in_ty_param<T: Fn() -> dyn std::fmt::Debug> (t: T) {
+   |                    - method `method` not found for this type parameter
+LL |     t.method();
+   |       ^^^^^^ method not found in `T`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
+   |
+LL | pub fn in_ty_param<T: Fn() -> (dyn std::fmt::Debug) + Trait> (t: T) {
+   |                               +                   +++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:29:21
+   |
+LL | fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {
+   |               - this type parameter needs to be `Sized`
+LL |     without_sized::<T>();
+   |                     ^ doesn't have a size known at compile-time
+   |
+note: required by an implicit `Sized` bound in `without_sized`
+  --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:33:18
+   |
+LL | fn without_sized<T: Fn() -> &'static dyn std::fmt::Debug>() {}
+   |                  ^ required by the implicit `Sized` requirement on this type parameter in `without_sized`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {
+LL + fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug)>() {
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | fn without_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {}
+   |                                      +                   ++++++++++
+
+error[E0310]: the parameter type `impl FnOnce(T) -> dyn Future<Output = ()>` may not live long enough
+  --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:8:5
+   |
+LL |     Box::new(executor)
+   |     ^^^^^^^^^^^^^^^^^^
+   |     |
+   |     the parameter type `impl FnOnce(T) -> dyn Future<Output = ()>` must be valid for the static lifetime...
+   |     ...so that the type `impl FnOnce(T) -> dyn Future<Output = ()>` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     executor: impl FnOnce(T) -> (dyn Future<Output = ()>) + 'static,
+   |                                 +                       +++++++++++
+
+error[E0310]: the parameter type `impl FnOnce(T) -> Future<Output = ()>` may not live long enough
+  --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:14:5
+   |
+LL |     Box::new(executor)
+   |     ^^^^^^^^^^^^^^^^^^
+   |     |
+   |     the parameter type `impl FnOnce(T) -> Future<Output = ()>` must be valid for the static lifetime...
+   |     ...so that the type `impl FnOnce(T) -> Future<Output = ()>` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     executor: impl FnOnce(T) -> (dyn* Future<Output = ()>) + 'static,
+   |                                 +                        +++++++++++
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0277, E0310, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
index 74526b4dbc1..49a4db7491e 100644
--- a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
+++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
@@ -12,13 +12,6 @@ note: trait bound `(): Iterator` was not satisfied
    |
 LL | trait IteratorAlias = Iterator;
    |       -------------   ^^^^^^^^ unsatisfied trait bound introduced here
-note: trait bound `(): IteratorAlias` was not satisfied
-  --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
-   |
-LL | impl<I: IteratorAlias> Foo<I> {
-   |         ^^^^^^^^^^^^^  ------
-   |         |
-   |         unsatisfied trait bound introduced here
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr
index 822fc91e43f..141f565077a 100644
--- a/tests/ui/traits/track-obligations.stderr
+++ b/tests/ui/traits/track-obligations.stderr
@@ -2,7 +2,10 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b
   --> $DIR/track-obligations.rs:83:16
    |
 LL | struct ALayer<C>(C);
-   | ---------------- doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>`
+   | ---------------- doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
+...
+LL | struct AService;
+   | --------------- doesn't satisfy `<AService as Service<Req>>::Response = Res`
 ...
 LL | struct Client<C>(C);
    | ---------------- method `check` not found for this struct
@@ -10,27 +13,14 @@ LL | struct Client<C>(C);
 LL |     Client(()).check();
    |                ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
    |
-note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
-  --> $DIR/track-obligations.rs:35:14
-   |
-LL | pub trait ParticularServiceLayer<C>:
-   |           ----------------------
-LL |     Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
-note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
-  --> $DIR/track-obligations.rs:71:16
+note: trait bound `<AService as Service<Req>>::Response = Res` was not satisfied
+  --> $DIR/track-obligations.rs:24:21
    |
-LL | impl<C> Client<C>
-   |         ---------
+LL | impl<T> ParticularService for T
+   |         -----------------     -
 LL | where
-LL |     ALayer<C>: ParticularServiceLayer<C>,
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
-note: the trait `ParticularServiceLayer` must be implemented
-  --> $DIR/track-obligations.rs:34:1
-   |
-LL | / pub trait ParticularServiceLayer<C>:
-LL | |     Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
-   | |____________________________________________________________________^
+LL |     T: Service<Req, Response = Res>,
+   |                     ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
 
 error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
   --> $DIR/track-obligations.rs:87:11
diff --git a/tests/ui/unknown-language-item.rs b/tests/ui/unknown-language-item.rs
index 20ffef71497..ce206d20358 100644
--- a/tests/ui/unknown-language-item.rs
+++ b/tests/ui/unknown-language-item.rs
@@ -3,7 +3,7 @@
 
 #[lang = "foo"]
 fn bar() -> ! {
-//~^^ ERROR definition of an unknown language item: `foo`
+//~^^ ERROR definition of an unknown lang item: `foo`
     loop {}
 }
 
diff --git a/tests/ui/unknown-language-item.stderr b/tests/ui/unknown-language-item.stderr
index 1e0256867c5..832f1342418 100644
--- a/tests/ui/unknown-language-item.stderr
+++ b/tests/ui/unknown-language-item.stderr
@@ -1,8 +1,8 @@
-error[E0522]: definition of an unknown language item: `foo`
+error[E0522]: definition of an unknown lang item: `foo`
   --> $DIR/unknown-language-item.rs:4:1
    |
 LL | #[lang = "foo"]
-   | ^^^^^^^^^^^^^^^ definition of unknown language item `foo`
+   | ^^^^^^^^^^^^^^^ definition of unknown lang item `foo`
 
 error: aborting due to 1 previous error