about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/dependencies.yml19
-rw-r--r--.mailmap1
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs10
-rw-r--r--compiler/rustc_const_eval/messages.ftl2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs9
-rw-r--r--compiler/rustc_const_eval/src/errors.rs1
-rw-r--r--compiler/rustc_const_eval/src/lib.rs7
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs19
-rw-r--r--compiler/rustc_hir/src/hir.rs22
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs169
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs (renamed from compiler/rustc_hir_typeck/src/inherited.rs)14
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_middle/src/query/keys.rs109
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs4
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs8
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs18
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs25
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs28
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs3
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs6
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs6
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs1
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs38
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl10
-rw-r--r--compiler/rustc_parse/src/errors.rs17
-rw-r--r--compiler/rustc_parse/src/parser/path.rs24
-rw-r--r--compiler/rustc_passes/src/reachable.rs72
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs39
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs5
-rw-r--r--compiler/rustc_resolve/src/imports.rs55
-rw-r--r--compiler/rustc_resolve/src/late.rs53
-rw-r--r--compiler/rustc_resolve/src/lib.rs13
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs11
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs8
-rw-r--r--library/alloc/src/boxed.rs5
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/rc.rs5
-rw-r--r--library/alloc/src/string.rs5
-rw-r--r--library/alloc/src/sync.rs5
-rw-r--r--library/alloc/src/vec/mod.rs3
-rw-r--r--library/core/Cargo.toml3
-rw-r--r--library/core/src/array/equality.rs1
-rw-r--r--library/core/src/array/mod.rs2
-rw-r--r--library/core/src/char/convert.rs1
-rw-r--r--library/core/src/convert/num.rs4
-rw-r--r--library/core/src/iter/adapters/step_by.rs1
-rw-r--r--library/core/src/iter/range.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs2
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/net/parser.rs1
-rw-r--r--library/core/src/ops/deref.rs19
-rw-r--r--library/core/src/ops/mod.rs3
-rw-r--r--library/core/src/option.rs2
-rw-r--r--library/core/src/ptr/alignment.rs1
-rw-r--r--library/core/src/result.rs2
-rw-r--r--library/core/src/unit.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/lib.rs4
-rw-r--r--library/portable-simd/crates/core_simd/src/vector.rs1
-rw-r--r--library/proc_macro/src/bridge/client.rs128
-rw-r--r--library/proc_macro/src/bridge/mod.rs4
-rw-r--r--library/proc_macro/src/bridge/scoped_cell.rs64
-rw-r--r--library/std/src/fs.rs2
-rw-r--r--library/std/src/sys/pal/unix/fs.rs4
m---------library/stdarch0
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs6
m---------src/doc/edition-guide0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/unstable-book/src/language-features/adt-const-params.md35
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs6
-rw-r--r--src/tools/compiletest/src/header.rs1
-rw-r--r--src/tools/miri/.github/workflows/ci.yml13
-rw-r--r--src/tools/miri/CONTRIBUTING.md15
-rw-r--r--src/tools/miri/README.md2
-rw-r--r--src/tools/miri/cargo-miri/src/main.rs20
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs12
-rwxr-xr-xsrc/tools/miri/ci/ci.sh14
-rwxr-xr-xsrc/tools/miri/miri2
-rw-r--r--src/tools/miri/miri-script/src/commands.rs10
-rw-r--r--src/tools/miri/miri.bat2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs6
-rw-r--r--src/tools/miri/src/concurrency/thread.rs19
-rw-r--r--src/tools/miri/test-cargo-miri/Cargo.lock7
-rw-r--r--src/tools/miri/test-cargo-miri/Cargo.toml3
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs.rs63
-rw-r--r--src/tools/miri/tests/pass/async-closure-drop.rs40
-rw-r--r--src/tools/miri/tests/pass/async-closure-drop.stdout3
-rw-r--r--src/tools/miri/tests/pass/async-closure.rs34
-rw-r--r--src/tools/miri/tests/pass/async-closure.stdout7
-rw-r--r--src/tools/miri/tests/ui.rs13
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--tests/codegen/intrinsics/typed_swap.rs13
-rw-r--r--tests/codegen/loads.rs3
-rw-r--r--tests/codegen/overaligned-constant.rs2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir2
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir6
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir62
-rw-r--r--tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff54
-rw-r--r--tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff62
-rw-r--r--tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff26
-rw-r--r--tests/run-make/jobserver-error/Makefile4
-rw-r--r--tests/run-make/jobserver-error/cannot_open_fd.stderr2
-rw-r--r--tests/run-make/link-framework/Makefile23
-rw-r--r--tests/run-make/link-framework/dep-link-framework.rs4
-rw-r--r--tests/run-make/link-framework/dep-link-weak-framework.rs6
-rw-r--r--tests/run-make/link-framework/empty.rs1
-rw-r--r--tests/run-make/link-framework/link-both.rs4
-rw-r--r--tests/run-make/link-framework/link-framework.rs3
-rw-r--r--tests/run-make/link-framework/link-weak-framework.rs3
-rw-r--r--tests/run-pass-valgrind/osx-frameworks.rs21
-rw-r--r--tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs30
-rw-r--r--tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr91
-rw-r--r--tests/ui/async-await/future-sizes/async-awaiting-fut.stdout28
-rw-r--r--tests/ui/async-await/future-sizes/large-arg.stdout26
-rw-r--r--tests/ui/borrowck/cloning-in-async-block-121547.rs11
-rw-r--r--tests/ui/borrowck/cloning-in-async-block-121547.stderr22
-rw-r--r--tests/ui/cfg/diagnostics-same-crate.rs15
-rw-r--r--tests/ui/cfg/diagnostics-same-crate.stderr40
-rw-r--r--tests/ui/consts/auxiliary/issue-63226.rs13
-rw-r--r--tests/ui/consts/issue-63226.rs2
-rw-r--r--tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs17
-rw-r--r--tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs19
-rw-r--r--tests/ui/debuginfo/backtrace-dylib-dep.rs114
-rw-r--r--tests/ui/delegation/target-expr.rs38
-rw-r--r--tests/ui/delegation/target-expr.stderr65
-rw-r--r--tests/ui/generic-const-items/hkl_where_bounds.rs14
-rw-r--r--tests/ui/higher-ranked/trait-bounds/future.current.stderr2
-rw-r--r--tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs78
-rw-r--r--tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr16
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs59
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr78
-rw-r--r--tests/ui/linkage-attr/framework.omit.stderr8
-rw-r--r--tests/ui/linkage-attr/framework.rs30
-rw-r--r--tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs2
-rw-r--r--tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr17
-rw-r--r--tests/ui/pattern/deref-patterns/ref-mut.rs17
-rw-r--r--tests/ui/pattern/deref-patterns/ref-mut.stderr20
-rw-r--r--tests/ui/print_type_sizes/async.stdout10
-rw-r--r--tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs38
-rw-r--r--tests/ui/traits/trait-selection-ice-84727.rs38
-rw-r--r--tests/ui/traits/trait-selection-ice-84727.stderr47
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs26
-rw-r--r--tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs29
-rw-r--r--tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr13
-rw-r--r--triagebot.toml10
172 files changed, 2192 insertions, 784 deletions
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
index 1dc5b0e9d08..f4e409e0d49 100644
--- a/.github/workflows/dependencies.yml
+++ b/.github/workflows/dependencies.yml
@@ -6,8 +6,6 @@ on:
   schedule:
     # Run weekly
     - cron: '0 0 * * Sun'
-    # Re-bump deps every 4 hours
-    - cron: '0 */4 * * *'
   workflow_dispatch:
     # Needed so we can run it manually
 permissions:
@@ -42,7 +40,7 @@ jobs:
 
           # Exit with error if open and S-waiting-on-bors
           if [[ "$STATE" == "OPEN" && "$WAITING_ON_BORS" == "true" ]]; then
-            gh run cancel ${{ github.run_id }}
+            exit 1
           fi
 
   update:
@@ -65,10 +63,7 @@ jobs:
 
       - name: cargo update
         # Remove first line that always just says "Updating crates.io index"
-        # If there are no changes, cancel the job here
-        run: |
-          cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
-          git status --porcelain | grep -q Cargo.lock || gh run cancel ${{ github.run_id }}
+        run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
       - name: upload Cargo.lock artifact for use in PR
         uses: actions/upload-artifact@v4
         with:
@@ -95,11 +90,11 @@ jobs:
         uses: actions/checkout@v4
 
       - name: download Cargo.lock from update job
-        uses: actions/download-artifact@v3
+        uses: actions/download-artifact@v4
         with:
           name: Cargo-lock
       - name: download cargo-update log from update job
-        uses: actions/download-artifact@v3
+        uses: actions/download-artifact@v4
         with:
           name: cargo-updates
 
@@ -134,14 +129,14 @@ jobs:
           # Exit with error if PR is closed
           STATE=$(gh pr view cargo_update --repo $GITHUB_REPOSITORY --json state --jq '.state')
           if [[ "$STATE" != "OPEN" ]]; then
-            gh run cancel ${{ github.run_id }}
+            exit 1
           fi
 
           gh pr edit cargo_update --title "${PR_TITLE}" --body-file body.md --repo $GITHUB_REPOSITORY
 
       - name: open new pull request
-        # Only run if there wasn't an existing PR and if this is the weekly run
-        if: steps.edit.outcome != 'success' && github.event.schedule == '0 0 * * Sun'
+        # Only run if there wasn't an existing PR
+        if: steps.edit.outcome != 'success'
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: gh pr create --title "${PR_TITLE}" --body-file body.md --repo $GITHUB_REPOSITORY
diff --git a/.mailmap b/.mailmap
index 0d96f5f3d4f..93f5ca8157c 100644
--- a/.mailmap
+++ b/.mailmap
@@ -324,6 +324,7 @@ Katze <binary@benary.org>
 Keegan McAllister <mcallister.keegan@gmail.com> <kmcallister@mozilla.com>
 Kerem Kat <keremkat@gmail.com>
 Kevin Butler <haqkrs@gmail.com>
+Kevin Reid <kpreid@switchb.org> <kpreid@google.com>
 Kevin Jiang <kwj2104@columbia.edu>
 Kornel Lesiński <kornel@geekhood.net>
 Krishna Sai Veera Reddy <veerareddy@email.arizona.edu>
diff --git a/Cargo.lock b/Cargo.lock
index 9163538765d..c4501d6e574 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3784,6 +3784,7 @@ dependencies = [
 name = "rustc_driver_impl"
 version = "0.0.0"
 dependencies = [
+ "ctrlc",
  "libc",
  "rustc_ast",
  "rustc_ast_lowering",
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 35bd7d37992..578369de4d6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -4,6 +4,7 @@
 #![allow(rustc::untranslatable_diagnostic)]
 
 use either::Either;
+use hir::ClosureKind;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
@@ -463,6 +464,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
                 {
                     // We already suggest cloning for these cases in `explain_captures`.
+                } else if let UseSpans::ClosureUse {
+                    closure_kind:
+                        ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)),
+                    args_span: _,
+                    capture_kind_span: _,
+                    path_span,
+                } = move_spans
+                {
+                    self.suggest_cloning(err, ty, expr, path_span);
                 } else if self.suggest_hoisting_call_outside_loop(err, expr) {
                     // The place where the the type moves would be misleading to suggest clone.
                     // #121466
@@ -621,7 +631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     }
 
                     // FIXME: We make sure that this is a normal top-level binding,
-                    // but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern
+                    // but we could suggest `todo!()` for all uninitialized bindings in the pattern pattern
                     if let hir::StmtKind::Let(hir::LetStmt { span, ty, init: None, pat, .. }) =
                         &ex.kind
                         && let hir::PatKind::Binding(..) = pat.kind
@@ -749,7 +759,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         true
     }
 
-    /// In a move error that occurs on a call wihtin a loop, we try to identify cases where cloning
+    /// In a move error that occurs on a call within a loop, we try to identify cases where cloning
     /// the value would lead to a logic error. We infer these cases by seeing if the moved value is
     /// part of the logic to break the loop, either through an explicit `break` or if the expression
     /// is part of a `while let`.
@@ -950,7 +960,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             {
                 // FIXME: We could check that the call's *parent* takes `&mut val` to make the
                 // suggestion more targeted to the `mk_iter(val).next()` case. Maybe do that only to
-                // check for wheter to suggest `let value` or `let mut value`.
+                // check for whether to suggest `let value` or `let mut value`.
 
                 let span = in_loop.span;
                 if !finder.found_breaks.is_empty()
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index a5a5ae73d77..1a32958d362 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -20,6 +20,7 @@ use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
 };
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
 use rustc_span::Span;
 use rustc_symbol_mangling::typeid::{
     kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
@@ -551,6 +552,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             layout: TyAndLayout<'tcx>,
             offset: Size,
         ) {
+            if bx.cx.sess().opts.optimize == OptLevel::No {
+                // Don't emit metadata we're not going to use
+                return;
+            }
+
             if !scalar.is_uninit_valid() {
                 bx.noundef_metadata(load);
             }
@@ -667,6 +673,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             return;
         }
 
+        if self.cx.sess().opts.optimize == OptLevel::No {
+            // Don't emit metadata we're not going to use
+            return;
+        }
+
         unsafe {
             let llty = self.cx.val_ty(load);
             let v = [
@@ -1630,7 +1641,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             }
 
             let typeid = if let Some(instance) = instance {
-                typeid_for_instance(self.tcx, &instance, options)
+                typeid_for_instance(self.tcx, instance, options)
             } else {
                 typeid_for_fnabi(self.tcx, fn_abi, options)
             };
@@ -1678,7 +1689,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             }
 
             let kcfi_typeid = if let Some(instance) = instance {
-                kcfi_typeid_for_instance(self.tcx, &instance, options)
+                kcfi_typeid_for_instance(self.tcx, instance, options)
             } else {
                 kcfi_typeid_for_fnabi(self.tcx, fn_abi, options)
             };
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index 78c0725a637..1a2498c75a7 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -141,17 +141,17 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
 
         if self.tcx.sess.is_sanitizer_cfi_enabled() {
             if let Some(instance) = instance {
-                let typeid = typeid_for_instance(self.tcx, &instance, TypeIdOptions::empty());
+                let typeid = typeid_for_instance(self.tcx, instance, TypeIdOptions::empty());
                 self.set_type_metadata(llfn, typeid);
                 let typeid =
-                    typeid_for_instance(self.tcx, &instance, TypeIdOptions::GENERALIZE_POINTERS);
+                    typeid_for_instance(self.tcx, instance, TypeIdOptions::GENERALIZE_POINTERS);
                 self.add_type_metadata(llfn, typeid);
                 let typeid =
-                    typeid_for_instance(self.tcx, &instance, TypeIdOptions::NORMALIZE_INTEGERS);
+                    typeid_for_instance(self.tcx, instance, TypeIdOptions::NORMALIZE_INTEGERS);
                 self.add_type_metadata(llfn, typeid);
                 let typeid = typeid_for_instance(
                     self.tcx,
-                    &instance,
+                    instance,
                     TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
                 );
                 self.add_type_metadata(llfn, typeid);
@@ -182,7 +182,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             }
 
             if let Some(instance) = instance {
-                let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, &instance, options);
+                let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, instance, options);
                 self.set_kcfi_type_metadata(llfn, kcfi_typeid);
             } else {
                 let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 0046190d20c..d6aae60c338 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -146,6 +146,8 @@ const_eval_intern_kind = {$kind ->
     *[other] {""}
 }
 
+const_eval_interrupted = compilation was interrupted
+
 const_eval_invalid_align_details =
     invalid align passed to `{$name}`: {$align} is {$err_kind ->
         [not_power_of_two] not a power of 2
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 5a1c7cc4209..098a6201c4e 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,3 +1,5 @@
+use std::sync::atomic::Ordering::Relaxed;
+
 use either::{Left, Right};
 
 use rustc_hir::def::DefKind;
@@ -22,6 +24,7 @@ use crate::interpret::{
     InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
     StackPopCleanup,
 };
+use crate::CTRL_C_RECEIVED;
 
 // Returns a pointer to where the result lives
 #[instrument(level = "trace", skip(ecx, body))]
@@ -79,7 +82,11 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
     ecx.storage_live_for_always_live_locals()?;
 
     // The main interpreter loop.
-    while ecx.step()? {}
+    while ecx.step()? {
+        if CTRL_C_RECEIVED.load(Relaxed) {
+            throw_exhaust!(Interrupted);
+        }
+    }
 
     // Intern the result
     intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index cc32640408b..5c46ec799f1 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -884,6 +884,7 @@ impl ReportErrorExt for ResourceExhaustionInfo {
             ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
             ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
             ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
+            ResourceExhaustionInfo::Interrupted => const_eval_interrupted,
         }
     }
     fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 633caf8d092..50420aaec04 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -32,6 +32,8 @@ pub mod interpret;
 pub mod transform;
 pub mod util;
 
+use std::sync::atomic::AtomicBool;
+
 pub use errors::ReportErrorExt;
 
 use rustc_middle::{ty, util::Providers};
@@ -58,3 +60,8 @@ pub fn provide(providers: &mut Providers) {
         util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
     };
 }
+
+/// `rustc_driver::main` installs a handler that will set this to `true` if
+/// the compiler has been sent a request to shut down, such as by a Ctrl-C.
+/// This static lives here because it is only read by the interpreter.
+pub static CTRL_C_RECEIVED: AtomicBool = AtomicBool::new(false);
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index fcc0afd3488..e4fb13822f8 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+ctrlc = "3.4.4"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_lowering = { path = "../rustc_ast_lowering" }
 rustc_ast_passes = { path = "../rustc_ast_passes" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 716e31080dd..b4007aeb8d7 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -19,6 +19,7 @@ extern crate tracing;
 
 use rustc_ast as ast;
 use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
+use rustc_const_eval::CTRL_C_RECEIVED;
 use rustc_data_structures::profiling::{
     get_resident_set_size, print_time_passes_entry, TimePassesFormat,
 };
@@ -1518,6 +1519,22 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
     }
 }
 
+/// Install our usual `ctrlc` handler, which sets [`rustc_const_eval::CTRL_C_RECEIVED`].
+/// Making this handler optional lets tools can install a different handler, if they wish.
+pub fn install_ctrlc_handler() {
+    ctrlc::set_handler(move || {
+        // Indicate that we have been signaled to stop. If we were already signaled, exit
+        // immediately. In our interpreter loop we try to consult this value often, but if for
+        // whatever reason we don't get to that check or the cleanup we do upon finding that
+        // this bool has become true takes a long time, the exit here will promptly exit the
+        // process on the second Ctrl-C.
+        if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
+            std::process::exit(1);
+        }
+    })
+    .expect("Unable to install ctrlc handler");
+}
+
 pub fn main() -> ! {
     let start_time = Instant::now();
     let start_rss = get_resident_set_size();
@@ -1528,6 +1545,8 @@ pub fn main() -> ! {
     signal_handler::install();
     let mut callbacks = TimePassesCallbacks::default();
     let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
+    install_ctrlc_handler();
+
     let exit_code = catch_with_exit_code(|| {
         RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
             .set_using_internal_features(using_internal_features)
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index cc0ab05d422..a70d2ebbd62 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2289,21 +2289,15 @@ pub enum ImplItemKind<'hir> {
     Type(&'hir Ty<'hir>),
 }
 
-/// Bind a type to an associated type (i.e., `A = Foo`).
+/// An associated item binding.
 ///
-/// Bindings like `A: Debug` are represented as a special type `A =
-/// $::Debug` that is understood by the HIR ty lowering code.
+/// ### Examples
 ///
-/// FIXME(alexreg): why have a separate type for the binding case,
-/// wouldn't it be better to make the `ty` field an enum like the
-/// following?
-///
-/// ```ignore (pseudo-rust)
-/// enum TypeBindingKind {
-///    Equals(...),
-///    Binding(...),
-/// }
-/// ```
+/// * `Trait<A = Ty, B = Ty>`
+/// * `Trait<G<Ty> = Ty>`
+/// * `Trait<A: Bound>`
+/// * `Trait<C = { Ct }>` (under feature `associated_const_equality`)
+/// * `Trait<f(): Bound>` (under feature `return_type_notation`)
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct TypeBinding<'hir> {
     pub hir_id: HirId,
@@ -2336,7 +2330,7 @@ impl<'hir> From<AnonConst> for Term<'hir> {
 pub enum TypeBindingKind<'hir> {
     /// E.g., `Foo<Bar: Send>`.
     Constraint { bounds: &'hir [GenericBound<'hir>] },
-    /// E.g., `Foo<Bar = ()>`, `Foo<Bar = ()>`
+    /// E.g., `Foo<Bar = ()>`.
     Equality { term: Term<'hir> },
 }
 
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index dbf86f5cf74..5d97019416f 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -199,6 +199,7 @@ language_item_table! {
 
     Deref,                   sym::deref,               deref_trait,                Target::Trait,          GenericRequirement::Exact(0);
     DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait,          GenericRequirement::Exact(0);
+    DerefPure,               sym::deref_pure,          deref_pure_trait,           Target::Trait,          GenericRequirement::Exact(0);
     DerefTarget,             sym::deref_target,        deref_target,               Target::AssocTy,        GenericRequirement::None;
     Receiver,                sym::receiver,            receiver_trait,             Target::Trait,          GenericRequirement::None;
 
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 80be563686a..8c35da3ac7b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -9,8 +9,85 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa
 use super::HirTyLowerer;
 
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
+    /// Prohibit or lint against *bare* trait object types depending on the edition.
+    ///
+    /// *Bare* trait object types are ones that aren't preceeded by the keyword `dyn`.
+    /// In edition 2021 and onward we emit a hard error for them.
+    pub(super) fn prohibit_or_lint_bare_trait_object_ty(
+        &self,
+        self_ty: &hir::Ty<'_>,
+        in_path: bool,
+    ) {
+        let tcx = self.tcx();
+
+        let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
+            self_ty.kind
+        else {
+            return;
+        };
+
+        let needs_bracket = in_path
+            && !tcx
+                .sess
+                .source_map()
+                .span_to_prev_source(self_ty.span)
+                .ok()
+                .is_some_and(|s| s.trim_end().ends_with('<'));
+
+        let is_global = poly_trait_ref.trait_ref.path.is_global();
+
+        let mut sugg = vec![(
+            self_ty.span.shrink_to_lo(),
+            format!(
+                "{}dyn {}",
+                if needs_bracket { "<" } else { "" },
+                if is_global { "(" } else { "" },
+            ),
+        )];
+
+        if is_global || needs_bracket {
+            sugg.push((
+                self_ty.span.shrink_to_hi(),
+                format!(
+                    "{}{}",
+                    if is_global { ")" } else { "" },
+                    if needs_bracket { ">" } else { "" },
+                ),
+            ));
+        }
+
+        if self_ty.span.edition().at_least_rust_2021() {
+            let msg = "trait objects must include the `dyn` keyword";
+            let label = "add `dyn` keyword before this trait";
+            let mut diag =
+                rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
+            if self_ty.span.can_be_used_for_suggestions()
+                && !self.maybe_suggest_impl_trait(self_ty, &mut diag)
+            {
+                // FIXME: Only emit this suggestion if the trait is object safe.
+                diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable);
+            }
+            // Check if the impl trait that we are considering is an impl of a local trait.
+            self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
+            self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
+            diag.stash(self_ty.span, StashKey::TraitMissingMethod);
+        } else {
+            let msg = "trait objects without an explicit `dyn` are deprecated";
+            tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
+                if self_ty.span.can_be_used_for_suggestions() {
+                    lint.multipart_suggestion_verbose(
+                        "if this is an object-safe trait, use `dyn`",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+                self.maybe_suggest_blanket_trait_impl(self_ty, lint);
+            });
+        }
+    }
+
     /// Make sure that we are in the condition to suggest the blanket implementation.
-    pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
+    fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
         &self,
         self_ty: &hir::Ty<'_>,
         diag: &mut Diag<'_, G>,
@@ -75,9 +152,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     }
 
     /// Make sure that we are in the condition to suggest `impl Trait`.
-    fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
+    fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
         let tcx = self.tcx();
         let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
+        // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
+        //        and suggest `Trait0<Ty = impl Trait1>`.
         let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
             hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
                 (sig, generics, None)
@@ -186,71 +265,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         false
     }
 
-    pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
-        let tcx = self.tcx();
-        if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
-            self_ty.kind
-        {
-            let needs_bracket = in_path
-                && !tcx
-                    .sess
-                    .source_map()
-                    .span_to_prev_source(self_ty.span)
-                    .ok()
-                    .is_some_and(|s| s.trim_end().ends_with('<'));
-
-            let is_global = poly_trait_ref.trait_ref.path.is_global();
-
-            let mut sugg = Vec::from_iter([(
-                self_ty.span.shrink_to_lo(),
-                format!(
-                    "{}dyn {}",
-                    if needs_bracket { "<" } else { "" },
-                    if is_global { "(" } else { "" },
-                ),
-            )]);
+    fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) {
+        let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id);
 
-            if is_global || needs_bracket {
-                sugg.push((
-                    self_ty.span.shrink_to_hi(),
-                    format!(
-                        "{}{}",
-                        if is_global { ")" } else { "" },
-                        if needs_bracket { ">" } else { "" },
-                    ),
-                ));
+        if let Some((_, hir::Node::TypeBinding(binding))) = parents.next()
+            && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(obj_ty) } = binding.kind
+        {
+            if let Some((_, hir::Node::TraitRef(..))) = parents.next()
+                && let Some((_, hir::Node::Ty(ty))) = parents.next()
+                && let hir::TyKind::TraitObject(..) = ty.kind
+            {
+                // Assoc ty bounds aren't permitted inside trait object types.
+                return;
             }
 
-            if self_ty.span.edition().at_least_rust_2021() {
-                let msg = "trait objects must include the `dyn` keyword";
-                let label = "add `dyn` keyword before this trait";
-                let mut diag =
-                    rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
-                if self_ty.span.can_be_used_for_suggestions()
-                    && !self.maybe_lint_impl_trait(self_ty, &mut diag)
-                {
-                    diag.multipart_suggestion_verbose(
-                        label,
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-                // check if the impl trait that we are considering is a impl of a local trait
-                self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
-                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
+            let lo = if binding.gen_args.span_ext.is_dummy() {
+                binding.ident.span
             } else {
-                let msg = "trait objects without an explicit `dyn` are deprecated";
-                tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
-                    if self_ty.span.can_be_used_for_suggestions() {
-                        lint.multipart_suggestion_verbose(
-                            "if this is an object-safe trait, use `dyn`",
-                            sugg,
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                    self.maybe_lint_blanket_trait_impl(self_ty, lint);
-                });
+                binding.gen_args.span_ext
+            };
+            let hi = obj_ty.span;
+
+            if !lo.eq_ctxt(hi) {
+                return;
             }
+
+            diag.span_suggestion_verbose(
+                lo.between(hi),
+                "you might have meant to write a bound here",
+                ": ",
+                Applicability::MaybeIncorrect,
+            );
         }
     }
 }
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 a119ea450b4..a83b5b78f9c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2339,12 +2339,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 )
             }
             hir::TyKind::TraitObject(bounds, lifetime, repr) => {
-                self.maybe_lint_bare_trait(hir_ty, in_path);
+                self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path);
+
                 let repr = match repr {
                     TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
                     TraitObjectSyntax::DynStar => ty::DynStar,
                 };
-
                 self.lower_trait_object_ty(
                     hir_ty.span,
                     hir_ty.hir_id,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 3ec5894700f..b7786ec219c 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -101,8 +101,9 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_middle::middle;
+use rustc_middle::mir::interpret::GlobalId;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util;
 use rustc_session::parse::feature_err;
 use rustc_span::{symbol::sym, Span};
@@ -186,7 +187,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         let def_kind = tcx.def_kind(item_def_id);
         match def_kind {
             DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id),
-            DefKind::Const => tcx.ensure().const_eval_poly(item_def_id.into()),
+            DefKind::Const if tcx.generics_of(item_def_id).params.is_empty() => {
+                let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
+                let cid = GlobalId { instance, promoted: None };
+                let param_env = ty::ParamEnv::reveal_all();
+                tcx.ensure().eval_to_const_value_raw(param_env.and(cid));
+            }
             _ => (),
         }
     });
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 9b7db9e4c8e..e42db342f14 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -243,7 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
             Some(ret_coercion) => {
                 let ret_ty = ret_coercion.borrow().expected_ty();
-                let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
+                let ret_ty = self.infcx.shallow_resolve(ret_ty);
                 self.can_coerce(arm_ty, ret_ty)
                     && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
                     // The match arms need to unify for the case of `impl Trait`.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 40555bf14eb..36af5394015 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             bound_vars,
         );
 
-        let c_result = self.inh.infcx.canonicalize_response(result);
+        let c_result = self.infcx.canonicalize_response(result);
         self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
 
         // Normalize only after registering in `user_provided_sigs`.
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 140618e97cc..fe1e4e74973 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -347,7 +347,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
                 .any(|n| roots_reachable_from_non_diverging.visited(n));
 
             let infer_var_infos: UnordBag<_> = self
-                .inh
                 .infer_var_info
                 .borrow()
                 .items()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 8e0be7c7163..011607bacc6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
         let scope_tree = self.tcx.region_scope_tree(def_id);
         let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) };
-        let mut typeck_results = self.inh.typeck_results.borrow_mut();
+        let mut typeck_results = self.typeck_results.borrow_mut();
         typeck_results.rvalue_scopes = rvalue_scopes;
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index efa2862177e..74f27cfebbd 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -7,7 +7,7 @@ mod suggestions;
 use crate::coercion::DynamicCoerceMany;
 use crate::fallback::DivergingFallbackBehavior;
 use crate::fn_ctxt::checks::DivergingBlockBehavior;
-use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited};
+use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
 use hir::def_id::CRATE_DEF_ID;
 use rustc_errors::{DiagCtxt, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -108,7 +108,7 @@ pub struct FnCtxt<'a, 'tcx> {
 
     pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
 
-    pub(super) inh: &'a Inherited<'tcx>,
+    pub(super) root_ctxt: &'a TypeckRootCtxt<'tcx>,
 
     pub(super) fallback_has_occurred: Cell<bool>,
 
@@ -118,12 +118,12 @@ pub struct FnCtxt<'a, 'tcx> {
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn new(
-        inh: &'a Inherited<'tcx>,
+        root_ctxt: &'a TypeckRootCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         body_id: LocalDefId,
     ) -> FnCtxt<'a, 'tcx> {
         let (diverging_fallback_behavior, diverging_block_behavior) =
-            parse_never_type_options_attr(inh.tcx);
+            parse_never_type_options_attr(root_ctxt.tcx);
         FnCtxt {
             body_id,
             param_env,
@@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 stack: Vec::new(),
                 by_id: Default::default(),
             }),
-            inh,
+            root_ctxt,
             fallback_has_occurred: Cell::new(false),
             diverging_fallback_behavior,
             diverging_block_behavior,
@@ -206,9 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
-    type Target = Inherited<'tcx>;
+    type Target = TypeckRootCtxt<'tcx>;
     fn deref(&self) -> &Self::Target {
-        self.inh
+        self.root_ctxt
     }
 }
 
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 1fa799dcec7..be5cd6e9d48 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -95,8 +95,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
             Some(ref ty) => {
                 let o_ty = self.fcx.lower_ty(ty);
 
-                let c_ty =
-                    self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw));
+                let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw));
                 debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
                 self.fcx
                     .typeck_results
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 0b67b37df29..3a16884d5c7 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -31,7 +31,6 @@ pub mod expr_use_visitor;
 mod fallback;
 mod fn_ctxt;
 mod gather_locals;
-mod inherited;
 mod intrinsicck;
 mod mem_categorization;
 mod method;
@@ -39,11 +38,12 @@ mod op;
 mod pat;
 mod place_op;
 mod rvalue_scopes;
+mod typeck_root_ctxt;
 mod upvar;
 mod writeback;
 
 pub use fn_ctxt::FnCtxt;
-pub use inherited::Inherited;
+pub use typeck_root_ctxt::TypeckRootCtxt;
 
 use crate::check::check_fn;
 use crate::coercion::DynamicCoerceMany;
@@ -170,11 +170,11 @@ fn typeck_with_fallback<'tcx>(
 
     let param_env = tcx.param_env(def_id);
 
-    let inh = Inherited::new(tcx, def_id);
+    let root_ctxt = TypeckRootCtxt::new(tcx, def_id);
     if let Some(inspector) = inspector {
-        inh.infcx.attach_obligation_inspector(inspector);
+        root_ctxt.infcx.attach_obligation_inspector(inspector);
     }
-    let mut fcx = FnCtxt::new(&inh, param_env, def_id);
+    let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id);
 
     if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
         let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 4dc60f7c6da..861a00ce874 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -388,8 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if !pat_adjustments.is_empty() {
             debug!("default binding mode is now {:?}", def_bm);
-            self.inh
-                .typeck_results
+            self.typeck_results
                 .borrow_mut()
                 .pat_adjustments_mut()
                 .insert(pat.hir_id, pat_adjustments);
@@ -614,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => BindingMode::convert(ba),
         };
         // ...and store it in a side table:
-        self.inh.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
+        self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
 
         debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
 
@@ -2002,8 +2001,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        // FIXME(deref_patterns): use `DerefPure` for soundness
-        // FIXME(deref_patterns): use `DerefMut` when required
+        // Register a `DerefPure` bound, which is required by all `deref!()` pats.
+        self.register_bound(
+            expected,
+            tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)),
+            self.misc(span),
+        );
         // <expected as Deref>::Target
         let ty = Ty::new_projection(
             tcx,
@@ -2013,6 +2016,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = self.normalize(span, ty);
         let ty = self.try_structurally_resolve_type(span, ty);
         self.check_pat(inner, ty, pat_info);
+
+        // Check if the pattern has any `ref mut` bindings, which would require
+        // `DerefMut` to be emitted in MIR building instead of just `Deref`.
+        // We do this *after* checking the inner pattern, since we want to make
+        // sure to apply any match-ergonomics adjustments.
+        if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) {
+            self.register_bound(
+                expected,
+                tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
+                self.misc(span),
+            );
+        }
+
         expected
     }
 
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index b0950ed2800..e493e6a0a7e 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -16,7 +16,8 @@ use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, Trai
 use std::cell::RefCell;
 use std::ops::Deref;
 
-/// Closures defined within the function. For example:
+// Data shared between a "typeck root" and its nested bodies,
+/// e.g. closures defined within the function. For example:
 /// ```ignore (illustrative)
 /// fn foo() {
 ///     bar(move|| { ... })
@@ -24,8 +25,9 @@ use std::ops::Deref;
 /// ```
 /// Here, the function `foo()` and the closure passed to
 /// `bar()` will each have their own `FnCtxt`, but they will
-/// share the inherited fields.
-pub struct Inherited<'tcx> {
+/// share the inference context, will process obligations together,
+/// can access each other's local types (scoping permitted), etc.
+pub struct TypeckRootCtxt<'tcx> {
     pub(super) infcx: InferCtxt<'tcx>,
 
     pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>,
@@ -65,14 +67,14 @@ pub struct Inherited<'tcx> {
     pub(super) infer_var_info: RefCell<UnordMap<ty::TyVid, ty::InferVarInfo>>,
 }
 
-impl<'tcx> Deref for Inherited<'tcx> {
+impl<'tcx> Deref for TypeckRootCtxt<'tcx> {
     type Target = InferCtxt<'tcx>;
     fn deref(&self) -> &Self::Target {
         &self.infcx
     }
 }
 
-impl<'tcx> Inherited<'tcx> {
+impl<'tcx> TypeckRootCtxt<'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
 
@@ -83,7 +85,7 @@ impl<'tcx> Inherited<'tcx> {
             .build();
         let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
 
-        Inherited {
+        TypeckRootCtxt {
             typeck_results,
             fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)),
             infcx,
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 751d6de83f9..c86970635a5 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -482,6 +482,8 @@ pub enum ResourceExhaustionInfo {
     MemoryExhausted,
     /// The address space (of the target) is full.
     AddressSpaceFull,
+    /// The compiler got an interrupt signal (a user ran out of patience).
+    Interrupted,
 }
 
 /// A trait for machine-specific errors (or other "machine stop" conditions).
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 3b1d1a04d6f..9cbc4d10146 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -9,8 +9,7 @@ use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::{GenericArg, GenericArgsRef};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE};
 use rustc_hir::hir_id::{HirId, OwnerId};
-use rustc_query_system::query::DefIdCacheSelector;
-use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
+use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi;
@@ -22,7 +21,7 @@ pub struct LocalCrate;
 /// The `Key` trait controls what types can legally be used as the key
 /// for a query.
 pub trait Key: Sized {
-    // N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector<Self>;`,
+    // N.B. Most of the keys down below have `type Cache<V> = DefaultCache<Self, V>;`,
     //      it would be reasonable to use associated type defaults, to remove the duplication...
     //
     //      ...But r-a doesn't support them yet and using a default here causes r-a to not infer
@@ -30,7 +29,7 @@ pub trait Key: Sized {
     //      type defaults, please restrain from using them here <3
     //
     //      r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693>
-    type CacheSelector;
+    type Cache<V>;
 
     /// In the event that a cycle occurs, if no explicit span has been
     /// given for a query with key `self`, what span should we use?
@@ -56,7 +55,7 @@ pub trait AsLocalKey: Key {
 }
 
 impl Key for () {
-    type CacheSelector = SingleCacheSelector;
+    type Cache<V> = SingleCache<V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -64,7 +63,7 @@ impl Key for () {
 }
 
 impl<'tcx> Key for ty::InstanceDef<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.def_id())
@@ -81,7 +80,7 @@ impl<'tcx> AsLocalKey for ty::InstanceDef<'tcx> {
 }
 
 impl<'tcx> Key for ty::Instance<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.def_id())
@@ -89,7 +88,7 @@ impl<'tcx> Key for ty::Instance<'tcx> {
 }
 
 impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.instance.default_span(tcx)
@@ -97,7 +96,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -105,7 +104,7 @@ impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
 }
 
 impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -113,7 +112,7 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
 }
 
 impl Key for CrateNum {
-    type CacheSelector = VecCacheSelector<Self>;
+    type Cache<V> = VecCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -130,7 +129,7 @@ impl AsLocalKey for CrateNum {
 }
 
 impl Key for OwnerId {
-    type CacheSelector = VecCacheSelector<Self>;
+    type Cache<V> = VecCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.to_def_id().default_span(tcx)
@@ -142,7 +141,7 @@ impl Key for OwnerId {
 }
 
 impl Key for LocalDefId {
-    type CacheSelector = VecCacheSelector<Self>;
+    type Cache<V> = VecCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.to_def_id().default_span(tcx)
@@ -154,7 +153,7 @@ impl Key for LocalDefId {
 }
 
 impl Key for DefId {
-    type CacheSelector = DefIdCacheSelector;
+    type Cache<V> = DefIdCache<V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
@@ -176,7 +175,7 @@ impl AsLocalKey for DefId {
 }
 
 impl Key for LocalModDefId {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
@@ -189,7 +188,7 @@ impl Key for LocalModDefId {
 }
 
 impl Key for ModDefId {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
@@ -211,7 +210,7 @@ impl AsLocalKey for ModDefId {
 }
 
 impl Key for SimplifiedType {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -219,7 +218,7 @@ impl Key for SimplifiedType {
 }
 
 impl Key for (DefId, DefId) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -227,7 +226,7 @@ impl Key for (DefId, DefId) {
 }
 
 impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -235,7 +234,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
 }
 
 impl Key for (DefId, LocalDefId) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -243,7 +242,7 @@ impl Key for (DefId, LocalDefId) {
 }
 
 impl Key for (LocalDefId, DefId) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -251,7 +250,7 @@ impl Key for (LocalDefId, DefId) {
 }
 
 impl Key for (LocalDefId, LocalDefId) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -259,7 +258,7 @@ impl Key for (LocalDefId, LocalDefId) {
 }
 
 impl Key for (DefId, Ident) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.0)
@@ -272,7 +271,7 @@ impl Key for (DefId, Ident) {
 }
 
 impl Key for (LocalDefId, LocalDefId, Ident) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -280,7 +279,7 @@ impl Key for (LocalDefId, LocalDefId, Ident) {
 }
 
 impl Key for (CrateNum, DefId) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.1.default_span(tcx)
@@ -297,7 +296,7 @@ impl AsLocalKey for (CrateNum, DefId) {
 }
 
 impl Key for (CrateNum, SimplifiedType) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -314,7 +313,7 @@ impl AsLocalKey for (CrateNum, SimplifiedType) {
 }
 
 impl Key for (DefId, SimplifiedType) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -322,7 +321,7 @@ impl Key for (DefId, SimplifiedType) {
 }
 
 impl<'tcx> Key for GenericArgsRef<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -330,7 +329,7 @@ impl<'tcx> Key for GenericArgsRef<'tcx> {
 }
 
 impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -338,7 +337,7 @@ impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) {
 }
 
 impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         (self.0).def.default_span(tcx)
@@ -346,7 +345,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
 }
 
 impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -354,7 +353,7 @@ impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) {
 }
 
 impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.1.def_id)
@@ -362,7 +361,7 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
 }
 
 impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.def_id())
@@ -370,7 +369,7 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
 }
 
 impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.def_id())
@@ -378,7 +377,7 @@ impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
 }
 
 impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.0.def_id())
@@ -386,7 +385,7 @@ impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
 }
 
 impl<'tcx> Key for GenericArg<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -394,7 +393,7 @@ impl<'tcx> Key for GenericArg<'tcx> {
 }
 
 impl<'tcx> Key for ty::Const<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -402,7 +401,7 @@ impl<'tcx> Key for ty::Const<'tcx> {
 }
 
 impl<'tcx> Key for Ty<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -418,7 +417,7 @@ impl<'tcx> Key for Ty<'tcx> {
 }
 
 impl<'tcx> Key for TyAndLayout<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -426,7 +425,7 @@ impl<'tcx> Key for TyAndLayout<'tcx> {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -434,7 +433,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
 }
 
 impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -442,7 +441,7 @@ impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> {
 }
 
 impl<'tcx> Key for ty::ParamEnv<'tcx> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -450,7 +449,7 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> {
 }
 
 impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.value.default_span(tcx)
@@ -462,7 +461,7 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
 }
 
 impl Key for Symbol {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -470,7 +469,7 @@ impl Key for Symbol {
 }
 
 impl Key for Option<Symbol> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -480,7 +479,7 @@ impl Key for Option<Symbol> {
 /// Canonical query goals correspond to abstract trait operations that
 /// are not tied to any crate in particular.
 impl<'tcx, T: Clone> Key for Canonical<'tcx, T> {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -488,7 +487,7 @@ impl<'tcx, T: Clone> Key for Canonical<'tcx, T> {
 }
 
 impl Key for (Symbol, u32, u32) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -496,7 +495,7 @@ impl Key for (Symbol, u32, u32) {
 }
 
 impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -504,7 +503,7 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, abi::VariantIdx) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -512,7 +511,7 @@ impl<'tcx> Key for (Ty<'tcx>, abi::VariantIdx) {
 }
 
 impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -520,7 +519,7 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
 }
 
 impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -528,7 +527,7 @@ impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
 }
 
 impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.0.default_span(tcx)
@@ -536,7 +535,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -544,7 +543,7 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
 }
 
 impl Key for HirId {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.hir().span(*self)
@@ -557,7 +556,7 @@ impl Key for HirId {
 }
 
 impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    type Cache<V> = DefaultCache<Self, V>;
 
     // Just forward to `Ty<'tcx>`
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 38cfd11a016..5e4454db3e2 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -73,7 +73,7 @@ use rustc_hir::lang_items::{LangItem, LanguageItems};
 use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate};
 use rustc_index::IndexVec;
 use rustc_query_system::ich::StableHashingContext;
-use rustc_query_system::query::{try_get_cached, CacheSelector, QueryCache, QueryMode, QueryState};
+use rustc_query_system::query::{try_get_cached, QueryCache, QueryMode, QueryState};
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::cstore::{CrateDepKind, CrateSource};
 use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 8d88488e167..e3588a7afdc 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -336,9 +336,7 @@ macro_rules! define_callbacks {
                     ))
                 }
 
-                pub type Storage<'tcx> = <
-                    <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>
-                >::Cache;
+                pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
 
                 // Ensure that keys grow no larger than 64 bytes
                 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 65574f5702b..4fec5653a79 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -335,7 +335,7 @@ impl<'tcx> InstanceDef<'tcx> {
 
 fn fmt_instance(
     f: &mut fmt::Formatter<'_>,
-    instance: &Instance<'_>,
+    instance: Instance<'_>,
     type_length: Option<rustc_session::Limit>,
 ) -> fmt::Result {
     ty::tls::with(|tcx| {
@@ -369,9 +369,9 @@ fn fmt_instance(
     }
 }
 
-pub struct ShortInstance<'a, 'tcx>(pub &'a Instance<'tcx>, pub usize);
+pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize);
 
-impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> {
+impl<'tcx> fmt::Display for ShortInstance<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt_instance(f, self.0, Some(rustc_session::Limit(self.1)))
     }
@@ -379,7 +379,7 @@ impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> {
 
 impl<'tcx> fmt::Display for Instance<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt_instance(f, self, None)
+        fmt_instance(f, *self, None)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3f0a3a1a7bf..914b19efc7e 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -804,7 +804,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             ty::Str => p!("str"),
             ty::Coroutine(did, args) => {
-                p!(write("{{"));
+                p!("{{");
                 let coroutine_kind = self.tcx().coroutine_kind(did).unwrap();
                 let should_print_movability = self.should_print_verbose()
                     || matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
@@ -818,9 +818,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
                 if !self.should_print_verbose() {
                     p!(write("{}", coroutine_kind));
-                    // FIXME(eddyb) should use `def_span`.
-                    if let Some(did) = did.as_local() {
-                        let span = self.tcx().def_span(did);
+                    if coroutine_kind.is_fn_like() {
+                        // If we are printing an `async fn` coroutine type, then give the path
+                        // of the fn, instead of its span, because that will in most cases be
+                        // more helpful for the reader than just a source location.
+                        //
+                        // This will look like:
+                        //    {async fn body of some_fn()}
+                        let did_of_the_fn_item = self.tcx().parent(did);
+                        p!(" of ", print_def_path(did_of_the_fn_item, args), "()");
+                    } else if let Some(local_did) = did.as_local() {
+                        let span = self.tcx().def_span(local_did);
                         p!(write(
                             "@{}",
                             // This may end up in stderr diagnostics but it may also be emitted
@@ -828,7 +836,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                             self.tcx().sess.source_map().span_to_embeddable_string(span)
                         ));
                     } else {
-                        p!(write("@"), print_def_path(did, args));
+                        p!("@", print_def_path(did, args));
                     }
                 } else {
                     p!(print_def_path(did, args));
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index d8541f4b25a..827b7e088ce 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -430,6 +430,31 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
     }
 
+    /// Does the pattern recursively contain a `ref mut` binding in it?
+    ///
+    /// This is used to determined whether a `deref` pattern should emit a `Deref`
+    /// or `DerefMut` call for its pattern scrutinee.
+    ///
+    /// 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 {
+        let mut has_ref_mut = false;
+        pat.walk(|pat| {
+            if let hir::PatKind::Binding(_, id, _, _) = pat.kind
+                && let Some(ty::BindByReference(ty::Mutability::Mut)) =
+                    self.pat_binding_modes().get(id)
+            {
+                has_ref_mut = true;
+                // No need to continue recursing
+                false
+            } else {
+                true
+            }
+        });
+        has_ref_mut
+    }
+
     /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
     /// by the closure.
     pub fn closure_min_captures_flattened(
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 6b7ab892a96..6d083e66a9b 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1006,6 +1006,10 @@ struct Candidate<'pat, 'tcx> {
     /// If the candidate matches, bindings and ascriptions must be established.
     extra_data: PatternExtraData<'tcx>,
 
+    /// If we filled `self.subcandidate`, we store here the span of the or-pattern they came from.
+    // Invariant: it is `None` iff `subcandidates.is_empty()`.
+    or_span: Option<Span>,
+
     /// The block before the `bindings` have been established.
     pre_binding_block: Option<BasicBlock>,
     /// The pre-binding block of the next candidate.
@@ -1028,6 +1032,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
             extra_data: flat_pat.extra_data,
             has_guard,
             subcandidates: Vec::new(),
+            or_span: None,
             otherwise_block: None,
             pre_binding_block: None,
             next_candidate_pre_binding_block: None,
@@ -1280,7 +1285,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 //
                 // only generates a single switch.
                 candidate.subcandidates = self.create_or_subcandidates(pats, candidate.has_guard);
-                candidate.match_pairs.pop();
+                let first_match_pair = candidate.match_pairs.pop().unwrap();
+                candidate.or_span = Some(first_match_pair.pattern.span);
                 split_or_candidate = true;
             }
         }
@@ -1290,8 +1296,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // At least one of the candidates has been split into subcandidates.
                 // We need to change the candidate list to include those.
                 let mut new_candidates = Vec::new();
-
-                for candidate in candidates {
+                for candidate in candidates.iter_mut() {
                     candidate.visit_leaves(|leaf_candidate| new_candidates.push(leaf_candidate));
                 }
                 self.match_simplified_candidates(
@@ -1301,6 +1306,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     otherwise_block,
                     &mut *new_candidates,
                 );
+
+                for candidate in candidates {
+                    self.merge_trivial_subcandidates(candidate);
+                }
             } else {
                 self.match_simplified_candidates(
                     span,
@@ -1534,16 +1543,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             &mut or_candidate_refs,
         );
         candidate.subcandidates = or_candidates;
-        self.merge_trivial_subcandidates(candidate, self.source_info(or_span));
+        candidate.or_span = Some(or_span);
+        self.merge_trivial_subcandidates(candidate);
     }
 
     /// Try to merge all of the subcandidates of the given candidate into one.
     /// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
-    fn merge_trivial_subcandidates(
-        &mut self,
-        candidate: &mut Candidate<'_, 'tcx>,
-        source_info: SourceInfo,
-    ) {
+    fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
         if candidate.subcandidates.is_empty() || candidate.has_guard {
             // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
             return;
@@ -1553,7 +1559,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         // Not `Iterator::all` because we don't want to short-circuit.
         for subcandidate in &mut candidate.subcandidates {
-            self.merge_trivial_subcandidates(subcandidate, source_info);
+            self.merge_trivial_subcandidates(subcandidate);
 
             // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
             can_merge &=
@@ -1562,6 +1568,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         if can_merge {
             let any_matches = self.cfg.start_new_block();
+            let or_span = candidate.or_span.take().unwrap();
+            let source_info = self.source_info(or_span);
             for subcandidate in mem::take(&mut candidate.subcandidates) {
                 let or_block = subcandidate.pre_binding_block.unwrap();
                 self.cfg.goto(or_block, source_info, any_matches);
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 97b94a0b362..bf1906f370b 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -82,7 +82,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     &*candidate.match_pairs
                 {
                     candidate.subcandidates = self.create_or_subcandidates(pats, has_guard);
-                    candidate.match_pairs.pop();
+                    let first_match_pair = candidate.match_pairs.pop().unwrap();
+                    candidate.or_span = Some(first_match_pair.pattern.span);
                 }
                 candidate
             })
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 78c0615b165..5f74841151c 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -165,7 +165,7 @@ impl<'tcx> Inliner<'tcx> {
         caller_body: &mut Body<'tcx>,
         callsite: &CallSite<'tcx>,
     ) -> Result<std::ops::Range<BasicBlock>, &'static str> {
-        self.check_mir_is_available(caller_body, &callsite.callee)?;
+        self.check_mir_is_available(caller_body, callsite.callee)?;
 
         let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
         let cross_crate_inlinable = self.tcx.cross_crate_inlinable(callsite.callee.def_id());
@@ -298,7 +298,7 @@ impl<'tcx> Inliner<'tcx> {
     fn check_mir_is_available(
         &self,
         caller_body: &Body<'tcx>,
-        callee: &Instance<'tcx>,
+        callee: Instance<'tcx>,
     ) -> Result<(), &'static str> {
         let caller_def_id = caller_body.source.def_id();
         let callee_def_id = callee.def_id();
@@ -354,7 +354,7 @@ impl<'tcx> Inliner<'tcx> {
 
             // If we know for sure that the function we're calling will itself try to
             // call us, then we avoid inlining that function.
-            if self.tcx.mir_callgraph_reachable((*callee, caller_def_id.expect_local())) {
+            if self.tcx.mir_callgraph_reachable((callee, caller_def_id.expect_local())) {
                 return Err("caller might be reachable from callee (query cycle avoidance)");
             }
 
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 94a95428ab0..b60ee7649b2 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -1015,8 +1015,8 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
         bug!();
     };
 
-    // We use `*mut Self` here because we only need to emit an ABI-compatible shim body,
-    // rather than match the signature exactly.
+    // We use `&mut Self` here because we only need to emit an ABI-compatible shim body,
+    // rather than match the signature exactly (which might take `&self` instead).
     //
     // The self type here is a coroutine-closure, not a coroutine, and we never read from
     // it because it never has any captures, because this is only true in the Fn/FnMut
@@ -1025,7 +1025,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
     if receiver_by_ref {
         // Triple-check that there's no captures here.
         assert_eq!(args.as_coroutine_closure().tupled_upvars_ty(), tcx.types.unit);
-        self_ty = Ty::new_mut_ptr(tcx, self_ty);
+        self_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, self_ty);
     }
 
     let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 35a052166bd..c746041ebd8 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -19,6 +19,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
         let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         'blocks: for block in body.basic_blocks_mut() {
             for stmt in block.statements.iter_mut() {
+                // Simplify `assume` of a known value: either a NOP or unreachable.
                 if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind
                     && let NonDivergingIntrinsic::Assume(discr) = intrinsic
                     && let Operand::Constant(ref c) = discr
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index a51b1c34a1a..3285cbd0432 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -397,7 +397,7 @@ fn collect_items_rec<'tcx>(
                 let instance = Instance::mono(tcx, def_id);
 
                 // Sanity check whether this ended up being collected accidentally
-                debug_assert!(should_codegen_locally(tcx, &instance));
+                debug_assert!(should_codegen_locally(tcx, instance));
 
                 let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
                 // Nested statics have no type.
@@ -429,7 +429,7 @@ fn collect_items_rec<'tcx>(
         }
         MonoItem::Fn(instance) => {
             // Sanity check whether this ended up being collected accidentally
-            debug_assert!(should_codegen_locally(tcx, &instance));
+            debug_assert!(should_codegen_locally(tcx, instance));
 
             // Keep track of the monomorphization recursion depth
             recursion_depth_reset = Some(check_recursion_limit(
@@ -474,7 +474,7 @@ fn collect_items_rec<'tcx>(
                         }
                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
                             let instance = Instance::mono(tcx, *def_id);
-                            if should_codegen_locally(tcx, &instance) {
+                            if should_codegen_locally(tcx, instance) {
                                 trace!("collecting static {:?}", def_id);
                                 used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
                             }
@@ -557,7 +557,7 @@ fn collect_items_rec<'tcx>(
 /// If the type name is longer than before+after, it will be written to a file.
 fn shrunk_instance_name<'tcx>(
     tcx: TyCtxt<'tcx>,
-    instance: &Instance<'tcx>,
+    instance: Instance<'tcx>,
 ) -> (String, Option<PathBuf>) {
     let s = instance.to_string();
 
@@ -603,7 +603,7 @@ fn check_recursion_limit<'tcx>(
     if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
         let def_span = tcx.def_span(def_id);
         let def_path_str = tcx.def_path_str(def_id);
-        let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
+        let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance);
         let mut path = PathBuf::new();
         let was_written = if let Some(written_to_path) = written_to_path {
             path = written_to_path;
@@ -645,7 +645,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     //
     // Bail out in these cases to avoid that bad user experience.
     if !tcx.type_length_limit().value_within_limit(type_length) {
-        let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
+        let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance);
         let span = tcx.def_span(instance.def_id());
         let mut path = PathBuf::new();
         let was_written = if let Some(path2) = written_to_path {
@@ -892,7 +892,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 if let ty::Closure(def_id, args) = *source_ty.kind() {
                     let instance =
                         Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce);
-                    if should_codegen_locally(self.tcx, &instance) {
+                    if should_codegen_locally(self.tcx, instance) {
                         self.used_items.push(create_fn_mono_item(self.tcx, instance, span));
                     }
                 } else {
@@ -902,7 +902,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
             mir::Rvalue::ThreadLocalRef(def_id) => {
                 assert!(self.tcx.is_thread_local_static(def_id));
                 let instance = Instance::mono(self.tcx, def_id);
-                if should_codegen_locally(self.tcx, &instance) {
+                if should_codegen_locally(self.tcx, instance) {
                     trace!("collecting thread-local static {:?}", def_id);
                     self.used_items.push(respan(span, MonoItem::Static(def_id)));
                 }
@@ -929,7 +929,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
         let tcx = self.tcx;
         let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
             let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
-            if should_codegen_locally(tcx, &instance) {
+            if should_codegen_locally(tcx, instance) {
                 this.used_items.push(create_fn_mono_item(tcx, instance, source));
             }
         };
@@ -962,7 +962,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                         }
                         mir::InlineAsmOperand::SymStatic { def_id } => {
                             let instance = Instance::mono(self.tcx, def_id);
-                            if should_codegen_locally(self.tcx, &instance) {
+                            if should_codegen_locally(self.tcx, instance) {
                                 trace!("collecting asm sym static {:?}", def_id);
                                 self.used_items.push(respan(source, MonoItem::Static(def_id)));
                             }
@@ -1051,7 +1051,7 @@ fn visit_instance_use<'tcx>(
     output: &mut MonoItems<'tcx>,
 ) {
     debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
-    if !should_codegen_locally(tcx, &instance) {
+    if !should_codegen_locally(tcx, instance) {
         return;
     }
     if let ty::InstanceDef::Intrinsic(def_id) = instance.def {
@@ -1063,13 +1063,13 @@ fn visit_instance_use<'tcx>(
             // codegen a call to that function without generating code for the function itself.
             let def_id = tcx.lang_items().get(LangItem::PanicNounwind).unwrap();
             let panic_instance = Instance::mono(tcx, def_id);
-            if should_codegen_locally(tcx, &panic_instance) {
+            if should_codegen_locally(tcx, panic_instance) {
                 output.push(create_fn_mono_item(tcx, panic_instance, source));
             }
         } else if tcx.has_attr(def_id, sym::rustc_intrinsic) {
             // Codegen the fallback body of intrinsics with fallback bodies
             let instance = ty::Instance::new(def_id, instance.args);
-            if should_codegen_locally(tcx, &instance) {
+            if should_codegen_locally(tcx, instance) {
                 output.push(create_fn_mono_item(tcx, instance, source));
             }
         }
@@ -1107,7 +1107,7 @@ fn visit_instance_use<'tcx>(
 
 /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
 /// can just link to the upstream crate and therefore don't need a mono item.
-pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
+pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
     let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
         return true;
     };
@@ -1304,7 +1304,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
                     None
                 }
                 VtblEntry::Method(instance) => {
-                    Some(*instance).filter(|instance| should_codegen_locally(tcx, instance))
+                    Some(*instance).filter(|instance| should_codegen_locally(tcx, *instance))
                 }
             })
             .map(|item| create_fn_mono_item(tcx, item, source));
@@ -1321,7 +1321,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
         GlobalAlloc::Static(def_id) => {
             assert!(!tcx.is_thread_local_static(def_id));
             let instance = Instance::mono(tcx, def_id);
-            if should_codegen_locally(tcx, &instance) {
+            if should_codegen_locally(tcx, instance) {
                 trace!("collecting static {:?}", def_id);
                 output.push(dummy_spanned(MonoItem::Static(def_id)));
             }
@@ -1339,7 +1339,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
             }
         }
         GlobalAlloc::Function(fn_instance) => {
-            if should_codegen_locally(tcx, &fn_instance) {
+            if should_codegen_locally(tcx, fn_instance) {
                 trace!("collecting {:?} with {:#?}", alloc_id, fn_instance);
                 output.push(create_fn_mono_item(tcx, fn_instance, DUMMY_SP));
             }
@@ -1474,7 +1474,7 @@ fn visit_mentioned_item<'tcx>(
             if let ty::Closure(def_id, args) = *source_ty.kind() {
                 let instance =
                     Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce);
-                if should_codegen_locally(tcx, &instance) {
+                if should_codegen_locally(tcx, instance) {
                     output.push(create_fn_mono_item(tcx, instance, span));
                 }
             } else {
@@ -1736,7 +1736,7 @@ fn create_mono_items_for_default_impls<'tcx>(
         let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args);
 
         let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
-        if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) {
+        if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, instance) {
             output.push(mono_item);
         }
     }
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 4ec842e8f85..9c4a6e69a3c 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -64,7 +64,7 @@ pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
     !instance.def_id().is_local()
         && tcx.is_compiler_builtins(LOCAL_CRATE)
         && tcx.codegen_fn_attrs(instance.def_id()).link_name.is_none()
-        && !should_codegen_locally(tcx, &instance)
+        && !should_codegen_locally(tcx, instance)
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index aa735f3de1f..8957d7d1bd3 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -14,10 +14,6 @@ parse_array_index_offset_of = array indexing not supported in offset_of
 
 parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
 
-parse_assoc_lifetime = associated lifetimes are not supported
-    .label = the lifetime is given here
-    .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
-
 parse_associated_static_item_not_allowed = associated `static` items are not allowed
 
 parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
@@ -445,6 +441,12 @@ parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated wit
     .suggestion = remove the lifetime annotation
     .label = annotated with lifetime here
 
+parse_lifetime_in_eq_constraint = lifetimes are not permitted in this context
+    .label = lifetime is not allowed here
+    .context_label = this introduces an associated item binding
+    .help = if you meant to specify a trait object, write `dyn /* Trait */ + {$lifetime}`
+    .colon_sugg = you might have meant to write a bound here
+
 parse_lone_slash = invalid trailing slash in literal
     .label = {parse_lone_slash}
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 20ebfc6691b..a6eedabf689 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2631,13 +2631,22 @@ pub(crate) struct GenericsInPath {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_assoc_lifetime)]
+#[diag(parse_lifetime_in_eq_constraint)]
 #[help]
-pub(crate) struct AssocLifetime {
+pub(crate) struct LifetimeInEqConstraint {
     #[primary_span]
-    pub span: Span,
     #[label]
-    pub lifetime: Span,
+    pub span: Span,
+    pub lifetime: Ident,
+    #[label(parse_context_label)]
+    pub binding_label: Span,
+    #[suggestion(
+        parse_colon_sugg,
+        style = "verbose",
+        applicability = "maybe-incorrect",
+        code = ": "
+    )]
+    pub colon_sugg: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 9153f2b9d06..608cdd945ff 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -718,7 +718,11 @@ impl<'a> Parser<'a> {
                         let bounds = self.parse_generic_bounds()?;
                         AssocConstraintKind::Bound { bounds }
                     } else if self.eat(&token::Eq) {
-                        self.parse_assoc_equality_term(ident, self.prev_token.span)?
+                        self.parse_assoc_equality_term(
+                            ident,
+                            gen_args.as_ref(),
+                            self.prev_token.span,
+                        )?
                     } else {
                         unreachable!();
                     };
@@ -753,11 +757,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse the term to the right of an associated item equality constraint.
-    /// That is, parse `<term>` in `Item = <term>`.
-    /// Right now, this only admits types in `<term>`.
+    ///
+    /// That is, parse `$term` in `Item = $term` where `$term` is a type or
+    /// a const expression (wrapped in curly braces if complex).
     fn parse_assoc_equality_term(
         &mut self,
         ident: Ident,
+        gen_args: Option<&GenericArgs>,
         eq: Span,
     ) -> PResult<'a, AssocConstraintKind> {
         let arg = self.parse_generic_arg(None)?;
@@ -769,9 +775,15 @@ impl<'a> Parser<'a> {
                 c.into()
             }
             Some(GenericArg::Lifetime(lt)) => {
-                let guar =
-                    self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
-                self.mk_ty(span, ast::TyKind::Err(guar)).into()
+                let guar = self.dcx().emit_err(errors::LifetimeInEqConstraint {
+                    span: lt.ident.span,
+                    lifetime: lt.ident,
+                    binding_label: span,
+                    colon_sugg: gen_args
+                        .map_or(ident.span, |args| args.span())
+                        .between(lt.ident.span),
+                });
+                self.mk_ty(lt.ident.span, ast::TyKind::Err(guar)).into()
             }
             None => {
                 let after_eq = eq.shrink_to_hi();
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index c2e604b02b3..90f2bab65b1 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -1,9 +1,14 @@
-// Finds items that are externally reachable, to determine which items
-// need to have their metadata (and possibly their AST) serialized.
-// All items that can be referred to through an exported name are
-// reachable, and when a reachable thing is inline or generic, it
-// makes all other generics or inline functions that it references
-// reachable as well.
+//! Finds local items that are externally reachable, which means that other crates need access to
+//! their compiled machine code or their MIR.
+//!
+//! An item is "externally reachable" if it is relevant for other crates. This obviously includes
+//! all public items. However, some of these items cannot be compiled to machine code (because they
+//! are generic), and for some the machine code is not sufficient (because we want to cross-crate
+//! inline them). These items "need cross-crate MIR". When a reachable function `f` needs
+//! cross-crate MIR, then all the functions it calls also become reachable, as they will be
+//! necessary to use the MIR of `f` from another crate. Furthermore, an item can become "externally
+//! reachable" by having a `const`/`const fn` return a pointer to that item, so we also need to
+//! recurse into reachable `const`/`const fn`.
 
 use hir::def_id::LocalDefIdSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -21,7 +26,9 @@ use rustc_privacy::DefIdVisitor;
 use rustc_session::config::CrateType;
 use rustc_target::spec::abi::Abi;
 
-fn item_might_be_inlined(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+/// Determines whether this item is recursive for reachability. See `is_recursively_reachable_local`
+/// below for details.
+fn recursively_reachable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     tcx.generics_of(def_id).requires_monomorphization(tcx)
         || tcx.cross_crate_inlinable(def_id)
         || tcx.is_const_fn(def_id)
@@ -54,12 +61,20 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         let res = match expr.kind {
             hir::ExprKind::Path(ref qpath) => {
+                // This covers fn ptr casts but also "non-method" calls.
                 Some(self.typeck_results().qpath_res(qpath, expr.hir_id))
             }
-            hir::ExprKind::MethodCall(..) => self
-                .typeck_results()
-                .type_dependent_def(expr.hir_id)
-                .map(|(kind, def_id)| Res::Def(kind, def_id)),
+            hir::ExprKind::MethodCall(..) => {
+                // Method calls don't involve a full "path", so we need to determine the callee
+                // based on the receiver type.
+                // If this is a method call on a generic type, we might not be able to find the
+                // callee. That's why `reachable_set` also adds all potential callees for such
+                // calls, i.e. all trait impl items, to the reachable set. So here we only worry
+                // about the calls we can identify.
+                self.typeck_results()
+                    .type_dependent_def(expr.hir_id)
+                    .map(|(kind, def_id)| Res::Def(kind, def_id))
+            }
             hir::ExprKind::Closure(&hir::Closure { def_id, .. }) => {
                 self.reachable_symbols.insert(def_id);
                 None
@@ -96,16 +111,24 @@ impl<'tcx> ReachableContext<'tcx> {
             .expect("`ReachableContext::typeck_results` called outside of body")
     }
 
-    // Returns true if the given def ID represents a local item that is
-    // eligible for inlining and false otherwise.
-    fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
+    /// Returns true if the given def ID represents a local item that is recursive for reachability,
+    /// i.e. whether everything mentioned in here also needs to be considered reachable.
+    ///
+    /// There are two reasons why an item may be recursively reachable:
+    /// - It needs cross-crate MIR (see the module-level doc comment above).
+    /// - It is a `const` or `const fn`. This is *not* because we need the MIR to interpret them
+    ///   (MIR for const-eval and MIR for codegen is separate, and MIR for const-eval is always
+    ///   encoded). Instead, it is because `const fn` can create `fn()` pointers to other items
+    ///   which end up in the evaluated result of the constant and can then be called from other
+    ///   crates. Those items must be considered reachable.
+    fn is_recursively_reachable_local(&self, def_id: DefId) -> bool {
         let Some(def_id) = def_id.as_local() else {
             return false;
         };
 
         match self.tcx.hir_node_by_def_id(def_id) {
             Node::Item(item) => match item.kind {
-                hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()),
+                hir::ItemKind::Fn(..) => recursively_reachable(self.tcx, def_id.into()),
                 _ => false,
             },
             Node::TraitItem(trait_method) => match trait_method.kind {
@@ -117,7 +140,7 @@ impl<'tcx> ReachableContext<'tcx> {
             Node::ImplItem(impl_item) => match impl_item.kind {
                 hir::ImplItemKind::Const(..) => true,
                 hir::ImplItemKind::Fn(..) => {
-                    item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id())
+                    recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id())
                 }
                 hir::ImplItemKind::Type(_) => false,
             },
@@ -174,7 +197,7 @@ impl<'tcx> ReachableContext<'tcx> {
             Node::Item(item) => {
                 match item.kind {
                     hir::ItemKind::Fn(.., body) => {
-                        if item_might_be_inlined(self.tcx, item.owner_id.into()) {
+                        if recursively_reachable(self.tcx, item.owner_id.into()) {
                             self.visit_nested_body(body);
                         }
                     }
@@ -228,7 +251,7 @@ impl<'tcx> ReachableContext<'tcx> {
                     self.visit_nested_body(body);
                 }
                 hir::ImplItemKind::Fn(_, body) => {
-                    if item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) {
+                    if recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id()) {
                         self.visit_nested_body(body)
                     }
                 }
@@ -316,7 +339,7 @@ impl<'tcx> ReachableContext<'tcx> {
                 self.worklist.push(def_id);
             }
             _ => {
-                if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
+                if self.is_recursively_reachable_local(def_id.to_def_id()) {
                     self.worklist.push(def_id);
                 } else {
                     self.reachable_symbols.insert(def_id);
@@ -394,6 +417,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
         || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
 }
 
+/// See module-level doc comment above.
 fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
     let effective_visibilities = &tcx.effective_visibilities(());
 
@@ -427,14 +451,16 @@ fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
         }
     }
     {
-        // Some methods from non-exported (completely private) trait impls still have to be
-        // reachable if they are called from inlinable code. Generally, it's not known until
-        // monomorphization if a specific trait impl item can be reachable or not. So, we
-        // conservatively mark all of them as reachable.
+        // As explained above, we have to mark all functions called from reachable
+        // `item_might_be_inlined` items as reachable. The issue is, when those functions are
+        // generic and call a trait method, we have no idea where that call goes! So, we
+        // conservatively mark all trait impl items as reachable.
         // FIXME: One possible strategy for pruning the reachable set is to avoid marking impl
         // items of non-exported traits (or maybe all local traits?) unless their respective
         // trait items are used from inlinable code through method call syntax or UFCS, or their
         // trait is a lang item.
+        // (But if you implement this, don't forget to take into account that vtables can also
+        // make trait methods reachable!)
         let crate_items = tcx.hir_crate_items(());
 
         for id in crate_items.free_items() {
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 674a0984ae9..c3fc036aed3 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -9,13 +9,6 @@ use rustc_span::def_id::DefId;
 use rustc_span::def_id::DefIndex;
 use std::fmt::Debug;
 use std::hash::Hash;
-use std::marker::PhantomData;
-
-pub trait CacheSelector<'tcx, V> {
-    type Cache
-    where
-        V: Copy;
-}
 
 pub trait QueryCache: Sized {
     type Key: Hash + Eq + Copy + Debug;
@@ -29,14 +22,6 @@ pub trait QueryCache: Sized {
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex));
 }
 
-pub struct DefaultCacheSelector<K>(PhantomData<K>);
-
-impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector<K> {
-    type Cache = DefaultCache<K, V>
-    where
-        V: Copy;
-}
-
 pub struct DefaultCache<K, V> {
     cache: Sharded<FxHashMap<K, (V, DepNodeIndex)>>,
 }
@@ -81,14 +66,6 @@ where
     }
 }
 
-pub struct SingleCacheSelector;
-
-impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for SingleCacheSelector {
-    type Cache = SingleCache<V>
-    where
-        V: Copy;
-}
-
 pub struct SingleCache<V> {
     cache: OnceLock<(V, DepNodeIndex)>,
 }
@@ -123,14 +100,6 @@ where
     }
 }
 
-pub struct VecCacheSelector<K>(PhantomData<K>);
-
-impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
-    type Cache = VecCache<K, V>
-    where
-        V: Copy;
-}
-
 pub struct VecCache<K: Idx, V> {
     cache: Sharded<IndexVec<K, Option<(V, DepNodeIndex)>>>,
 }
@@ -174,14 +143,6 @@ where
     }
 }
 
-pub struct DefIdCacheSelector;
-
-impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for DefIdCacheSelector {
-    type Cache = DefIdCache<V>
-    where
-        V: Copy;
-}
-
 pub struct DefIdCache<V> {
     /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is
     /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap.
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 01b9d458f1e..91a0026f281 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -9,10 +9,7 @@ pub use self::job::{
 };
 
 mod caches;
-pub use self::caches::{
-    CacheSelector, DefIdCacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector,
-    VecCacheSelector,
-};
+pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
 
 mod config;
 pub use self::config::{HashResult, QueryConfig};
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 9bf3e9ccabd..48711f43518 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -19,6 +19,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
 use rustc_hir::def::{self, DefKind, PartialRes};
+use rustc_hir::def_id::DefId;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::metadata::Reexport;
 use rustc_middle::span_bug;
@@ -250,6 +251,9 @@ struct UnresolvedImportError {
     note: Option<String>,
     suggestion: Option<Suggestion>,
     candidates: Option<Vec<ImportSuggestion>>,
+    segment: Option<Symbol>,
+    /// comes from `PathRes::Failed { module }`
+    module: Option<DefId>,
 }
 
 // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
@@ -579,16 +583,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 &import.kind,
                 import.span,
             );
-            let err = UnresolvedImportError {
-                span: import.span,
-                label: None,
-                note: None,
-                suggestion: None,
-                candidates: None,
-            };
             // FIXME: there should be a better way of doing this than
             // formatting this as a string then checking for `::`
             if path.contains("::") {
+                let err = UnresolvedImportError {
+                    span: import.span,
+                    label: None,
+                    note: None,
+                    suggestion: None,
+                    candidates: None,
+                    segment: None,
+                    module: None,
+                };
                 errors.push((*import, err))
             }
         }
@@ -738,15 +744,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
             }
 
-            match &import.kind {
-                ImportKind::Single { source, .. } => {
-                    if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get()
-                        && let Some(module) = module.opt_def_id()
-                    {
-                        self.find_cfg_stripped(&mut diag, &source.name, module)
-                    }
-                }
-                _ => {}
+            if matches!(import.kind, ImportKind::Single { .. })
+                && let Some(segment) = err.segment
+                && let Some(module) = err.module
+            {
+                self.find_cfg_stripped(&mut diag, &segment, module)
             }
         }
 
@@ -916,10 +918,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 span,
                 label,
                 suggestion,
+                module,
+                segment_name,
                 ..
             } => {
                 if no_ambiguity {
                     assert!(import.imported_module.get().is_none());
+                    let module = if let Some(ModuleOrUniformRoot::Module(m)) = module {
+                        m.opt_def_id()
+                    } else {
+                        None
+                    };
                     let err = match self.make_path_suggestion(
                         span,
                         import.module_path.clone(),
@@ -935,6 +944,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 Applicability::MaybeIncorrect,
                             )),
                             candidates: None,
+                            segment: Some(segment_name),
+                            module,
                         },
                         None => UnresolvedImportError {
                             span,
@@ -942,6 +953,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             note: None,
                             suggestion,
                             candidates: None,
+                            segment: Some(segment_name),
+                            module,
                         },
                     };
                     return Some(err);
@@ -990,6 +1003,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 note: None,
                                 suggestion: None,
                                 candidates: None,
+                                segment: None,
+                                module: None,
                             });
                         }
                     }
@@ -1199,6 +1214,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     } else {
                         None
                     },
+                    module: import.imported_module.get().and_then(|module| {
+                        if let ModuleOrUniformRoot::Module(m) = module {
+                            m.opt_def_id()
+                        } else {
+                            None
+                        }
+                    }),
+                    segment: Some(ident.name),
                 })
             } else {
                 // `resolve_ident_in_module` reported a privacy error.
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index b2b339d2521..49b4a6efd3c 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2531,7 +2531,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             ItemKind::Delegation(ref delegation) => {
-                self.resolve_delegation(delegation);
+                let span = delegation.path.segments.last().unwrap().ident.span;
+                self.with_generic_param_rib(
+                    &[],
+                    RibKind::Item(HasGenericParams::Yes(span), def_kind),
+                    LifetimeRibKind::Generics {
+                        binder: item.id,
+                        kind: LifetimeBinderKind::Function,
+                        span,
+                    },
+                    |this| this.resolve_delegation(delegation),
+                );
             }
 
             ItemKind::ExternCrate(..) => {}
@@ -2819,7 +2829,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
                 }
                 AssocItemKind::Delegation(delegation) => {
-                    self.resolve_delegation(delegation);
+                    self.with_generic_param_rib(
+                        &[],
+                        RibKind::AssocItem,
+                        LifetimeRibKind::Generics {
+                            binder: item.id,
+                            kind: LifetimeBinderKind::Function,
+                            span: delegation.path.segments.last().unwrap().ident.span,
+                        },
+                        |this| this.resolve_delegation(delegation),
+                    );
                 }
                 AssocItemKind::Type(box TyAlias { generics, .. }) => self
                     .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
@@ -3069,16 +3088,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
             AssocItemKind::Delegation(box delegation) => {
                 debug!("resolve_implementation AssocItemKind::Delegation");
-                self.check_trait_item(
-                    item.id,
-                    item.ident,
-                    &item.kind,
-                    ValueNS,
-                    item.span,
-                    seen_trait_items,
-                    |i, s, c| MethodNotMemberOfTrait(i, s, c),
+                self.with_generic_param_rib(
+                    &[],
+                    RibKind::AssocItem,
+                    LifetimeRibKind::Generics {
+                        binder: item.id,
+                        kind: LifetimeBinderKind::Function,
+                        span: delegation.path.segments.last().unwrap().ident.span,
+                    },
+                    |this| {
+                        this.check_trait_item(
+                            item.id,
+                            item.ident,
+                            &item.kind,
+                            ValueNS,
+                            item.span,
+                            seen_trait_items,
+                            |i, s, c| MethodNotMemberOfTrait(i, s, c),
+                        );
+
+                        this.resolve_delegation(delegation)
+                    },
                 );
-                self.resolve_delegation(delegation);
             }
             AssocItemKind::MacCall(_) => {
                 panic!("unexpanded macro in resolve!")
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index dfc2d029d4c..aa03adb7097 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -415,6 +415,19 @@ enum PathResult<'a> {
         label: String,
         suggestion: Option<Suggestion>,
         is_error_from_last_segment: bool,
+        /// The final module being resolved, for instance:
+        ///
+        /// ```compile_fail
+        /// mod a {
+        ///     mod b {
+        ///         mod c {}
+        ///     }
+        /// }
+        ///
+        /// use a::not_exist::c;
+        /// ```
+        ///
+        /// In this case, `module` will point to `a`.
         module: Option<ModuleOrUniformRoot<'a>>,
         /// The segment name of target
         segment_name: Symbol,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 73fcd2a76df..891ddb7af5b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -674,6 +674,7 @@ symbols! {
         deref_mut,
         deref_mut_method,
         deref_patterns,
+        deref_pure,
         deref_target,
         derive,
         derive_const,
diff --git a/compiler/rustc_symbol_mangling/src/typeid.rs b/compiler/rustc_symbol_mangling/src/typeid.rs
index 3bf564a4a16..1d28d2b732f 100644
--- a/compiler/rustc_symbol_mangling/src/typeid.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid.rs
@@ -33,10 +33,10 @@ pub fn typeid_for_fnabi<'tcx>(
 /// Returns a type metadata identifier for the specified Instance.
 pub fn typeid_for_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
-    instance: &Instance<'tcx>,
+    instance: Instance<'tcx>,
     options: TypeIdOptions,
 ) -> String {
-    typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options)
+    typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options)
 }
 
 /// Returns a KCFI type metadata identifier for the specified FnAbi.
@@ -55,12 +55,12 @@ pub fn kcfi_typeid_for_fnabi<'tcx>(
 /// Returns a KCFI type metadata identifier for the specified Instance.
 pub fn kcfi_typeid_for_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
-    instance: &Instance<'tcx>,
+    instance: Instance<'tcx>,
     options: TypeIdOptions,
 ) -> u32 {
     // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
     // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
     let mut hash: XxHash64 = Default::default();
-    hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options).as_bytes());
+    hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes());
     hash.finish() as u32
 }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 3101015281b..1c6a0f9cf4d 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -1124,7 +1124,10 @@ pub fn typeid_for_instance<'tcx>(
             .trait_item_def_id
             .expect("Part of a trait implementation, but not linked to the def_id?");
         let trait_method = tcx.associated_item(method_id);
-        if traits::is_vtable_safe_method(tcx, trait_ref.skip_binder().def_id, trait_method) {
+        let trait_id = trait_ref.skip_binder().def_id;
+        if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
+            && tcx.object_safety_violations(trait_id).is_empty()
+        {
             // Trait methods will have a Self polymorphic parameter, where the concreteized
             // implementatation will not. We need to walk back to the more general trait method
             let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
@@ -1152,8 +1155,8 @@ pub fn typeid_for_instance<'tcx>(
 
     let fn_abi = tcx
         .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty())))
-        .unwrap_or_else(|instance| {
-            bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance)
+        .unwrap_or_else(|error| {
+            bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}")
         });
 
     typeid_for_fnabi(tcx, fn_abi, options)
@@ -1182,6 +1185,7 @@ fn strip_receiver_auto<'tcx>(
     tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
 }
 
+#[instrument(skip(tcx), ret)]
 fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> {
     assert!(!poly_trait_ref.has_non_region_param());
     let principal_pred = poly_trait_ref.map_bound(|trait_ref| {
@@ -1199,6 +1203,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
                             ty::ParamEnv::reveal_all(),
                             alias_ty.to_ty(tcx),
                         );
+                        debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx));
                         ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
                             def_id: assoc_ty.def_id,
                             args: ty::ExistentialTraitRef::erase_self_ty(tcx, super_trait_ref).args,
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index af1dfb6f7e9..65c3cf1a607 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -125,8 +125,12 @@ fn fn_sig_for_fn_abi<'tcx>(
                     coroutine_kind = ty::ClosureKind::FnOnce;
 
                     // Implementations of `FnMut` and `Fn` for coroutine-closures
-                    // still take their receiver by ref.
-                    if receiver_by_ref { Ty::new_mut_ptr(tcx, coroutine_ty) } else { coroutine_ty }
+                    // still take their receiver by (mut) ref.
+                    if receiver_by_ref {
+                        Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty)
+                    } else {
+                        coroutine_ty
+                    }
                 } else {
                     tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region)
                 };
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index cfaf533088a..7c3fa2312e5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -161,7 +161,7 @@ use core::marker::Unsize;
 use core::mem::{self, SizedTypeProperties};
 use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
 use core::ops::{
-    CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DispatchFromDyn, Receiver,
+    CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver,
 };
 use core::pin::Pin;
 use core::ptr::{self, addr_of_mut, NonNull, Unique};
@@ -1939,6 +1939,9 @@ impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
     }
 }
 
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized, A: Allocator> DerefPure for Box<T, A> {}
+
 #[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized, A: Allocator> Receiver for Box<T, A> {}
 
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 02d155aaf12..ebc30c08910 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -122,6 +122,7 @@
 #![feature(const_waker)]
 #![feature(core_intrinsics)]
 #![feature(deprecated_suggestion)]
+#![feature(deref_pure_trait)]
 #![feature(dispatch_from_dyn)]
 #![feature(error_generic_member_access)]
 #![feature(error_in_core)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index facfc9d208e..569db54b137 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -260,7 +260,7 @@ use core::marker::{PhantomData, Unsize};
 #[cfg(not(no_global_oom_handling))]
 use core::mem::size_of_val;
 use core::mem::{self, align_of_val_raw, forget, ManuallyDrop};
-use core::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
+use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
 #[cfg(not(no_global_oom_handling))]
 use core::pin::Pin;
@@ -2126,6 +2126,9 @@ impl<T: ?Sized, A: Allocator> Deref for Rc<T, A> {
     }
 }
 
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
+
 #[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for Rc<T> {}
 
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index c4dcff1b1c4..7464df268cc 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -260,7 +260,7 @@ use crate::vec::Vec;
 /// # Representation
 ///
 /// A `String` is made up of three components: a pointer to some bytes, a
-/// length, and a capacity. The pointer points to an internal buffer `String`
+/// length, and a capacity. The pointer points to the internal buffer which `String`
 /// uses to store its data. The length is the number of bytes currently stored
 /// in the buffer, and the capacity is the size of the buffer in bytes. As such,
 /// the length will always be less than or equal to the capacity.
@@ -2479,6 +2479,9 @@ impl ops::Deref for String {
     }
 }
 
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl ops::DerefPure for String {}
+
 #[stable(feature = "derefmut_for_string", since = "1.3.0")]
 impl ops::DerefMut for String {
     #[inline]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 7e3e2fb38b1..4dea27221b7 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -21,7 +21,7 @@ use core::marker::{PhantomData, Unsize};
 #[cfg(not(no_global_oom_handling))]
 use core::mem::size_of_val;
 use core::mem::{self, align_of_val_raw};
-use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
+use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
@@ -2107,6 +2107,9 @@ impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> {
     }
 }
 
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
+
 #[unstable(feature = "receiver_trait", issue = "none")]
 impl<T: ?Sized> Receiver for Arc<T> {}
 
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 94bed825bb2..3062f8664b7 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2772,6 +2772,9 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
     }
 }
 
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T, A: Allocator> ops::DerefPure for Vec<T, A> {}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml
index 3dc8c84e0bf..a02fcf50416 100644
--- a/library/core/Cargo.toml
+++ b/library/core/Cargo.toml
@@ -7,7 +7,8 @@ description = "The Rust Core Library"
 autotests = false
 autobenches = false
 # If you update this, be sure to update it in a bunch of other places too!
-# As of 2022, it was the ci/pgo.sh script and the core-no-fp-fmt-parse test.
+# As of 2024, it was src/tools/opt-dist, the core-no-fp-fmt-parse test and
+# the version of the prelude imported in core/lib.rs.
 edition = "2021"
 
 [lib]
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs
index bdb6599abf5..bb668d2a673 100644
--- a/library/core/src/array/equality.rs
+++ b/library/core/src/array/equality.rs
@@ -1,5 +1,4 @@
 use crate::cmp::BytewiseEq;
-use crate::convert::TryInto;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, U, const N: usize> PartialEq<[U; N]> for [T; N]
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 8b5b48c59c2..2a447aafe72 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -6,7 +6,7 @@
 
 use crate::borrow::{Borrow, BorrowMut};
 use crate::cmp::Ordering;
-use crate::convert::{Infallible, TryFrom};
+use crate::convert::Infallible;
 use crate::error::Error;
 use crate::fmt;
 use crate::hash::{self, Hash};
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index 8f612929110..f0c2636307f 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -1,7 +1,6 @@
 //! Character conversions.
 
 use crate::char::TryFromCharError;
-use crate::convert::TryFrom;
 use crate::error::Error;
 use crate::fmt;
 use crate::mem::transmute;
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 46a9006c146..0167d04c413 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -1,4 +1,3 @@
-use super::TryFrom;
 use crate::num::TryFromIntError;
 
 mod private {
@@ -323,7 +322,6 @@ impl_try_from_lower_bounded!(isize => usize);
 #[cfg(target_pointer_width = "16")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use crate::convert::TryFrom;
 
     impl_try_from_upper_bounded!(usize => u8);
     impl_try_from_unbounded!(usize => u16, u32, u64, u128);
@@ -346,7 +344,6 @@ mod ptr_try_from_impls {
 #[cfg(target_pointer_width = "32")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use crate::convert::TryFrom;
 
     impl_try_from_upper_bounded!(usize => u8, u16);
     impl_try_from_unbounded!(usize => u32, u64, u128);
@@ -372,7 +369,6 @@ mod ptr_try_from_impls {
 #[cfg(target_pointer_width = "64")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use crate::convert::TryFrom;
 
     impl_try_from_upper_bounded!(usize => u8, u16, u32);
     impl_try_from_unbounded!(usize => u64, u128);
diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs
index 54ed4c952fb..b8b96417d13 100644
--- a/library/core/src/iter/adapters/step_by.rs
+++ b/library/core/src/iter/adapters/step_by.rs
@@ -1,4 +1,3 @@
-use crate::convert::TryFrom;
 use crate::{
     intrinsics,
     iter::{from_fn, TrustedLen, TrustedRandomAccess},
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 055ead117ea..5eea764b28a 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,5 +1,4 @@
 use crate::ascii::Char as AsciiChar;
-use crate::convert::TryFrom;
 use crate::mem;
 use crate::net::{Ipv4Addr, Ipv6Addr};
 use crate::num::NonZero;
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index e1904ed220c..d2c9e1554b4 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -8,11 +8,11 @@ use super::super::ByRefSized;
 use super::super::TrustedRandomAccessNoCoerce;
 use super::super::{ArrayChunks, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
 use super::super::{FlatMap, Flatten};
-use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip};
 use super::super::{
     Inspect, Map, MapWhile, MapWindows, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take,
     TakeWhile,
 };
+use super::super::{Intersperse, IntersperseWith, Product, Sum, Zip};
 
 fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index f0448a98981..3bc1a87f848 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -270,6 +270,7 @@
 #![feature(arm_target_feature)]
 #![feature(avx512_target_feature)]
 #![feature(hexagon_target_feature)]
+#![feature(loongarch_target_feature)]
 #![feature(mips_target_feature)]
 #![feature(powerpc_target_feature)]
 #![feature(riscv_target_feature)]
@@ -285,7 +286,7 @@ extern crate self as core;
 
 #[prelude_import]
 #[allow(unused)]
-use prelude::v1::*;
+use prelude::rust_2021::*;
 
 #[cfg(not(test))] // See #65860
 #[macro_use]
diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs
index 835ab9d73af..deea8212448 100644
--- a/library/core/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -3,7 +3,6 @@
 //! This module is "publicly exported" through the `FromStr` implementations
 //! below.
 
-use crate::convert::{TryFrom, TryInto};
 use crate::error::Error;
 use crate::fmt;
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 2c7845d4304..3795a81c2c1 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -275,6 +275,25 @@ impl<T: ?Sized> DerefMut for &mut T {
     }
 }
 
+/// Perma-unstable marker trait. Indicates that the type has a well-behaved [`Deref`]
+/// (and, if applicable, [`DerefMut`]) implementation. This is relied on for soundness
+/// of deref patterns.
+///
+/// FIXME(deref_patterns): The precise semantics are undecided; the rough idea is that
+/// successive calls to `deref`/`deref_mut` without intermediate mutation should be
+/// idempotent, in the sense that they return the same value as far as pattern-matching
+/// is concerned. Calls to `deref`/`deref_mut`` must leave the pointer itself likewise
+/// unchanged.
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+#[cfg_attr(not(bootstrap), lang = "deref_pure")]
+pub unsafe trait DerefPure {}
+
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized> DerefPure for &T {}
+
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized> DerefPure for &mut T {}
+
 /// Indicates that a struct can be used as a method receiver, without the
 /// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
 /// `Rc<T>`, `&T`, and `Pin<P>`.
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 4289a86f89b..ac808bec50e 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -165,6 +165,9 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::deref::{Deref, DerefMut};
 
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+pub use self::deref::DerefPure;
+
 #[unstable(feature = "receiver_trait", issue = "none")]
 pub use self::deref::Receiver;
 
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 0083d15efae..631e1654ce0 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -553,7 +553,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
+use crate::iter::{self, FusedIterator, TrustedLen};
 use crate::panicking::{panic, panic_str};
 use crate::pin::Pin;
 use crate::{
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index bc84fb5ccb0..68fce3960c7 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -1,4 +1,3 @@
-use crate::convert::{TryFrom, TryInto};
 use crate::num::NonZero;
 #[cfg(debug_assertions)]
 use crate::ub_checks::assert_unsafe_precondition;
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 6879ac03f70..b2b627fe6a9 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -488,7 +488,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
+use crate::iter::{self, FusedIterator, TrustedLen};
 use crate::ops::{self, ControlFlow, Deref, DerefMut};
 use crate::{convert, fmt, hint};
 
diff --git a/library/core/src/unit.rs b/library/core/src/unit.rs
index 6656dd5c40b..d656005f3d4 100644
--- a/library/core/src/unit.rs
+++ b/library/core/src/unit.rs
@@ -1,5 +1,3 @@
-use crate::iter::FromIterator;
-
 /// Collapses all unit items from an iterator into one.
 ///
 /// This is more useful when combined with higher-level abstractions, like
diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs
index 7a161b7e01d..48514e52587 100644
--- a/library/portable-simd/crates/core_simd/src/lib.rs
+++ b/library/portable-simd/crates/core_simd/src/lib.rs
@@ -45,10 +45,6 @@
 #![unstable(feature = "portable_simd", issue = "86656")]
 //! Portable SIMD module.
 
-#[prelude_import]
-#[allow(unused_imports)]
-use core::prelude::v1::*;
-
 #[path = "mod.rs"]
 mod core_simd;
 pub use self::core_simd::simd;
diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs
index 6c8205b112c..8dbdfc0e1fe 100644
--- a/library/portable-simd/crates/core_simd/src/vector.rs
+++ b/library/portable-simd/crates/core_simd/src/vector.rs
@@ -4,7 +4,6 @@ use crate::simd::{
     ptr::{SimdConstPtr, SimdMutPtr},
     LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle,
 };
-use core::convert::{TryFrom, TryInto};
 
 /// A SIMD vector with the shape of `[T; N]` but the operations of `T`.
 ///
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index 8a1ba436f72..f3cfc41bac7 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -2,6 +2,7 @@
 
 use super::*;
 
+use std::cell::RefCell;
 use std::marker::PhantomData;
 use std::sync::atomic::AtomicU32;
 
@@ -189,61 +190,61 @@ struct Bridge<'a> {
 impl<'a> !Send for Bridge<'a> {}
 impl<'a> !Sync for Bridge<'a> {}
 
-enum BridgeState<'a> {
-    /// No server is currently connected to this client.
-    NotConnected,
+#[allow(unsafe_code)]
+mod state {
+    use super::Bridge;
+    use std::cell::{Cell, RefCell};
+    use std::ptr;
 
-    /// A server is connected and available for requests.
-    Connected(Bridge<'a>),
-
-    /// Access to the bridge is being exclusively acquired
-    /// (e.g., during `BridgeState::with`).
-    InUse,
-}
+    thread_local! {
+        static BRIDGE_STATE: Cell<*const ()> = const { Cell::new(ptr::null()) };
+    }
 
-enum BridgeStateL {}
+    pub(super) fn set<'bridge, R>(state: &RefCell<Bridge<'bridge>>, f: impl FnOnce() -> R) -> R {
+        struct RestoreOnDrop(*const ());
+        impl Drop for RestoreOnDrop {
+            fn drop(&mut self) {
+                BRIDGE_STATE.set(self.0);
+            }
+        }
 
-impl<'a> scoped_cell::ApplyL<'a> for BridgeStateL {
-    type Out = BridgeState<'a>;
-}
+        let inner = ptr::from_ref(state).cast();
+        let outer = BRIDGE_STATE.replace(inner);
+        let _restore = RestoreOnDrop(outer);
 
-thread_local! {
-    static BRIDGE_STATE: scoped_cell::ScopedCell<BridgeStateL> =
-        const { scoped_cell::ScopedCell::new(BridgeState::NotConnected) };
-}
+        f()
+    }
 
-impl BridgeState<'_> {
-    /// Take exclusive control of the thread-local
-    /// `BridgeState`, and pass it to `f`, mutably.
-    /// The state will be restored after `f` exits, even
-    /// by panic, including modifications made to it by `f`.
-    ///
-    /// N.B., while `f` is running, the thread-local state
-    /// is `BridgeState::InUse`.
-    fn with<R>(f: impl FnOnce(&mut BridgeState<'_>) -> R) -> R {
-        BRIDGE_STATE.with(|state| state.replace(BridgeState::InUse, f))
+    pub(super) fn with<R>(
+        f: impl for<'bridge> FnOnce(Option<&RefCell<Bridge<'bridge>>>) -> R,
+    ) -> R {
+        let state = BRIDGE_STATE.get();
+        // SAFETY: the only place where the pointer is set is in `set`. It puts
+        // back the previous value after the inner call has returned, so we know
+        // that as long as the pointer is not null, it came from a reference to
+        // a `RefCell<Bridge>` that outlasts the call to this function. Since `f`
+        // works the same for any lifetime of the bridge, including the actual
+        // one, we can lie here and say that the lifetime is `'static` without
+        // anyone noticing.
+        let bridge = unsafe { state.cast::<RefCell<Bridge<'static>>>().as_ref() };
+        f(bridge)
     }
 }
 
 impl Bridge<'_> {
     fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
-        BridgeState::with(|state| match state {
-            BridgeState::NotConnected => {
-                panic!("procedural macro API is used outside of a procedural macro");
-            }
-            BridgeState::InUse => {
-                panic!("procedural macro API is used while it's already in use");
-            }
-            BridgeState::Connected(bridge) => f(bridge),
+        state::with(|state| {
+            let bridge = state.expect("procedural macro API is used outside of a procedural macro");
+            let mut bridge = bridge
+                .try_borrow_mut()
+                .expect("procedural macro API is used while it's already in use");
+            f(&mut bridge)
         })
     }
 }
 
 pub(crate) fn is_available() -> bool {
-    BridgeState::with(|state| match state {
-        BridgeState::Connected(_) | BridgeState::InUse => true,
-        BridgeState::NotConnected => false,
-    })
+    state::with(|s| s.is_some())
 }
 
 /// A client-side RPC entry-point, which may be using a different `proc_macro`
@@ -282,11 +283,7 @@ fn maybe_install_panic_hook(force_show_panics: bool) {
     HIDE_PANICS_DURING_EXPANSION.call_once(|| {
         let prev = panic::take_hook();
         panic::set_hook(Box::new(move |info| {
-            let show = BridgeState::with(|state| match state {
-                BridgeState::NotConnected => true,
-                BridgeState::Connected(_) | BridgeState::InUse => force_show_panics,
-            });
-            if show {
+            if force_show_panics || !is_available() {
                 prev(info)
             }
         }));
@@ -312,29 +309,24 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
         let (globals, input) = <(ExpnGlobals<Span>, A)>::decode(reader, &mut ());
 
         // Put the buffer we used for input back in the `Bridge` for requests.
-        let new_state =
-            BridgeState::Connected(Bridge { cached_buffer: buf.take(), dispatch, globals });
-
-        BRIDGE_STATE.with(|state| {
-            state.set(new_state, || {
-                let output = f(input);
-
-                // Take the `cached_buffer` back out, for the output value.
-                buf = Bridge::with(|bridge| bridge.cached_buffer.take());
-
-                // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
-                // from encoding a panic (`Err(e: PanicMessage)`) to avoid
-                // having handles outside the `bridge.enter(|| ...)` scope, and
-                // to catch panics that could happen while encoding the success.
-                //
-                // Note that panics should be impossible beyond this point, but
-                // this is defensively trying to avoid any accidental panicking
-                // reaching the `extern "C"` (which should `abort` but might not
-                // at the moment, so this is also potentially preventing UB).
-                buf.clear();
-                Ok::<_, ()>(output).encode(&mut buf, &mut ());
-            })
-        })
+        let state = RefCell::new(Bridge { cached_buffer: buf.take(), dispatch, globals });
+
+        let output = state::set(&state, || f(input));
+
+        // Take the `cached_buffer` back out, for the output value.
+        buf = RefCell::into_inner(state).cached_buffer;
+
+        // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
+        // from encoding a panic (`Err(e: PanicMessage)`) to avoid
+        // having handles outside the `bridge.enter(|| ...)` scope, and
+        // to catch panics that could happen while encoding the success.
+        //
+        // Note that panics should be impossible beyond this point, but
+        // this is defensively trying to avoid any accidental panicking
+        // reaching the `extern "C"` (which should `abort` but might not
+        // at the moment, so this is also potentially preventing UB).
+        buf.clear();
+        Ok::<_, ()>(output).encode(&mut buf, &mut ());
     }))
     .map_err(PanicMessage::from)
     .unwrap_or_else(|e| {
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 67c72cf98d4..8553e8d5e4f 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -154,7 +154,7 @@ macro_rules! reverse_decode {
 mod arena;
 #[allow(unsafe_code)]
 mod buffer;
-#[forbid(unsafe_code)]
+#[deny(unsafe_code)]
 pub mod client;
 #[allow(unsafe_code)]
 mod closure;
@@ -166,8 +166,6 @@ mod handle;
 #[forbid(unsafe_code)]
 mod rpc;
 #[allow(unsafe_code)]
-mod scoped_cell;
-#[allow(unsafe_code)]
 mod selfless_reify;
 #[forbid(unsafe_code)]
 pub mod server;
diff --git a/library/proc_macro/src/bridge/scoped_cell.rs b/library/proc_macro/src/bridge/scoped_cell.rs
deleted file mode 100644
index a8b34143908..00000000000
--- a/library/proc_macro/src/bridge/scoped_cell.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-//! `Cell` variant for (scoped) existential lifetimes.
-
-use std::cell::Cell;
-use std::mem;
-
-/// Type lambda application, with a lifetime.
-#[allow(unused_lifetimes)]
-pub trait ApplyL<'a> {
-    type Out;
-}
-
-/// Type lambda taking a lifetime, i.e., `Lifetime -> Type`.
-pub trait LambdaL: for<'a> ApplyL<'a> {}
-
-impl<T: for<'a> ApplyL<'a>> LambdaL for T {}
-
-pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>);
-
-impl<T: LambdaL> ScopedCell<T> {
-    pub const fn new(value: <T as ApplyL<'static>>::Out) -> Self {
-        ScopedCell(Cell::new(value))
-    }
-
-    /// Sets the value in `self` to `replacement` while
-    /// running `f`, which gets the old value, mutably.
-    /// The old value will be restored after `f` exits, even
-    /// by panic, including modifications made to it by `f`.
-    #[rustc_confusables("swap")]
-    pub fn replace<'a, R>(
-        &self,
-        replacement: <T as ApplyL<'a>>::Out,
-        f: impl for<'b, 'c> FnOnce(&'b mut <T as ApplyL<'c>>::Out) -> R,
-    ) -> R {
-        /// Wrapper that ensures that the cell always gets filled
-        /// (with the original state, optionally changed by `f`),
-        /// even if `f` had panicked.
-        struct PutBackOnDrop<'a, T: LambdaL> {
-            cell: &'a ScopedCell<T>,
-            value: Option<<T as ApplyL<'static>>::Out>,
-        }
-
-        impl<'a, T: LambdaL> Drop for PutBackOnDrop<'a, T> {
-            fn drop(&mut self) {
-                self.cell.0.set(self.value.take().unwrap());
-            }
-        }
-
-        let mut put_back_on_drop = PutBackOnDrop {
-            cell: self,
-            value: Some(self.0.replace(unsafe {
-                let erased = mem::transmute_copy(&replacement);
-                mem::forget(replacement);
-                erased
-            })),
-        };
-
-        f(put_back_on_drop.value.as_mut().unwrap())
-    }
-
-    /// Sets the value in `self` to `value` while running `f`.
-    pub fn set<R>(&self, value: <T as ApplyL<'_>>::Out, f: impl FnOnce() -> R) -> R {
-        self.replace(value, |_| f())
-    }
-}
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 5d0de2d06a0..8b3a9e82aad 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -97,7 +97,7 @@ use crate::time::SystemTime;
 /// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).
 ///
 /// [`BufReader`]: io::BufReader
-/// [`BufWriter`]: io::BufReader
+/// [`BufWriter`]: io::BufWriter
 /// [`sync_all`]: File::sync_all
 /// [`write`]: File::write
 /// [`read`]: File::read
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index b968f8df34c..99b6da60c14 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -517,7 +517,7 @@ impl FileAttr {
 
     #[cfg(any(target_os = "horizon", target_os = "hurd"))]
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.stat.st_mtim))
+        SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64)
     }
 
     #[cfg(not(any(
@@ -545,7 +545,7 @@ impl FileAttr {
 
     #[cfg(any(target_os = "horizon", target_os = "hurd"))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.stat.st_atim))
+        SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64)
     }
 
     #[cfg(any(
diff --git a/library/stdarch b/library/stdarch
-Subproject 56087ea170d878a7a57b3a5725e0c00f5f5cad7
+Subproject 967e7afd87cbea3232581a4a55031134ab88f59
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 012d64e5344..d9c7032d0db 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1003,6 +1003,7 @@ impl Step for PlainSourceTarball {
             // Vendor all Cargo dependencies
             let mut cmd = Command::new(&builder.initial_cargo);
             cmd.arg("vendor")
+                .arg("--versioned-dirs")
                 .arg("--sync")
                 .arg(builder.src.join("./src/tools/cargo/Cargo.toml"))
                 .arg("--sync")
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index f22a9ca604e..026c6907999 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -680,9 +680,13 @@ impl Step for Miri {
             .arg("--manifest-path")
             .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
         cargo.arg("--target").arg(target.rustc_target_arg());
-        cargo.arg("--tests"); // don't run doctests, they are too confused by the staging
         cargo.arg("--").args(builder.config.test_args());
 
+        // `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "run", not a "test".
+        // Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage.
+        // So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER).
+        cargo.env("RUSTDOC", builder.rustdoc(compiler_std));
+
         // Tell `cargo miri` where to find things.
         cargo.env("MIRI_SYSROOT", &miri_sysroot);
         cargo.env("MIRI_HOST_SYSROOT", sysroot);
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject e1eead1181a691e56299294d5f1d62fe7a26d31
+Subproject 98b33e9a441457b0a491fe1be90e7de64eafc3e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 5afb503a4c1ea3c84370f8f4c08a1cddd1cdf6a
+Subproject 984b36eca4b9293df04d5ba4eb5c4f77db0f51d
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject e093099709456e6fd74fecd2505fdf49a2471c1
+Subproject 7601e0c5ad29d5bd3b518700ea63fddfff5915a
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 8a5d647f19b08998612146b1cb2ca47083db63e
+Subproject ffa246b7fd95a96e1cd54883e613aed42c32547
diff --git a/src/doc/unstable-book/src/language-features/adt-const-params.md b/src/doc/unstable-book/src/language-features/adt-const-params.md
new file mode 100644
index 00000000000..208bf5e4c15
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/adt-const-params.md
@@ -0,0 +1,35 @@
+# `adt_const_params`
+
+The tracking issue for this feature is: [#95174]
+
+[#95174]: https://github.com/rust-lang/rust/issues/95174
+
+------------------------
+
+Allows for using more complex types for const parameters, such as structs or enums.
+
+```rust
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::marker::ConstParamTy;
+
+#[derive(ConstParamTy, PartialEq, Eq)]
+enum Foo {
+    A,
+    B,
+    C,
+}
+
+#[derive(ConstParamTy, PartialEq, Eq)]
+struct Bar {
+    flag: bool,
+}
+
+fn is_foo_a_and_bar_true<const F: Foo, const B: Bar>() -> bool {
+    match (F, B.flag) {
+        (Foo::A, true) => true,
+        _ => false,
+    }
+}
+```
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject d438c80c45c24be676ef5867edc79d0a14910ef
+Subproject 499a61ce7a0fc6a72040084862a68b2603e770e
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 07fbb1cb5c9..981a76d683d 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -83,7 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                 LitFloatType::Unsuffixed => None,
             };
             let (is_whole, is_inf, mut float_str) = match fty {
-                FloatTy::F16 => unimplemented!("f16_f128"),
+                FloatTy::F16 => {
+                    // FIXME(f16_f128): do a check like the others when parsing is available
+                    return;
+                },
                 FloatTy::F32 => {
                     let value = sym_str.parse::<f32>().unwrap();
 
@@ -94,7 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
 
                     (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
                 },
-                FloatTy::F128 => unimplemented!("f16_f128"),
+                FloatTy::F128 => {
+                    // FIXME(f16_f128): do a check like the others when parsing is available
+                    return;
+                },
             };
 
             if is_inf {
@@ -139,10 +145,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
 #[must_use]
 fn max_digits(fty: FloatTy) -> u32 {
     match fty {
-        FloatTy::F16 => unimplemented!("f16_f128"),
+        // FIXME(f16_f128): replace the magic numbers once `{f16,f128}::DIGITS` are available
+        FloatTy::F16 => 3,
         FloatTy::F32 => f32::DIGITS,
         FloatTy::F64 => f64::DIGITS,
-        FloatTy::F128 => unimplemented!("f16_f128"),
+        FloatTy::F128 => 33,
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index bc5dd10cad0..e58d4776427 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -12,7 +12,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
-use rustc_hir_typeck::{FnCtxt, Inherited};
+use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::Mutability;
@@ -438,8 +438,8 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Item(item) => {
                 if let ItemKind::Fn(_, _, body_id) = &item.kind
                     && let output_ty = return_ty(cx, item.owner_id)
-                    && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id)
-                    && let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_id)
+                    && let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id)
+                    && let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id)
                     && fn_ctxt.can_coerce(ty, output_ty)
                 {
                     if has_lifetime(output_ty) && has_lifetime(ty) {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index 7a7bb9f9c94..15f1890aa39 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -1,6 +1,6 @@
 use rustc_hir as hir;
 use rustc_hir::Expr;
-use rustc_hir_typeck::{cast, FnCtxt, Inherited};
+use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt};
 use rustc_lint::LateContext;
 use rustc_middle::ty::cast::CastKind;
 use rustc_middle::ty::Ty;
@@ -34,8 +34,8 @@ pub(super) fn check_cast<'tcx>(
     let hir_id = e.hir_id;
     let local_def_id = hir_id.owner.def_id;
 
-    let inherited = Inherited::new(cx.tcx, local_def_id);
-    let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id);
+    let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id);
+    let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id);
 
     if let Ok(check) = cast::CastCheck::new(
         &fn_ctxt,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 6ff47dbffbc..00fe1208c2f 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -708,6 +708,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "check-run-results",
     "check-stdout",
     "check-test-line-numbers-match",
+    "compare-output-lines-by-subset",
     "compile-flags",
     "dont-check-compiler-stderr",
     "dont-check-compiler-stdout",
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 1097fc6db72..2c5868d5b37 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -30,11 +30,16 @@ jobs:
             host_target: i686-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     env:
-      RUST_BACKTRACE: 1
       HOST_TARGET: ${{ matrix.host_target }}
     steps:
       - uses: actions/checkout@v3
 
+      - name: Show Rust version (stable toolchain)
+        run: |
+          rustup show
+          rustc -Vv
+          cargo -V
+
       # Cache the global cargo directory, but NOT the local `target` directory which
       # we cannot reuse anyway when the nightly changes (and it grows quite large
       # over time).
@@ -58,7 +63,7 @@ jobs:
         if: ${{ steps.cache.outputs.cache-hit != 'true' }}
         run: cargo install -f rustup-toolchain-install-master
 
-      - name: Install "master" toolchain
+      - name: Install miri toolchain
         run: |
           if [[ ${{ github.event_name }} == 'schedule' ]]; then
             echo "Building against latest rustc git version"
@@ -66,13 +71,13 @@ jobs:
           fi
           ./miri toolchain --host ${{ matrix.host_target }}
 
-      - name: Show Rust version
+      - name: Show Rust version (miri toolchain)
         run: |
           rustup show
           rustc -Vv
           cargo -V
 
-      - name: Test
+      - name: Test Miri
         run: ./ci/ci.sh
 
   style:
diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md
index f2f3a642e0a..3416fb0d9ba 100644
--- a/src/tools/miri/CONTRIBUTING.md
+++ b/src/tools/miri/CONTRIBUTING.md
@@ -64,19 +64,22 @@ For example, you can (cross-)run the driver on a particular file by doing
 ./miri run tests/pass/hello.rs --target i686-unknown-linux-gnu
 ```
 
-and you can (cross-)run the entire test suite using:
+Tests in ``pass-dep`` need to be run using ``./miri run --dep <filename>``.  
+For example:
+```sh
+./miri run --dep tests/pass-dep/shims/libc-fs.rs
+```
+
+You can (cross-)run the entire test suite using:
 
 ```
 ./miri test
 MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test
 ```
 
-If your target doesn't support libstd that should usually just work. However, if you are using a
-custom target file, you might have to set `MIRI_NO_STD=1`.
-
 `./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the
 base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed
-to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`.
+to `cargo test`, so for multiple filters you need to use `./miri test -- FILTER1 FILTER2`.
 
 #### Fine grained logging
 
@@ -178,6 +181,7 @@ to `.vscode/settings.json` in your local Miri clone:
         "cargo",
         "clippy", // make this `check` when working with a locally built rustc
         "--message-format=json",
+        "--all-targets",
     ],
     // Contrary to what the name suggests, this also affects proc macros.
     "rust-analyzer.cargo.buildScripts.overrideCommand": [
@@ -187,6 +191,7 @@ to `.vscode/settings.json` in your local Miri clone:
         "cargo",
         "check",
         "--message-format=json",
+        "--all-targets",
     ],
 }
 ```
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index b043805291e..26e55b89708 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -505,6 +505,8 @@ binaries, and as such worth documenting:
 * `MIRI_LOCAL_CRATES` is set by `cargo-miri` to tell the Miri driver which
   crates should be given special treatment in diagnostics, in addition to the
   crate currently being compiled.
+* `MIRI_ORIG_RUSTDOC` is set and read by different phases of `cargo-miri` to remember the
+  value of `RUSTDOC` from before it was overwritten.
 * `MIRI_VERBOSE` when set to any value tells the various `cargo-miri` phases to
   perform verbose logging.
 * `MIRI_HOST_SYSROOT` is set by bootstrap to tell `cargo-miri` which sysroot to use for *host*
diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs
index c5fada6fe55..9fdd4c3e470 100644
--- a/src/tools/miri/cargo-miri/src/main.rs
+++ b/src/tools/miri/cargo-miri/src/main.rs
@@ -11,10 +11,18 @@ use std::{env, iter};
 
 use crate::phases::*;
 
+/// Returns `true` if our flags look like they may be for rustdoc, i.e., this is cargo calling us to
+/// be rustdoc. It's hard to be sure as cargo does not have a RUSTDOC_WRAPPER or an env var that
+/// would let us get a clear signal.
+fn looks_like_rustdoc() -> bool {
+    // The `--test-run-directory` flag only exists for rustdoc and cargo always passes it. Perfect!
+    env::args().any(|arg| arg == "--test-run-directory")
+}
+
 fn main() {
     // Rustc does not support non-UTF-8 arguments so we make no attempt either.
     // (We do support non-UTF-8 environment variables though.)
-    let mut args = std::env::args();
+    let mut args = env::args();
     // Skip binary name.
     args.next().unwrap();
 
@@ -91,10 +99,16 @@ fn main() {
             // (see https://github.com/rust-lang/cargo/issues/10886).
             phase_rustc(args, RustcPhase::Build)
         }
-        _ => {
-            // Everything else must be rustdoc. But we need to get `first` "back onto the iterator",
+        _ if looks_like_rustdoc() => {
+            // This is probably rustdoc. But we need to get `first` "back onto the iterator",
             // it is some part of the rustdoc invocation.
             phase_rustdoc(iter::once(first).chain(args));
         }
+        _ => {
+            show_error!(
+                "`cargo-miri` failed to recognize which phase of the build process this is, please report a bug.\nThe command-line arguments were: {:#?}",
+                Vec::from_iter(env::args()),
+            );
+        }
     }
 }
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index 81ff68545cc..8c0f605fd6e 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -202,6 +202,9 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases!
 
     // Set rustdoc to us as well, so we can run doctests.
+    if let Some(orig_rustdoc) = env::var_os("RUSTDOC") {
+        cmd.env("MIRI_ORIG_RUSTDOC", orig_rustdoc);
+    }
     cmd.env("RUSTDOC", &cargo_miri_path);
 
     cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata));
@@ -581,9 +584,10 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
     let verbose = std::env::var("MIRI_VERBOSE")
         .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
 
-    // phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here;
-    // just default to a straight-forward invocation for now:
-    let mut cmd = Command::new("rustdoc");
+    // phase_cargo_miri sets the RUSTDOC env var to ourselves, and puts a backup
+    // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now.
+    let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string());
+    let mut cmd = Command::new(rustdoc);
 
     let extern_flag = "--extern";
     let runtool_flag = "--runtool";
@@ -620,7 +624,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
 
     // The `--test-builder` and `--runtool` arguments are unstable rustdoc features,
     // which are disabled by default. We first need to enable them explicitly:
-    cmd.arg("-Z").arg("unstable-options");
+    cmd.arg("-Zunstable-options");
 
     // rustdoc needs to know the right sysroot.
     cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index 9d2c3f362e6..54c5d3087fd 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -13,6 +13,15 @@ function endgroup {
 
 begingroup "Building Miri"
 
+# Special Windows hacks
+if [ "$HOST_TARGET" = i686-pc-windows-msvc ]; then
+  # The $BASH variable is `/bin/bash` here, but that path does not actually work. There are some
+  # hacks in place somewhere to try to paper over this, but the hacks dont work either (see
+  # <https://github.com/rust-lang/miri/pull/3402>). So we hard-code the correct location for Github
+  # CI instead.
+  BASH="C:/Program Files/Git/usr/bin/bash"
+fi
+
 # Determine configuration for installed build
 echo "Installing release version of Miri"
 export RUSTFLAGS="-D warnings"
@@ -58,12 +67,13 @@ function run_tests {
     MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
 
     # Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
+    # (Need to invoke via explicit `bash -c` for Windows.)
     for FILE in tests/many-seeds/*.rs; do
-      MIRI_SEEDS=64 ./miri many-seeds ./miri run "$FILE"
+      MIRI_SEEDS=64 ./miri many-seeds "$BASH" -c "./miri run '$FILE'"
     done
 
     # Check that the benchmarks build and run, but without actually benchmarking.
-    HYPERFINE="bash -c" ./miri bench
+    HYPERFINE="'$BASH' -c" ./miri bench
   fi
 
   ## test-cargo-miri
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index 169f4521f2d..5f71fc94438 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -3,5 +3,5 @@ set -e
 # Instead of doing just `cargo run --manifest-path .. $@`, we invoke miri-script binary directly. Invoking `cargo run` goes through
 # rustup (that sets it's own environmental variables), which is undesirable.
 MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target
-cargo build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml
+cargo +stable build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml
 "$MIRI_SCRIPT_TARGET_DIR"/debug/miri-script "$@"
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index 7fff6ae80b4..66f323290b2 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -178,7 +178,7 @@ impl Command {
             .context("Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'")?;
         let sh = Shell::new()?;
         sh.change_dir(miri_dir()?);
-        let new_commit = Some(sh.read_file("rust-version")?.trim().to_owned());
+        let new_commit = sh.read_file("rust-version")?.trim().to_owned();
         let current_commit = {
             let rustc_info = cmd!(sh, "rustc +miri --version -v").read();
             if rustc_info.is_err() {
@@ -193,7 +193,7 @@ impl Command {
             }
         };
         // Check if we already are at that commit.
-        if current_commit == new_commit {
+        if current_commit.as_ref() == Some(&new_commit) {
             if active_toolchain()? != "miri" {
                 cmd!(sh, "rustup override set miri").run()?;
             }
@@ -202,7 +202,7 @@ impl Command {
         // Install and setup new toolchain.
         cmd!(sh, "rustup toolchain uninstall miri").run()?;
 
-        cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit...}").run()?;
+        cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit}").run()?;
         cmd!(sh, "rustup override set miri").run()?;
         // Cleanup.
         cmd!(sh, "cargo clean").run()?;
@@ -380,9 +380,9 @@ impl Command {
                 .env("MIRIFLAGS", miriflags)
                 .quiet()
                 .run();
-            if status.is_err() {
+            if let Err(err) = status {
                 println!("Failing seed: {seed}");
-                break;
+                return Err(err.into());
             }
         }
         Ok(())
diff --git a/src/tools/miri/miri.bat b/src/tools/miri/miri.bat
index 959e54d8844..18baa683f65 100644
--- a/src/tools/miri/miri.bat
+++ b/src/tools/miri/miri.bat
@@ -5,7 +5,7 @@ set MIRI_SCRIPT_TARGET_DIR=%0\..\miri-script\target
 
 :: If any other steps are added, the "|| exit /b" must be appended to early
 :: return from the script. If not, it will continue execution.
-cargo build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml || exit /b
+cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml || exit /b
 
 :: Forwards all arguments to this file to the executable.
 :: We invoke the binary directly to avoid going through rustup, which would set some extra
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 9b89f016a77..fa06a069d54 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-c3b05c6e5b5b59613350b8c2875b0add67ed74df
+cb7c63606e53715f94f3ba04d38e50772e4cd23d
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index c12382527e7..8fffb91542f 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -276,7 +276,7 @@ fn run_compiler(
         // If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where
         // that sysroot lives, and that is passed to rustc.
         let sysroot_flag = "--sysroot";
-        if !args.iter().any(|e| e == sysroot_flag) {
+        if !args.iter().any(|e| e.starts_with(sysroot_flag)) {
             // Using the built-in default here would be plain wrong, so we *require*
             // the env var to make sure things make sense.
             let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
@@ -364,6 +364,10 @@ fn main() {
     let args = rustc_driver::args::raw_args(&early_dcx)
         .unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
 
+    // Install the ctrlc handler that sets `rustc_const_eval::CTRL_C_RECEIVED`, even if
+    // MIRI_BE_RUSTC is set.
+    rustc_driver::install_ctrlc_handler();
+
     // If the environment asks us to actually be rustc, then do that.
     if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
         // Earliest rustc setup.
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 805c0580b2f..e2e18d3a734 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -3,12 +3,13 @@
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
 use std::num::TryFromIntError;
-use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
+use std::sync::atomic::Ordering::Relaxed;
 use std::task::Poll;
 use std::time::{Duration, SystemTime};
 
 use either::Either;
 
+use rustc_const_eval::CTRL_C_RECEIVED;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_index::{Idx, IndexVec};
@@ -1045,21 +1046,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
     /// termination).
     fn run_threads(&mut self) -> InterpResult<'tcx, !> {
-        static SIGNALED: AtomicBool = AtomicBool::new(false);
-        ctrlc::set_handler(move || {
-            // Indicate that we have ben signaled to stop. If we were already signaled, exit
-            // immediately. In our interpreter loop we try to consult this value often, but if for
-            // whatever reason we don't get to that check or the cleanup we do upon finding that
-            // this bool has become true takes a long time, the exit here will promptly exit the
-            // process on the second Ctrl-C.
-            if SIGNALED.swap(true, Relaxed) {
-                std::process::exit(1);
-            }
-        })
-        .unwrap();
-        let this = self.eval_context_mut();
+       let this = self.eval_context_mut();
         loop {
-            if SIGNALED.load(Relaxed) {
+            if CTRL_C_RECEIVED.load(Relaxed) {
                 this.machine.handle_abnormal_termination();
                 std::process::exit(1);
             }
diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock
index d5e57a66a8d..f75d68f4e29 100644
--- a/src/tools/miri/test-cargo-miri/Cargo.lock
+++ b/src/tools/miri/test-cargo-miri/Cargo.lock
@@ -3,6 +3,12 @@
 version = 3
 
 [[package]]
+name = "anyhow"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
+
+[[package]]
 name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -24,6 +30,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 name = "cargo-miri-test"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
  "autocfg",
  "byteorder 0.5.3",
  "byteorder 1.4.3",
diff --git a/src/tools/miri/test-cargo-miri/Cargo.toml b/src/tools/miri/test-cargo-miri/Cargo.toml
index 1688096fd9a..58c451741bb 100644
--- a/src/tools/miri/test-cargo-miri/Cargo.toml
+++ b/src/tools/miri/test-cargo-miri/Cargo.toml
@@ -22,6 +22,9 @@ issue_rust_86261 = { path = "issue-rust-86261" }
 byteorder_2 = { package = "byteorder", version = "0.5" } # to test dev-dependencies behave as expected, with renaming
 # Not actually used, but exercises some unique code path (`--extern` .so file).
 serde_derive = "1.0.185"
+# Not actually used, but uses a custom build probe so let's make sure that works.
+# (Ideally we'd check if the probe was successful, but that's not easily possible.)
+anyhow = "1.0"
 
 [build-dependencies]
 autocfg = "1"
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
index fafeb9e0558..4cfc1843a7a 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
@@ -16,6 +16,10 @@ mod utils;
 fn main() {
     test_dup_stdout_stderr();
     test_canonicalize_too_long();
+    test_rename();
+    test_ftruncate::<libc::off_t>(libc::ftruncate);
+    #[cfg(target_os = "linux")]
+    test_ftruncate::<libc::off64_t>(libc::ftruncate64);
     test_readlink();
     test_file_open_unix_allow_two_args();
     test_file_open_unix_needs_three_args();
@@ -133,6 +137,65 @@ fn test_readlink() {
     assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
 }
 
+fn test_rename() {
+    let path1 = prepare("miri_test_libc_fs_source.txt");
+    let path2 = prepare("miri_test_libc_fs_rename_destination.txt");
+
+    let file = File::create(&path1).unwrap();
+    drop(file);
+
+    let c_path1 = CString::new(path1.as_os_str().as_bytes()).expect("CString::new failed");
+    let c_path2 = CString::new(path2.as_os_str().as_bytes()).expect("CString::new failed");
+
+    // Renaming should succeed
+    unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
+    // Check that old file path isn't present
+    assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
+    // Check that the file has moved successfully
+    assert!(path2.metadata().unwrap().is_file());
+
+    // Renaming a nonexistent file should fail
+    let res = unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
+    assert_eq!(res, -1);
+    assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
+
+    remove_file(&path2).unwrap();
+}
+
+fn test_ftruncate<T: From<i32>>(
+    ftruncate: unsafe extern "C" fn(fd: libc::c_int, length: T) -> libc::c_int,
+) {
+    // libc::off_t is i32 in target i686-unknown-linux-gnu
+    // https://docs.rs/libc/latest/i686-unknown-linux-gnu/libc/type.off_t.html
+
+    let bytes = b"hello";
+    let path = prepare("miri_test_libc_fs_ftruncate.txt");
+    let mut file = File::create(&path).unwrap();
+    file.write(bytes).unwrap();
+    file.sync_all().unwrap();
+    assert_eq!(file.metadata().unwrap().len(), 5);
+
+    let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
+    let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) };
+
+    // Truncate to a bigger size
+    let mut res = unsafe { ftruncate(fd, T::from(10)) };
+    assert_eq!(res, 0);
+    assert_eq!(file.metadata().unwrap().len(), 10);
+
+    // Write after truncate
+    file.write(b"dup").unwrap();
+    file.sync_all().unwrap();
+    assert_eq!(file.metadata().unwrap().len(), 10);
+
+    // Truncate to smaller size
+    res = unsafe { ftruncate(fd, T::from(2)) };
+    assert_eq!(res, 0);
+    assert_eq!(file.metadata().unwrap().len(), 2);
+
+    remove_file(&path).unwrap();
+}
+
 #[cfg(target_os = "linux")]
 fn test_o_tmpfile_flag() {
     use std::fs::{create_dir, OpenOptions};
diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs
new file mode 100644
index 00000000000..9b2fc2948bf
--- /dev/null
+++ b/src/tools/miri/tests/pass/async-closure-drop.rs
@@ -0,0 +1,40 @@
+#![feature(async_closure, noop_waker, async_fn_traits)]
+
+use std::future::Future;
+use std::pin::pin;
+use std::task::*;
+
+pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
+    let mut fut = pin!(fut);
+    let ctx = &mut Context::from_waker(Waker::noop());
+
+    loop {
+        match fut.as_mut().poll(ctx) {
+            Poll::Pending => {}
+            Poll::Ready(t) => break t,
+        }
+    }
+}
+
+async fn call_once(f: impl async FnOnce(DropMe)) {
+    f(DropMe("world")).await;
+}
+
+#[derive(Debug)]
+struct DropMe(&'static str);
+
+impl Drop for DropMe {
+    fn drop(&mut self) {
+        println!("{}", self.0);
+    }
+}
+
+pub fn main() {
+    block_on(async {
+        let b = DropMe("hello");
+        let async_closure = async move |a: DropMe| {
+            println!("{a:?} {b:?}");
+        };
+        call_once(async_closure).await;
+    });
+}
diff --git a/src/tools/miri/tests/pass/async-closure-drop.stdout b/src/tools/miri/tests/pass/async-closure-drop.stdout
new file mode 100644
index 00000000000..34cfdedc44a
--- /dev/null
+++ b/src/tools/miri/tests/pass/async-closure-drop.stdout
@@ -0,0 +1,3 @@
+DropMe("world") DropMe("hello")
+world
+hello
diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs
index 9b2fc2948bf..2f7ec2b9e6f 100644
--- a/src/tools/miri/tests/pass/async-closure.rs
+++ b/src/tools/miri/tests/pass/async-closure.rs
@@ -1,6 +1,7 @@
 #![feature(async_closure, noop_waker, async_fn_traits)]
 
 use std::future::Future;
+use std::ops::{AsyncFnMut, AsyncFnOnce};
 use std::pin::pin;
 use std::task::*;
 
@@ -16,25 +17,36 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
     }
 }
 
-async fn call_once(f: impl async FnOnce(DropMe)) {
-    f(DropMe("world")).await;
+async fn call_mut(f: &mut impl AsyncFnMut(i32)) {
+    f(0).await;
 }
 
-#[derive(Debug)]
-struct DropMe(&'static str);
+async fn call_once(f: impl AsyncFnOnce(i32)) {
+    f(1).await;
+}
 
-impl Drop for DropMe {
-    fn drop(&mut self) {
-        println!("{}", self.0);
-    }
+async fn call_normal<F: Future<Output = ()>>(f: &impl Fn(i32) -> F) {
+    f(0).await;
+}
+
+async fn call_normal_once<F: Future<Output = ()>>(f: impl FnOnce(i32) -> F) {
+    f(1).await;
 }
 
 pub fn main() {
     block_on(async {
-        let b = DropMe("hello");
-        let async_closure = async move |a: DropMe| {
-            println!("{a:?} {b:?}");
+        let b = 2i32;
+        let mut async_closure = async move |a: i32| {
+            println!("{a} {b}");
         };
+        call_mut(&mut async_closure).await;
         call_once(async_closure).await;
+
+        // No-capture closures implement `Fn`.
+        let async_closure = async move |a: i32| {
+            println!("{a}");
+        };
+        call_normal(&async_closure).await;
+        call_normal_once(async_closure).await;
     });
 }
diff --git a/src/tools/miri/tests/pass/async-closure.stdout b/src/tools/miri/tests/pass/async-closure.stdout
index 34cfdedc44a..7baae1aa94f 100644
--- a/src/tools/miri/tests/pass/async-closure.stdout
+++ b/src/tools/miri/tests/pass/async-closure.stdout
@@ -1,3 +1,4 @@
-DropMe("world") DropMe("hello")
-world
-hello
+0 2
+1 2
+0
+1
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index 7f363ccdfe5..129d1dfd732 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -4,8 +4,11 @@ use std::ffi::OsString;
 use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
 use std::{env, process::Command};
-use ui_test::{color_eyre::Result, Config, Match, Mode, OutputConflictHandling};
-use ui_test::{status_emitter, CommandBuilder, Format, RustfixMode};
+use ui_test::color_eyre::eyre::{Context, Result};
+use ui_test::{
+    status_emitter, CommandBuilder, Config, Format, Match, Mode, OutputConflictHandling,
+    RustfixMode,
+};
 
 fn miri_path() -> PathBuf {
     PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri")))
@@ -124,6 +127,9 @@ fn run_tests(
     // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
     config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
 
+    // If a test ICEs, we want to see a backtrace.
+    config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into())));
+
     // Handle command-line arguments.
     let args = ui_test::Args::test()?;
     let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
@@ -223,7 +229,7 @@ fn ui(
     with_dependencies: Dependencies,
     tmpdir: &Path,
 ) -> Result<()> {
-    let msg = format!("## Running ui tests in {path} against miri for {target}");
+    let msg = format!("## Running ui tests in {path} for {target}");
     eprintln!("{}", msg.green().bold());
 
     let with_dependencies = match with_dependencies {
@@ -231,6 +237,7 @@ fn ui(
         WithoutDependencies => false,
     };
     run_tests(mode, path, target, with_dependencies, tmpdir)
+        .with_context(|| format!("ui tests in {path} for {target} failed"))
 }
 
 fn get_target() -> String {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 10fdfc0a65f..b74afa0d3e8 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -208,6 +208,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "byteorder", // via ruzstd in object in thorin-dwp
     "cc",
     "cfg-if",
+    "cfg_aliases",
     "compiler_builtins",
     "cpufeatures",
     "crc32fast",
@@ -216,6 +217,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "crossbeam-epoch",
     "crossbeam-utils",
     "crypto-common",
+    "ctrlc",
     "darling",
     "darling_core",
     "darling_macro",
@@ -281,6 +283,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "memmap2",
     "memoffset",
     "miniz_oxide",
+    "nix",
     "nu-ansi-term",
     "num-conv",
     "num_cpus",
diff --git a/tests/codegen/intrinsics/typed_swap.rs b/tests/codegen/intrinsics/typed_swap.rs
index b55fb8ee36f..e73931d1d54 100644
--- a/tests/codegen/intrinsics/typed_swap.rs
+++ b/tests/codegen/intrinsics/typed_swap.rs
@@ -24,9 +24,8 @@ pub unsafe fn swap_i32(x: &mut i32, y: &mut i32) {
     // CHECK-NOT: alloca
 
     // CHECK: %[[TEMP:.+]] = load i32, ptr %x, align 4
-    // CHECK-SAME: !noundef
+    // OPT3-SAME: !noundef
     // OPT0: %[[TEMP2:.+]] = load i32, ptr %y, align 4
-    // OPT0-SAME: !noundef
     // OPT0: store i32 %[[TEMP2]], ptr %x, align 4
     // OPT0-NOT: memcpy
     // OPT3-NOT: load
@@ -42,9 +41,9 @@ pub unsafe fn swap_pair(x: &mut (i32, u32), y: &mut (i32, u32)) {
     // CHECK-NOT: alloca
 
     // CHECK: load i32
-    // CHECK-SAME: !noundef
+    // OPT3-SAME: !noundef
     // CHECK: load i32
-    // CHECK-SAME: !noundef
+    // OPT3-SAME: !noundef
     // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 8, i1 false)
     // CHECK: store i32
     // CHECK: store i32
@@ -57,10 +56,10 @@ pub unsafe fn swap_str<'a>(x: &mut &'a str, y: &mut &'a str) {
     // CHECK-NOT: alloca
 
     // CHECK: load ptr
-    // CHECK-SAME: !nonnull
-    // CHECK-SAME: !noundef
+    // OPT3-SAME: !nonnull
+    // OPT3-SAME: !noundef
     // CHECK: load i64
-    // CHECK-SAME: !noundef
+    // OPT3-SAME: !noundef
     // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false)
     // CHECK: store ptr
     // CHECK: store i64
diff --git a/tests/codegen/loads.rs b/tests/codegen/loads.rs
index b86b3dd3a19..ba4de77ce6f 100644
--- a/tests/codegen/loads.rs
+++ b/tests/codegen/loads.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0
+//@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 -O
+
 #![crate_type = "lib"]
 #![feature(generic_nonzero)]
 
diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs
index 351c8ea8f4b..9e5b69ff267 100644
--- a/tests/codegen/overaligned-constant.rs
+++ b/tests/codegen/overaligned-constant.rs
@@ -16,7 +16,7 @@ fn main() {
     // CHECK-LABEL: @_ZN20overaligned_constant4main
     // CHECK: [[full:%_.*]] = alloca %SmallStruct, align 8
     // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false)
-    // CHECK: %b.0 = load i32, ptr @0, align 4,
+    // CHECK: %b.0 = load i32, ptr @0, align 4
     // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4
     let mut s = S(1);
 
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir
index f51540bcfff..cab7bdb7e3c 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
 
-fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
+fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
     let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10};
 
     bb0: {
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir
index f51540bcfff..cab7bdb7e3c 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir
@@ -1,6 +1,6 @@
 // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
 
-fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
+fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} {
     let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10};
 
     bb0: {
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
index 8b22743d2b0..7480324b177 100644
--- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir
@@ -9,7 +9,7 @@
     storage_conflicts: BitMatrix(0x0) {},
 } */
 
-fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>, _2: &mut Context<'_>) -> Poll<()> {
+fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
     debug _task_context => _4;
     let mut _0: std::task::Poll<()>;
     let mut _3: ();
@@ -17,7 +17,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>
     let mut _5: u32;
 
     bb0: {
-        _5 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16})));
+        _5 = discriminant((*(_1.0: &mut {async fn body of a()})));
         switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5];
     }
 
@@ -29,7 +29,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>
 
     bb2: {
         _0 = Poll::<()>::Ready(move _3);
-        discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}))) = 1;
+        discriminant((*(_1.0: &mut {async fn body of a()}))) = 1;
         return;
     }
 
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
index 2f7c4f7d402..d697ea49231 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir
@@ -51,19 +51,19 @@
     },
 } */
 
-fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, _2: &mut Context<'_>) -> Poll<()> {
+fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
     debug _task_context => _38;
     let mut _0: std::task::Poll<()>;
     let _3: ();
-    let mut _4: {async fn body@$DIR/async_await.rs:12:14: 12:16};
-    let mut _5: {async fn body@$DIR/async_await.rs:12:14: 12:16};
-    let mut _6: {async fn body@$DIR/async_await.rs:12:14: 12:16};
+    let mut _4: {async fn body of a()};
+    let mut _5: {async fn body of a()};
+    let mut _6: {async fn body of a()};
     let mut _7: ();
     let _8: ();
     let mut _9: std::task::Poll<()>;
-    let mut _10: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>;
-    let mut _11: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
-    let mut _12: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
+    let mut _10: std::pin::Pin<&mut {async fn body of a()}>;
+    let mut _11: &mut {async fn body of a()};
+    let mut _12: &mut {async fn body of a()};
     let mut _13: &mut std::task::Context<'_>;
     let mut _14: &mut std::task::Context<'_>;
     let mut _15: &mut std::task::Context<'_>;
@@ -71,14 +71,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     let mut _18: !;
     let mut _19: &mut std::task::Context<'_>;
     let mut _20: ();
-    let mut _21: {async fn body@$DIR/async_await.rs:12:14: 12:16};
-    let mut _22: {async fn body@$DIR/async_await.rs:12:14: 12:16};
-    let mut _23: {async fn body@$DIR/async_await.rs:12:14: 12:16};
+    let mut _21: {async fn body of a()};
+    let mut _22: {async fn body of a()};
+    let mut _23: {async fn body of a()};
     let _24: ();
     let mut _25: std::task::Poll<()>;
-    let mut _26: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>;
-    let mut _27: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
-    let mut _28: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
+    let mut _26: std::pin::Pin<&mut {async fn body of a()}>;
+    let mut _27: &mut {async fn body of a()};
+    let mut _28: &mut {async fn body of a()};
     let mut _29: &mut std::task::Context<'_>;
     let mut _30: &mut std::task::Context<'_>;
     let mut _31: &mut std::task::Context<'_>;
@@ -90,7 +90,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     let mut _38: &mut std::task::Context<'_>;
     let mut _39: u32;
     scope 1 {
-        debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
+        debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
         let _17: ();
         scope 2 {
         }
@@ -99,7 +99,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         }
     }
     scope 4 {
-        debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
+        debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
         let _33: ();
         scope 5 {
         }
@@ -109,7 +109,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     }
 
     bb0: {
-        _39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})));
+        _39 = discriminant((*(_1.0: &mut {async fn body of b()})));
         switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
     }
 
@@ -122,14 +122,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     }
 
     bb2: {
-        _4 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable];
+        _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable];
     }
 
     bb3: {
         StorageDead(_5);
         PlaceMention(_4);
         nop;
-        (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _4;
+        (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}) = move _4;
         goto -> bb4;
     }
 
@@ -139,9 +139,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         StorageLive(_10);
         StorageLive(_11);
         StorageLive(_12);
-        _12 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
+        _12 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
         _11 = &mut (*_12);
-        _10 = Pin::<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable];
+        _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
@@ -157,7 +157,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     bb6: {
         _13 = &mut (*_14);
         StorageDead(_15);
-        _9 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable];
+        _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable];
     }
 
     bb7: {
@@ -186,7 +186,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         StorageDead(_4);
         StorageDead(_19);
         StorageDead(_20);
-        discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 3;
+        discriminant((*(_1.0: &mut {async fn body of b()}))) = 3;
         return;
     }
 
@@ -199,7 +199,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         StorageDead(_12);
         StorageDead(_9);
         StorageDead(_8);
-        drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16})) -> [return: bb12, unwind unreachable];
+        drop((((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable];
     }
 
     bb11: {
@@ -224,14 +224,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     }
 
     bb14: {
-        _21 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable];
+        _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable];
     }
 
     bb15: {
         StorageDead(_22);
         PlaceMention(_21);
         nop;
-        (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _21;
+        (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}) = move _21;
         goto -> bb16;
     }
 
@@ -241,9 +241,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         StorageLive(_26);
         StorageLive(_27);
         StorageLive(_28);
-        _28 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
+        _28 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
         _27 = &mut (*_28);
-        _26 = Pin::<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable];
+        _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable];
     }
 
     bb17: {
@@ -259,7 +259,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
     bb18: {
         _29 = &mut (*_30);
         StorageDead(_31);
-        _25 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable];
+        _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable];
     }
 
     bb19: {
@@ -283,7 +283,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         StorageDead(_21);
         StorageDead(_35);
         StorageDead(_36);
-        discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 4;
+        discriminant((*(_1.0: &mut {async fn body of b()}))) = 4;
         return;
     }
 
@@ -296,7 +296,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
         StorageDead(_28);
         StorageDead(_25);
         StorageDead(_24);
-        drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16})) -> [return: bb23, unwind unreachable];
+        drop((((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable];
     }
 
     bb22: {
@@ -319,7 +319,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
 
     bb25: {
         _0 = Poll::<()>::Ready(move _37);
-        discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 1;
+        discriminant((*(_1.0: &mut {async fn body of b()}))) = 1;
         return;
     }
 
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
index b189b4e73f4..0243e31cb1a 100644
--- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
@@ -5,24 +5,24 @@
       debug permit => (_1.0: ActionPermit<'_, T>);
       debug ctx => (*(_1.1: &mut std::task::Context<'_>));
       let mut _0: ();
-      let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let mut _2: {async fn body of ActionPermit<'_, T>::perform()};
       let mut _3: ActionPermit<'_, T>;
-      let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let mut _5: &mut {async fn body of ActionPermit<'_, T>::perform()};
       let _6: ();
       let mut _7: std::task::Poll<()>;
-      let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+      let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
       let mut _9: &mut std::task::Context<'_>;
       let mut _10: &mut std::task::Context<'_>;
       scope 1 {
           debug fut => _2;
-          let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+          let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
           scope 2 {
               debug fut => _4;
               scope 4 {
               }
 +             scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
 +                 debug _task_context => _31;
-+                 debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
++                 debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>);
 +                 let _11: ActionPermit<'_, T>;
 +                 let mut _12: std::future::Ready<()>;
 +                 let mut _13: std::future::Ready<()>;
@@ -43,19 +43,19 @@
 +                 let mut _30: ();
 +                 let mut _31: &mut std::task::Context<'_>;
 +                 let mut _32: u32;
-+                 let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 scope 8 {
-+                     debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
++                     debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>);
 +                     let mut _15: std::future::Ready<()>;
 +                     scope 9 {
-+                         debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
++                         debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>);
 +                         let _26: ();
 +                         scope 10 {
 +                         }
@@ -71,7 +71,7 @@
 +             }
           }
           scope 3 {
-+             scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
++             scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) {
 +                 debug pointer => _5;
 +             }
           }
@@ -93,11 +93,11 @@
           StorageLive(_4);
           StorageLive(_5);
           _5 = &mut _2;
--         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable];
+-         _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable];
 -     }
 - 
 -     bb2: {
-+         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
++         _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 };
           StorageDead(_5);
           StorageLive(_6);
           StorageLive(_7);
@@ -106,7 +106,7 @@
           StorageLive(_9);
           _10 = deref_copy (_1.1: &mut std::task::Context<'_>);
           _9 = &mut (*_10);
--         _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
+-         _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
 +         StorageLive(_11);
 +         StorageLive(_15);
 +         StorageLive(_16);
@@ -123,7 +123,7 @@
 +         StorageLive(_38);
 +         StorageLive(_39);
 +         StorageLive(_40);
-+         _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _32 = discriminant((*_33));
 +         switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8];
       }
@@ -164,8 +164,8 @@
   
 +     bb3: {
 +         _31 = move _9;
-+         _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
-+         _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
 +         StorageLive(_12);
 +         StorageLive(_13);
@@ -183,7 +183,7 @@
 -         StorageDead(_2);
 -         return;
 +         StorageDead(_13);
-+         _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
 +         goto -> bb5;
 +     }
@@ -194,7 +194,7 @@
 +         StorageLive(_19);
 +         StorageLive(_20);
 +         StorageLive(_21);
-+         _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
 +         _20 = &mut (*_21);
 +         _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable];
@@ -236,7 +236,7 @@
 +         StorageDead(_12);
 +         StorageDead(_28);
 +         StorageDead(_29);
-+         _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         discriminant((*_38)) = 3;
 +         goto -> bb2;
 +     }
@@ -251,13 +251,13 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable];
 +     }
 + 
 +     bb11: {
 +         _7 = Poll::<()>::Ready(move _30);
-+         _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         discriminant((*_40)) = 1;
 +         goto -> bb2;
 +     }
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
index ed18c0a3adb..96a93cdda3d 100644
--- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
@@ -5,24 +5,24 @@
       debug permit => (_1.0: ActionPermit<'_, T>);
       debug ctx => (*(_1.1: &mut std::task::Context<'_>));
       let mut _0: ();
-      let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let mut _2: {async fn body of ActionPermit<'_, T>::perform()};
       let mut _3: ActionPermit<'_, T>;
-      let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let mut _5: &mut {async fn body of ActionPermit<'_, T>::perform()};
       let _6: ();
       let mut _7: std::task::Poll<()>;
-      let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+      let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
       let mut _9: &mut std::task::Context<'_>;
       let mut _10: &mut std::task::Context<'_>;
       scope 1 {
           debug fut => _2;
-          let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+          let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
           scope 2 {
               debug fut => _4;
               scope 4 {
               }
 +             scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
 +                 debug _task_context => _31;
-+                 debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
++                 debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>);
 +                 let _11: ActionPermit<'_, T>;
 +                 let mut _12: std::future::Ready<()>;
 +                 let mut _13: std::future::Ready<()>;
@@ -43,21 +43,21 @@
 +                 let mut _30: ();
 +                 let mut _31: &mut std::task::Context<'_>;
 +                 let mut _32: u32;
-+                 let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _41: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
-+                 let mut _42: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()};
++                 let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()};
 +                 scope 8 {
-+                     debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
++                     debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>);
 +                     let mut _15: std::future::Ready<()>;
 +                     scope 9 {
-+                         debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
++                         debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>);
 +                         let _26: ();
 +                         scope 10 {
 +                         }
@@ -73,7 +73,7 @@
 +             }
           }
           scope 3 {
-+             scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
++             scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) {
 +                 debug pointer => _5;
 +             }
           }
@@ -95,11 +95,11 @@
           StorageLive(_4);
           StorageLive(_5);
           _5 = &mut _2;
--         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5];
+-         _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5];
 -     }
 - 
 -     bb2: {
-+         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
++         _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 };
           StorageDead(_5);
           StorageLive(_6);
           StorageLive(_7);
@@ -108,7 +108,7 @@
           StorageLive(_9);
           _10 = deref_copy (_1.1: &mut std::task::Context<'_>);
           _9 = &mut (*_10);
--         _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
+-         _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
 +         StorageLive(_11);
 +         StorageLive(_15);
 +         StorageLive(_16);
@@ -127,7 +127,7 @@
 +         StorageLive(_40);
 +         StorageLive(_41);
 +         StorageLive(_42);
-+         _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _32 = discriminant((*_33));
 +         switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10];
       }
@@ -181,8 +181,8 @@
 -         return;
 +     bb5: {
 +         _31 = move _9;
-+         _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
-+         _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
++         _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
 +         StorageLive(_12);
 +         StorageLive(_13);
@@ -200,7 +200,7 @@
 -         drop(_2) -> [return: bb6, unwind terminate(cleanup)];
 +     bb6: {
 +         StorageDead(_13);
-+         _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
 +         goto -> bb7;
       }
@@ -213,7 +213,7 @@
 +         StorageLive(_19);
 +         StorageLive(_20);
 +         StorageLive(_21);
-+         _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
 +         _20 = &mut (*_21);
 +         _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15];
@@ -255,7 +255,7 @@
 +         StorageDead(_12);
 +         StorageDead(_28);
 +         StorageDead(_29);
-+         _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         discriminant((*_38)) = 3;
 +         goto -> bb4;
 +     }
@@ -270,13 +270,13 @@
 +         StorageDead(_18);
 +         StorageDead(_17);
 +         StorageDead(_12);
-+         _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19];
 +     }
 + 
 +     bb13: {
 +         _7 = Poll::<()>::Ready(move _30);
-+         _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         discriminant((*_40)) = 1;
 +         goto -> bb4;
 +     }
@@ -308,12 +308,12 @@
 + 
 +     bb18 (cleanup): {
 +         StorageDead(_12);
-+         _41 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)];
 +     }
 + 
 +     bb19 (cleanup): {
-+         _42 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
 +         discriminant((*_42)) = 2;
 +         goto -> bb2;
 +     }
diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
index f1d18b0f7ff..f11c993340f 100644
--- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
+++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -26,18 +26,20 @@
           _3 = _1;
           _2 = move _3 as [u32; 4] (Transmute);
           StorageDead(_3);
-          switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb6];
+          switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb4];
       }
   
       bb1: {
-          switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb6];
+          switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb4];
       }
   
       bb2: {
-          switchInt(_2[2 of 4]) -> [0: bb4, 4294901760: bb5, otherwise: bb6];
+          switchInt(_2[2 of 4]) -> [0: bb3, 4294901760: bb3, otherwise: bb4];
       }
   
       bb3: {
+          StorageLive(_4);
+          _4 = _2[3 of 4];
           StorageLive(_5);
           StorageLive(_6);
           _6 = _4;
@@ -46,27 +48,15 @@
           _0 = Option::<[u8; 4]>::Some(move _5);
           StorageDead(_5);
           StorageDead(_4);
-          goto -> bb7;
+          goto -> bb5;
       }
   
       bb4: {
-          StorageLive(_4);
-          _4 = _2[3 of 4];
-          goto -> bb3;
-      }
-  
-      bb5: {
-          StorageLive(_4);
-          _4 = _2[3 of 4];
-          goto -> bb3;
-      }
-  
-      bb6: {
           _0 = Option::<[u8; 4]>::None;
-          goto -> bb7;
+          goto -> bb5;
       }
   
-      bb7: {
+      bb5: {
           StorageDead(_2);
           return;
       }
diff --git a/tests/run-make/jobserver-error/Makefile b/tests/run-make/jobserver-error/Makefile
index a7601b86715..9f34970f96f 100644
--- a/tests/run-make/jobserver-error/Makefile
+++ b/tests/run-make/jobserver-error/Makefile
@@ -4,9 +4,11 @@ include ../tools.mk
 # ignore-cross-compile
 
 # Test compiler behavior in case environment specifies wrong jobserver.
+# Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr),
+# but also 3 and 4 for either end of the ctrl-c signal handler self-pipe.
 
 all:
-	bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
+	bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=5,5" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
 	bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr -
 
 # This test randomly fails, see https://github.com/rust-lang/rust/issues/110321
diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr
index 343de5cd52c..7c421846535 100644
--- a/tests/run-make/jobserver-error/cannot_open_fd.stderr
+++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr
@@ -1,4 +1,4 @@
-warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9)
+warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=5,5"`: cannot open file descriptor 5 from the jobserver environment variable value: Bad file descriptor (os error 9)
   |
   = note: the build environment is likely misconfigured
 
diff --git a/tests/run-make/link-framework/Makefile b/tests/run-make/link-framework/Makefile
new file mode 100644
index 00000000000..f33347ac7f8
--- /dev/null
+++ b/tests/run-make/link-framework/Makefile
@@ -0,0 +1,23 @@
+# only-macos
+#
+# Check that linking to a framework actually makes it to the linker.
+
+include ../tools.mk
+
+all:
+	$(RUSTC) dep-link-framework.rs
+	$(RUSTC) dep-link-weak-framework.rs
+
+	$(RUSTC) empty.rs
+	otool -L $(TMPDIR)/no-link | $(CGREP) -v CoreFoundation
+
+	$(RUSTC) link-framework.rs
+	otool -L $(TMPDIR)/link-framework | $(CGREP) CoreFoundation | $(CGREP) -v weak
+
+	$(RUSTC) link-weak-framework.rs
+	otool -L $(TMPDIR)/link-weak-framework | $(CGREP) CoreFoundation | $(CGREP) weak
+
+# When linking the framework both normally, and weakly, the weak linking takes preference
+
+	$(RUSTC) link-both.rs
+	otool -L $(TMPDIR)/link-both | $(CGREP) CoreFoundation | $(CGREP) weak
diff --git a/tests/run-make/link-framework/dep-link-framework.rs b/tests/run-make/link-framework/dep-link-framework.rs
new file mode 100644
index 00000000000..9bdeb2052d2
--- /dev/null
+++ b/tests/run-make/link-framework/dep-link-framework.rs
@@ -0,0 +1,4 @@
+#![crate_type = "rlib"]
+
+#[link(name = "CoreFoundation", kind = "framework")]
+extern "C" {}
diff --git a/tests/run-make/link-framework/dep-link-weak-framework.rs b/tests/run-make/link-framework/dep-link-weak-framework.rs
new file mode 100644
index 00000000000..d3e1cf9c98f
--- /dev/null
+++ b/tests/run-make/link-framework/dep-link-weak-framework.rs
@@ -0,0 +1,6 @@
+#![crate_type = "rlib"]
+#![feature(link_arg_attribute)]
+
+#[link(name = "-weak_framework", kind = "link-arg", modifiers = "+verbatim")]
+#[link(name = "CoreFoundation", kind = "link-arg", modifiers = "+verbatim")]
+extern "C" {}
diff --git a/tests/run-make/link-framework/empty.rs b/tests/run-make/link-framework/empty.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/link-framework/empty.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/link-framework/link-both.rs b/tests/run-make/link-framework/link-both.rs
new file mode 100644
index 00000000000..31fc79e1929
--- /dev/null
+++ b/tests/run-make/link-framework/link-both.rs
@@ -0,0 +1,4 @@
+extern crate dep_link_framework;
+extern crate dep_link_weak_framework;
+
+fn main() {}
diff --git a/tests/run-make/link-framework/link-framework.rs b/tests/run-make/link-framework/link-framework.rs
new file mode 100644
index 00000000000..e33e830248e
--- /dev/null
+++ b/tests/run-make/link-framework/link-framework.rs
@@ -0,0 +1,3 @@
+extern crate dep_link_framework;
+
+fn main() {}
diff --git a/tests/run-make/link-framework/link-weak-framework.rs b/tests/run-make/link-framework/link-weak-framework.rs
new file mode 100644
index 00000000000..f0557f8013a
--- /dev/null
+++ b/tests/run-make/link-framework/link-weak-framework.rs
@@ -0,0 +1,3 @@
+extern crate dep_link_weak_framework;
+
+fn main() {}
diff --git a/tests/run-pass-valgrind/osx-frameworks.rs b/tests/run-pass-valgrind/osx-frameworks.rs
deleted file mode 100644
index 71465c0d199..00000000000
--- a/tests/run-pass-valgrind/osx-frameworks.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ pretty-expanded FIXME #23616
-
-#![feature(rustc_private)]
-
-extern crate libc;
-
-#[cfg(target_os = "macos")]
-#[link(name = "CoreFoundation", kind = "framework")]
-extern "C" {
-    fn CFRunLoopGetTypeID() -> libc::c_ulong;
-}
-
-#[cfg(target_os = "macos")]
-pub fn main() {
-    unsafe {
-        CFRunLoopGetTypeID();
-    }
-}
-
-#[cfg(not(target_os = "macos"))]
-pub fn main() {}
diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs
new file mode 100644
index 00000000000..7df042d5f88
--- /dev/null
+++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs
@@ -0,0 +1,30 @@
+// Regression test for issue #105056.
+//@ edition: 2021
+
+fn f(_: impl Trait<T = Copy>) {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP you might have meant to write a bound here
+//~| ERROR the trait `Copy` cannot be made into an object
+
+fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP you might have meant to write a bound here
+//~| ERROR only auto traits can be used as additional traits in a trait object
+//~| HELP consider creating a new trait
+//~| ERROR the trait `Eq` cannot be made into an object
+
+fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {}
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+//~| HELP you might have meant to write a bound here
+
+// Don't suggest assoc ty bound in trait object types, that's not valid:
+type Obj = dyn Trait<T = Clone>;
+//~^ ERROR trait objects must include the `dyn` keyword
+//~| HELP add `dyn` keyword before this trait
+
+trait Trait { type T; }
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr
new file mode 100644
index 00000000000..13be2162c52
--- /dev/null
+++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr
@@ -0,0 +1,91 @@
+error[E0038]: the trait `Copy` cannot be made into an object
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:20
+   |
+LL | fn f(_: impl Trait<T = Copy>) {}
+   |                    ^^^^^^^^ `Copy` cannot be made into an object
+   |
+   = note: the trait cannot be made into an object because it requires `Self: Sized`
+   = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:42
+   |
+LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {}
+   |                        ---------------   ^^ additional non-auto trait
+   |                        |
+   |                        first non-auto trait
+   |
+   = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Debug + Eq {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
+
+error[E0038]: the trait `Eq` cannot be made into an object
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24
+   |
+LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {}
+   |                        ^^^^^^^^^^^^^^^^^^^^ `Eq` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:24
+   |
+LL | fn f(_: impl Trait<T = Copy>) {}
+   |                        ^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | fn f(_: impl Trait<T = dyn Copy>) {}
+   |                        +++
+help: you might have meant to write a bound here
+   |
+LL | fn f(_: impl Trait<T: Copy>) {}
+   |                     ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24
+   |
+LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {}
+   |                        ^^^^^^^^^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | fn g(_: impl Trait<T = dyn std::fmt::Debug + Eq>) {}
+   |                        +++
+help: you might have meant to write a bound here
+   |
+LL | fn g(_: impl Trait<T: std::fmt::Debug + Eq>) {}
+   |                     ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26
+   |
+LL | fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {}
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | fn h(_: impl Trait<T<> = dyn 'static + for<'a> Fn(&'a ())>) {}
+   |                          +++
+help: you might have meant to write a bound here
+   |
+LL | fn h(_: impl Trait<T<>: 'static + for<'a> Fn(&'a ())>) {}
+   |                       ~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:24:26
+   |
+LL | type Obj = dyn Trait<T = Clone>;
+   |                          ^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | type Obj = dyn Trait<T = dyn Clone>;
+   |                          +++
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0038, E0225, E0782.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
index d6fb643702c..def967ba195 100644
--- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
@@ -1,17 +1,17 @@
-print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`: 3078 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of test()}`: 3078 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Suspend0`: 3077 bytes
-print-type-size         local `.__awaitee`: 3077 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}
+print-type-size         local `.__awaitee`: 3077 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 3077 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 3077 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 3077 bytes
-print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}`: 3077 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1025 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
@@ -20,29 +20,29 @@ print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1
 print-type-size         padding: 1 bytes
 print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
-print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
+print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
 print-type-size     variant `Suspend1`: 3076 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size         padding: 1026 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
-print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}
+print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()}
 print-type-size     variant `Suspend2`: 2052 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size         padding: 1 bytes
 print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
-print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
+print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
 print-type-size     variant `Returned`: 1025 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
 print-type-size     variant `Panicked`: 1025 bytes
 print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1025 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1025 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1025 bytes
-print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of big_fut()}`: 1025 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
 print-type-size         upvar `.arg`: 1024 bytes
@@ -52,13 +52,13 @@ print-type-size     variant `Panicked`: 1024 bytes
 print-type-size         upvar `.arg`: 1024 bytes
 print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
 print-type-size type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1 bytes
@@ -67,7 +67,7 @@ print-type-size     discriminant: 1 bytes
 print-type-size     variant `Ready`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Pending`: 0 bytes
-print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}`: 1 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Returned`: 0 bytes
diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout
index 589df102af4..67168a3d6ef 100644
--- a/tests/ui/async-await/future-sizes/large-arg.stdout
+++ b/tests/ui/async-await/future-sizes/large-arg.stdout
@@ -1,47 +1,47 @@
-print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of test()}`: 3076 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Suspend0`: 3075 bytes
-print-type-size         local `.__awaitee`: 3075 bytes, type: {async fn body@$DIR/large-arg.rs:10:30: 12:2}
+print-type-size         local `.__awaitee`: 3075 bytes, type: {async fn body of a<[u8; 1024]>()}
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 3075 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 3075 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 3075 bytes
-print-type-size type: `{async fn body@$DIR/large-arg.rs:10:30: 12:2}`: 3075 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 3075 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
 print-type-size     variant `Suspend0`: 3074 bytes
 print-type-size         upvar `.t`: 1024 bytes
-print-type-size         local `.__awaitee`: 2050 bytes, type: {async fn body@$DIR/large-arg.rs:13:26: 15:2}
+print-type-size         local `.__awaitee`: 2050 bytes, type: {async fn body of b<[u8; 1024]>()}
 print-type-size     variant `Returned`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
 print-type-size     variant `Panicked`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 2050 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 2050 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 2050 bytes
-print-type-size type: `{async fn body@$DIR/large-arg.rs:13:26: 15:2}`: 2050 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 2050 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
 print-type-size     variant `Suspend0`: 2049 bytes
 print-type-size         upvar `.t`: 1024 bytes
-print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/large-arg.rs:16:26: 18:2}
+print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of c<[u8; 1024]>()}
 print-type-size     variant `Returned`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
 print-type-size     variant `Panicked`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1025 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1025 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1025 bytes
@@ -50,7 +50,7 @@ print-type-size     discriminant: 1 bytes
 print-type-size     variant `Ready`: 1024 bytes
 print-type-size         field `.0`: 1024 bytes
 print-type-size     variant `Pending`: 0 bytes
-print-type-size type: `{async fn body@$DIR/large-arg.rs:16:26: 18:2}`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of c<[u8; 1024]>()}`: 1025 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1024 bytes
 print-type-size         upvar `.t`: 1024 bytes
diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.rs b/tests/ui/borrowck/cloning-in-async-block-121547.rs
new file mode 100644
index 00000000000..b2d8dbae977
--- /dev/null
+++ b/tests/ui/borrowck/cloning-in-async-block-121547.rs
@@ -0,0 +1,11 @@
+//@ edition:2021
+
+async fn clone_async_block(value: String) {
+    for _ in 0..10 {
+        async { //~ ERROR: use of moved value: `value` [E0382]
+            drop(value);
+            //~^ HELP: consider cloning the value if the performance cost is acceptable
+        }.await
+    }
+}
+fn main() {}
diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.stderr b/tests/ui/borrowck/cloning-in-async-block-121547.stderr
new file mode 100644
index 00000000000..ae57e0018f8
--- /dev/null
+++ b/tests/ui/borrowck/cloning-in-async-block-121547.stderr
@@ -0,0 +1,22 @@
+error[E0382]: use of moved value: `value`
+  --> $DIR/cloning-in-async-block-121547.rs:5:9
+   |
+LL |   async fn clone_async_block(value: String) {
+   |                              ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
+LL |       for _ in 0..10 {
+   |       -------------- inside of this loop
+LL | /         async {
+LL | |             drop(value);
+   | |                  ----- use occurs due to use in coroutine
+LL | |
+LL | |         }.await
+   | |_________^ value moved here, in previous iteration of loop
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |             drop(value.clone());
+   |                       ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs
index 2d0907c6dfb..d9ff8d61e92 100644
--- a/tests/ui/cfg/diagnostics-same-crate.rs
+++ b/tests/ui/cfg/diagnostics-same-crate.rs
@@ -4,8 +4,12 @@ pub mod inner {
     //~^ NOTE found an item that was configured out
 
     #[cfg(FALSE)]
-    pub mod doesnt_exist { //~ NOTE found an item that was configured out
+    pub mod doesnt_exist {
+        //~^ NOTE found an item that was configured out
+        //~| NOTE found an item that was configured out
+        //~| NOTE found an item that was configured out
         pub fn hello() {}
+        pub mod hi {}
     }
 
     pub mod wrong {
@@ -20,6 +24,15 @@ pub mod inner {
     }
 }
 
+mod placeholder {
+    use super::inner::doesnt_exist;
+    //~^ ERROR unresolved import `super::inner::doesnt_exist`
+    //~| NOTE no `doesnt_exist` in `inner`
+    use super::inner::doesnt_exist::hi;
+    //~^ ERROR unresolved import `super::inner::doesnt_exist`
+    //~| NOTE could not find `doesnt_exist` in `inner`
+}
+
 #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)]
 pub fn vanished() {}
 
diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr
index 62a9d132de0..83a44587238 100644
--- a/tests/ui/cfg/diagnostics-same-crate.stderr
+++ b/tests/ui/cfg/diagnostics-same-crate.stderr
@@ -1,5 +1,29 @@
+error[E0432]: unresolved import `super::inner::doesnt_exist`
+  --> $DIR/diagnostics-same-crate.rs:28:9
+   |
+LL |     use super::inner::doesnt_exist;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `doesnt_exist` in `inner`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-same-crate.rs:7:13
+   |
+LL |     pub mod doesnt_exist {
+   |             ^^^^^^^^^^^^
+
+error[E0432]: unresolved import `super::inner::doesnt_exist`
+  --> $DIR/diagnostics-same-crate.rs:31:23
+   |
+LL |     use super::inner::doesnt_exist::hi;
+   |                       ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-same-crate.rs:7:13
+   |
+LL |     pub mod doesnt_exist {
+   |             ^^^^^^^^^^^^
+
 error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
-  --> $DIR/diagnostics-same-crate.rs:37:12
+  --> $DIR/diagnostics-same-crate.rs:50:12
    |
 LL |     inner::doesnt_exist::hello();
    |            ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
@@ -11,7 +35,7 @@ LL |     pub mod doesnt_exist {
    |             ^^^^^^^^^^^^
 
 error[E0425]: cannot find function `uwu` in module `inner`
-  --> $DIR/diagnostics-same-crate.rs:32:12
+  --> $DIR/diagnostics-same-crate.rs:45:12
    |
 LL |     inner::uwu();
    |            ^^^ not found in `inner`
@@ -23,31 +47,31 @@ LL |     pub fn uwu() {}
    |            ^^^
 
 error[E0425]: cannot find function `meow` in module `inner::right`
-  --> $DIR/diagnostics-same-crate.rs:41:19
+  --> $DIR/diagnostics-same-crate.rs:54:19
    |
 LL |     inner::right::meow();
    |                   ^^^^ not found in `inner::right`
    |
 note: found an item that was configured out
-  --> $DIR/diagnostics-same-crate.rs:18:16
+  --> $DIR/diagnostics-same-crate.rs:22:16
    |
 LL |         pub fn meow() {}
    |                ^^^^
    = note: the item is gated behind the `what-a-cool-feature` feature
 
 error[E0425]: cannot find function `uwu` in this scope
-  --> $DIR/diagnostics-same-crate.rs:28:5
+  --> $DIR/diagnostics-same-crate.rs:41:5
    |
 LL |     uwu();
    |     ^^^ not found in this scope
 
 error[E0425]: cannot find function `vanished` in this scope
-  --> $DIR/diagnostics-same-crate.rs:48:5
+  --> $DIR/diagnostics-same-crate.rs:61:5
    |
 LL |     vanished();
    |     ^^^^^^^^ not found in this scope
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0425, E0433.
+Some errors have detailed explanations: E0425, E0432, E0433.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/consts/auxiliary/issue-63226.rs b/tests/ui/consts/auxiliary/issue-63226.rs
index 2dc9539ba52..5bb0e694af7 100644
--- a/tests/ui/consts/auxiliary/issue-63226.rs
+++ b/tests/ui/consts/auxiliary/issue-63226.rs
@@ -2,13 +2,24 @@ pub struct VTable{
     state:extern "C" fn(),
 }
 
-impl VTable{
+impl VTable {
     pub const fn vtable()->&'static VTable{
         Self::VTABLE
     }
 
     const VTABLE: &'static VTable =
         &VTable{state};
+
+    pub const VTABLE2: &'static VTable =
+        &VTable{state: state2};
 }
 
+pub const VTABLE3: &'static VTable =
+    &VTable{state: state3};
+
+// Only referenced via a `pub const fn`, and yet reachable.
 extern "C" fn state() {}
+// Only referenced via a associated `pub const`, and yet reachable.
+extern "C" fn state2() {}
+// Only referenced via a free `pub const`, and yet reachable.
+extern "C" fn state3() {}
diff --git a/tests/ui/consts/issue-63226.rs b/tests/ui/consts/issue-63226.rs
index f8ceab33925..41e63c294ac 100644
--- a/tests/ui/consts/issue-63226.rs
+++ b/tests/ui/consts/issue-63226.rs
@@ -8,5 +8,7 @@
 use issue_63226::VTable;
 
 static ICE_ICE:&'static VTable=VTable::vtable();
+static MORE_ICE:&'static VTable=VTable::VTABLE2;
+static MORE_ICE3:&'static VTable=issue_63226::VTABLE3;
 
 fn main() {}
diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs
new file mode 100644
index 00000000000..d45e0bcd3b4
--- /dev/null
+++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -g -Cstrip=none -Cforce-frame-pointers=yes
+
+#[inline(never)]
+pub fn callback<F>(f: F)
+where
+    F: FnOnce((&'static str, u32)),
+{
+    f((file!(), line!()))
+}
+
+#[inline(always)]
+pub fn callback_inlined<F>(f: F)
+where
+    F: FnOnce((&'static str, u32)),
+{
+    f((file!(), line!()))
+}
diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs
new file mode 100644
index 00000000000..565d8b65de0
--- /dev/null
+++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -g -Cstrip=none -Cforce-frame-pointers=yes
+
+#![crate_type = "cdylib"]
+#![crate_type = "rlib"]
+
+#![allow(improper_ctypes_definitions)]
+
+type Pos = (&'static str, u32);
+
+macro_rules! pos {
+    () => {
+        (file!(), line!())
+    };
+}
+
+#[no_mangle]
+pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) {
+    inner(outer, pos!());
+}
diff --git a/tests/ui/debuginfo/backtrace-dylib-dep.rs b/tests/ui/debuginfo/backtrace-dylib-dep.rs
new file mode 100644
index 00000000000..e2414073ede
--- /dev/null
+++ b/tests/ui/debuginfo/backtrace-dylib-dep.rs
@@ -0,0 +1,114 @@
+// Check that backtrace info is correctly generated for dynamic libraries and is usable by a
+// rust binary.
+// Part of porting some backtrace tests to rustc: <https://github.com/rust-lang/rust/issues/122899>.
+// Original test:
+// <https://github.com/rust-lang/backtrace-rs/tree/6fa4b85b9962c3e1be8c2e5cc605cd078134152b/crates/dylib-dep>
+// ignore-tidy-linelength
+//@ ignore-android FIXME #17520
+//@ ignore-fuchsia Backtraces not symbolized
+//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written).
+//@ needs-unwind
+//@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes
+//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs
+//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs
+//@ run-pass
+
+#![allow(improper_ctypes)]
+#![allow(improper_ctypes_definitions)]
+
+extern crate dylib_dep_helper;
+extern crate auxiliary;
+
+use std::backtrace::Backtrace;
+
+macro_rules! pos {
+    () => {
+        (file!(), line!())
+    };
+}
+
+macro_rules! check {
+    ($($pos:expr),*) => ({
+        verify(&[$($pos,)* pos!()]);
+    })
+}
+
+fn verify(filelines: &[Pos]) {
+    let trace = Backtrace::capture();
+    eprintln!("-----------------------------------");
+    eprintln!("looking for:");
+    for (file, line) in filelines.iter().rev() {
+        eprintln!("\t{file}:{line}");
+    }
+    eprintln!("found:\n{trace:#?}");
+    let mut iter = filelines.iter().rev();
+    // FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now,
+    // this depends on the debug format of `Backtrace` which is of course fragile.
+    let backtrace = format!("{:#?}", trace);
+    while let Some((file, line)) = iter.next() {
+        // FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has
+        // them.
+        assert!(backtrace.contains(file), "expected backtrace to contain {}", file);
+        assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line);
+    }
+}
+
+type Pos = (&'static str, u32);
+
+extern "C" {
+    #[link_name = "foo"]
+    fn foo(p: Pos, cb: fn(Pos, Pos));
+}
+
+fn main() {
+    std::env::set_var("RUST_BACKTRACE", "1");
+
+    unsafe {
+        foo(pos!(), |a, b| {
+            check!(a, b)
+        })
+    }
+
+    outer(pos!());
+}
+
+#[inline(never)]
+fn outer(main_pos: Pos) {
+    inner(main_pos, pos!());
+    inner_inlined(main_pos, pos!());
+}
+
+#[inline(never)]
+fn inner(main_pos: Pos, outer_pos: Pos) {
+    check!(main_pos, outer_pos);
+    check!(main_pos, outer_pos);
+    let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+    let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+}
+
+#[inline(always)]
+fn inner_inlined(main_pos: Pos, outer_pos: Pos) {
+    check!(main_pos, outer_pos);
+    check!(main_pos, outer_pos);
+
+    #[inline(always)]
+    fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
+        check!(main_pos, outer_pos, inner_pos);
+    }
+    inner_further_inlined(main_pos, outer_pos, pos!());
+
+    let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+    let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+
+    // this tests a distinction between two independent calls to the inlined function.
+    // (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
+    inner_further_inlined(main_pos, outer_pos, pos!());
+}
diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs
new file mode 100644
index 00000000000..b9c6fe92810
--- /dev/null
+++ b/tests/ui/delegation/target-expr.rs
@@ -0,0 +1,38 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait {
+    fn static_method(x: i32) -> i32 { x }
+}
+
+struct F;
+
+struct S(F);
+impl Trait for S {}
+
+fn foo(x: i32) -> i32 { x }
+
+fn bar<T: Default>(_: T) {
+    reuse Trait::static_method {
+        //~^ ERROR delegation with early bound generics is not supported yet
+        //~| ERROR mismatched types
+        let _ = T::Default();
+        //~^ ERROR can't use generic parameters from outer item
+    }
+}
+
+fn main() {
+    let y = 0;
+    reuse <S as Trait>::static_method {
+        let x = y;
+        //~^ ERROR can't capture dynamic environment in a fn item
+        foo(self);
+
+        let reuse_ptr: fn(i32) -> i32  = static_method;
+        reuse_ptr(0)
+    }
+    self.0;
+    //~^ ERROR expected value, found module `self`
+    let z = x;
+    //~^ ERROR cannot find value `x` in this scope
+}
diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr
new file mode 100644
index 00000000000..da0fac2f5e4
--- /dev/null
+++ b/tests/ui/delegation/target-expr.stderr
@@ -0,0 +1,65 @@
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/target-expr.rs:19:17
+   |
+LL | fn bar<T: Default>(_: T) {
+   |        - type parameter from outer item
+LL |     reuse Trait::static_method {
+   |                               - help: try introducing a local generic parameter here: `T,`
+...
+LL |         let _ = T::Default();
+   |                 ^^^^^^^^^^ use of generic parameter from outer item
+
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/target-expr.rs:27:17
+   |
+LL |         let x = y;
+   |                 ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/target-expr.rs:34:5
+   |
+LL | fn main() {
+   |    ---- this function can't have a `self` parameter
+...
+LL |     self.0;
+   |     ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/target-expr.rs:36:13
+   |
+LL |     let z = x;
+   |             ^
+   |
+help: the binding `x` is available in a different scope in the same function
+  --> $DIR/target-expr.rs:27:13
+   |
+LL |         let x = y;
+   |             ^
+
+error: delegation with early bound generics is not supported yet
+  --> $DIR/target-expr.rs:16:18
+   |
+LL |     fn static_method(x: i32) -> i32 { x }
+   |     ------------------------------- callee defined here
+...
+LL |     reuse Trait::static_method {
+   |                  ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/target-expr.rs:16:32
+   |
+LL |       reuse Trait::static_method {
+   |  ________________________________^
+LL | |
+LL | |
+LL | |         let _ = T::Default();
+LL | |
+LL | |     }
+   | |_____^ expected `i32`, found `()`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/generic-const-items/hkl_where_bounds.rs b/tests/ui/generic-const-items/hkl_where_bounds.rs
new file mode 100644
index 00000000000..cded518312a
--- /dev/null
+++ b/tests/ui/generic-const-items/hkl_where_bounds.rs
@@ -0,0 +1,14 @@
+//! Test that nonsense bounds prevent consts from being evaluated at all.
+//@ check-pass
+
+#![feature(generic_const_items)]
+#![allow(incomplete_features)]
+trait Trait {
+    const ASSOC: u32;
+}
+
+// rustfmt eats the where bound
+#[rustfmt::skip]
+const ASSOC: u32 = <&'static ()>::ASSOC where for<'a> &'a (): Trait;
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/trait-bounds/future.current.stderr b/tests/ui/higher-ranked/trait-bounds/future.current.stderr
index 5a6381ad28e..673bc48a424 100644
--- a/tests/ui/higher-ranked/trait-bounds/future.current.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/future.current.stderr
@@ -1,6 +1,6 @@
 error: the compiler unexpectedly panicked. this is a bug.
 
 query stack during panic:
-#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:33:35: 35:2}: core::future::future::Future`
+#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body of strlen()}: core::future::future::Future`
 #1 [codegen_select_candidate] computing candidate for `<strlen as Trait>`
 end of query stack
diff --git a/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs
new file mode 100644
index 00000000000..7445d8dc51e
--- /dev/null
+++ b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs
@@ -0,0 +1,78 @@
+// ICE: failed to get layout for [type error]
+// issue: rust-lang/rust#92979
+
+use std::fs;
+use std::fs::File;
+use std::io::Read;
+use std::convert::TryInto;
+
+fn get_file_as_byte_vec(filename: &String) -> Vec<u8> {
+    let mut f = File::open(&filename).expect("no file found");
+    let metadata = fs::metadata(&filename).expect("unable to read metadata");
+    let mut buffer = vec![0; metadata.len() as usize];
+    f.read(&mut buffer).expect("buffer overflow");
+
+    buffer
+}
+
+
+
+fn demo<T, const N: usize>(v: Vec<T>) -> [T; N] {
+    v.try_into()
+        .unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
+}
+
+
+fn main() {
+
+    // Specify filepath
+    let file: &String = &String::from("SomeBinaryDataFileWith4ByteHeaders_f32s_and_u32s");
+
+    // Read file into a vector of bytes
+    let file_data = get_file_as_byte_vec(file);
+
+    // Print length of vector and first few values
+    let length = file_data.len();
+    println!("The read function read {} bytes", length);
+    println!("The first few bytes:");
+    for i in 0..20{
+        println!("{}", file_data[i]);
+    }
+
+    // Manually count just to make sure
+    let mut n: u64 = 0;
+    for data in file_data{
+        n += 1;
+    }
+    println!("We counted {} bytes", n);
+    assert!(n as usize == length, "Manual counting does not equal len method");
+
+    // Simulation parameters
+    const N: usize = 49627502;                // Number of Particles
+    const bs: f64 = 125.0;                  // Box Size
+    const HEADER_INCREMENT: u64 = 4*1;
+
+    // Initialize index and counter variables
+    let (mut j, mut pos, mut vel, mut id, mut mass): (u64, u64, u64, u64, u64) = (0, 0, 0, 0, 0);
+
+    // Unpack Position Data
+    j += HEADER_INCREMENT;
+    let mut position: Vec<f32> = Vec::new();
+    while position.len() < N*3 {
+
+        let p: Vec<u8> = Vec::new();
+        for item in 0i8..4 {
+            let item = item;
+            p.push(file_data[j as usize]);
+            j += 1;
+        }
+        &mut position[position.len()] = f32::from_be_bytes(demo(p));
+        //~^ ERROR invalid left-hand side of assignment
+    }
+
+    // Ensure position data is indeed position by checking values
+    for p in position {
+        assert!((p > 0.) & (p < 125.), "Not in box")
+    }
+
+}
diff --git a/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr
new file mode 100644
index 00000000000..a6b9e376896
--- /dev/null
+++ b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr
@@ -0,0 +1,16 @@
+error[E0070]: invalid left-hand side of assignment
+  --> $DIR/failed-to-get-layout-for-type-error-ice-92979.rs:69:39
+   |
+LL |         &mut position[position.len()] = f32::from_be_bytes(demo(p));
+   |         ----------------------------- ^
+   |         |
+   |         cannot assign to this expression
+   |
+help: consider dereferencing here to assign to the mutably borrowed value
+   |
+LL |         *&mut position[position.len()] = f32::from_be_bytes(demo(p));
+   |         +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
new file mode 100644
index 00000000000..6380449124f
--- /dev/null
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
@@ -0,0 +1,59 @@
+// ICE argument to function with "rust-call" ABI is not a tuple
+// issue: rust-lang/rust#81974
+
+#![feature(unboxed_closures)]
+#![feature(fn_traits)]
+
+use std::collections::HashMap;
+use std::hash::Hash;
+
+struct CachedFun<A, B> {
+    cache: HashMap<A, B>,
+    fun: fn(&mut CachedFun<A, B>, A) -> B,
+}
+
+impl<A: Eq + Hash, B> CachedFun<A, B> {
+    fn new(fun: fn(&mut Self, A) -> B) -> Self {
+        CachedFun {
+            cache: HashMap::new(),
+            fun,
+        }
+    }
+}
+
+impl<A, B> FnOnce<A> for CachedFun<A, B>
+//~^ ERROR type parameter to bare `FnOnce` trait must be a tuple
+where
+    A: Eq + Hash + Clone,
+    B: Clone,
+{
+    type Output = B;
+    extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+        self.call_mut(a)
+        //~^ ERROR `A` is not a tuple
+    }
+}
+
+impl<A, B> FnMut<A> for CachedFun<A, B>
+//~^ ERROR type parameter to bare `FnMut` trait must be a tuple
+where
+    A: Eq + Hash + Clone,
+    B: Clone,
+{
+    extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+        self.cache.get(&a).map(|a| a.clone()).unwrap_or_else(|| {
+            let b = (self.fun)(self, a.clone());
+            self.cache.insert(a, b.clone());
+            b
+        })
+    }
+}
+
+fn main() -> () {
+    let pesce = |y: &mut CachedFun<i32, i32>, x| x + 1;
+    let cachedcoso = CachedFun::new(pesce);
+    cachedcoso.call_once(1);
+    //~^ ERROR `i32` is not a tuple
+}
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
new file mode 100644
index 00000000000..cceaddf7803
--- /dev/null
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
@@ -0,0 +1,78 @@
+error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:24:12
+   |
+LL | impl<A, B> FnOnce<A> for CachedFun<A, B>
+   |            ^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+note: required by a bound in `FnOnce`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0059]: type parameter to bare `FnMut` trait must be a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:38:12
+   |
+LL | impl<A, B> FnMut<A> for CachedFun<A, B>
+   |            ^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+note: required by a bound in `FnMut`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5
+   |
+LL |     extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:44:5
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: `A` is not a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:33:23
+   |
+LL |         self.call_mut(a)
+   |              -------- ^ the trait `Tuple` is not implemented for `A`
+   |              |
+   |              required by a bound introduced by this call
+   |
+note: required by a bound in `call_mut`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: `i32` is not a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:57:26
+   |
+LL |     cachedcoso.call_once(1);
+   |                --------- ^ the trait `Tuple` is not implemented for `i32`
+   |                |
+   |                required by a bound introduced by this call
+   |
+note: required by a bound in `call_once`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0059, E0277.
+For more information about an error, try `rustc --explain E0059`.
diff --git a/tests/ui/linkage-attr/framework.omit.stderr b/tests/ui/linkage-attr/framework.omit.stderr
new file mode 100644
index 00000000000..5cb4d391437
--- /dev/null
+++ b/tests/ui/linkage-attr/framework.omit.stderr
@@ -0,0 +1,8 @@
+error: linking with `cc` failed: exit status: 1
+   |
+           ld: Undefined symbols:
+             _CFRunLoopGetTypeID, referenced from:
+           clang: error: linker command failed with exit code 1 (use -v to see invocation)
+
+
+error: aborting due to 1 previous error
diff --git a/tests/ui/linkage-attr/framework.rs b/tests/ui/linkage-attr/framework.rs
new file mode 100644
index 00000000000..662ef4c429d
--- /dev/null
+++ b/tests/ui/linkage-attr/framework.rs
@@ -0,0 +1,30 @@
+// Check that linking frameworks on Apple platforms works.
+//@ only-macos
+//@ revisions: omit link weak both
+//@ [omit]build-fail
+//@ [link]run-pass
+//@ [weak]run-pass
+//@ [both]run-pass
+
+// The linker's exact error output changes between Xcode versions.
+//@ compare-output-lines-by-subset
+//@ normalize-stderr-test: "Undefined symbols for architecture .*" -> "ld: Undefined symbols:"
+//@ normalize-stderr-test: "._CFRunLoopGetTypeID.," -> "_CFRunLoopGetTypeID,"
+
+#![cfg_attr(any(weak, both), feature(link_arg_attribute))]
+
+#[cfg_attr(any(link, both), link(name = "CoreFoundation", kind = "framework"))]
+#[cfg_attr(
+    any(weak, both),
+    link(name = "-weak_framework", kind = "link-arg", modifiers = "+verbatim"),
+    link(name = "CoreFoundation", kind = "link-arg", modifiers = "+verbatim")
+)]
+extern "C" {
+    fn CFRunLoopGetTypeID() -> core::ffi::c_ulong;
+}
+
+pub fn main() {
+    unsafe {
+        CFRunLoopGetTypeID();
+    }
+}
diff --git a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs
index 558fcdfe177..cb65f80b089 100644
--- a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs
+++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs
@@ -1,6 +1,6 @@
 #[cfg(FALSE)]
 fn syntax() {
-    bar::<Item = 'a>(); //~ ERROR associated lifetimes are not supported
+    bar::<Item = 'a>(); //~ ERROR lifetimes are not permitted in this context
 }
 
 fn main() {}
diff --git a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr
index 39a6682fcae..606b737e723 100644
--- a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr
+++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr
@@ -1,12 +1,17 @@
-error: associated lifetimes are not supported
-  --> $DIR/recover-assoc-lifetime-constraint.rs:3:11
+error: lifetimes are not permitted in this context
+  --> $DIR/recover-assoc-lifetime-constraint.rs:3:18
    |
 LL |     bar::<Item = 'a>();
-   |           ^^^^^^^--
-   |                  |
-   |                  the lifetime is given here
+   |           -------^^
+   |           |      |
+   |           |      lifetime is not allowed here
+   |           this introduces an associated item binding
    |
-   = help: if you meant to specify a trait object, write `dyn Trait + 'lifetime`
+   = help: if you meant to specify a trait object, write `dyn /* Trait */ + 'a`
+help: you might have meant to write a bound here
+   |
+LL |     bar::<Item: 'a>();
+   |               ~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/pattern/deref-patterns/ref-mut.rs b/tests/ui/pattern/deref-patterns/ref-mut.rs
new file mode 100644
index 00000000000..1918008a761
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/ref-mut.rs
@@ -0,0 +1,17 @@
+#![feature(deref_patterns)]
+//~^ WARN the feature `deref_patterns` is incomplete
+
+use std::rc::Rc;
+
+fn main() {
+    match &mut vec![1] {
+        deref!(x) => {}
+        _ => {}
+    }
+
+    match &mut Rc::new(1) {
+        deref!(x) => {}
+        //~^ ERROR the trait bound `Rc<{integer}>: DerefMut` is not satisfied
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/ref-mut.stderr b/tests/ui/pattern/deref-patterns/ref-mut.stderr
new file mode 100644
index 00000000000..41f1c3061ce
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/ref-mut.stderr
@@ -0,0 +1,20 @@
+warning: the feature `deref_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/ref-mut.rs:1:12
+   |
+LL | #![feature(deref_patterns)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #87121 <https://github.com/rust-lang/rust/issues/87121> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied
+  --> $DIR/ref-mut.rs:13:9
+   |
+LL |         deref!(x) => {}
+   |         ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>`
+   |
+   = note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout
index 1df4d85d09e..83a6962e4cd 100644
--- a/tests/ui/print_type_sizes/async.stdout
+++ b/tests/ui/print_type_sizes/async.stdout
@@ -1,11 +1,11 @@
-print-type-size type: `{async fn body@$DIR/async.rs:10:36: 13:2}`: 16386 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of test()}`: 16386 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 8192 bytes
 print-type-size         upvar `.arg`: 8192 bytes
 print-type-size     variant `Suspend0`: 16385 bytes
 print-type-size         upvar `.arg`: 8192 bytes
 print-type-size         local `.arg`: 8192 bytes
-print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async.rs:8:17: 8:19}
+print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
 print-type-size     variant `Returned`: 8192 bytes
 print-type-size         upvar `.arg`: 8192 bytes
 print-type-size     variant `Panicked`: 8192 bytes
@@ -16,9 +16,9 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment
 print-type-size     variant `MaybeUninit`: 8192 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 8192 bytes
-print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async.rs:8:17: 8:19}>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
-print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async.rs:8:17: 8:19}>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1 bytes
@@ -27,7 +27,7 @@ print-type-size     discriminant: 1 bytes
 print-type-size     variant `Ready`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Pending`: 0 bytes
-print-type-size type: `{async fn body@$DIR/async.rs:8:17: 8:19}`: 1 bytes, alignment: 1 bytes
+print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Returned`: 0 bytes
diff --git a/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs
new file mode 100644
index 00000000000..dd604b6bf7d
--- /dev/null
+++ b/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs
@@ -0,0 +1,38 @@
+// Regression test for issue 123053, where associated types with lifetimes caused generation of the
+// trait object type to fail, causing an ICE.
+//
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021
+//@ no-prefer-dynamic
+//@ only-x86_64-unknown-linux-gnu
+//@ build-pass
+
+trait Iterable {
+    type Item<'a>
+    where
+        Self: 'a;
+    type Iter<'a>: Iterator<Item = Self::Item<'a>>
+    where
+        Self: 'a;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a>;
+}
+
+impl<T> Iterable for [T] {
+    type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a;
+    type Iter<'a> = std::slice::Iter<'a, T> where T: 'a;
+
+    fn iter<'a>(&'a self) -> Self::Iter<'a> {
+        self.iter()
+    }
+}
+
+fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> {
+    it.iter().next()
+}
+
+fn main() {
+    let v = vec![1, 2, 3];
+
+    assert_eq!(Some(&1), get_first(&*v));
+}
diff --git a/tests/ui/traits/trait-selection-ice-84727.rs b/tests/ui/traits/trait-selection-ice-84727.rs
new file mode 100644
index 00000000000..08a282892a5
--- /dev/null
+++ b/tests/ui/traits/trait-selection-ice-84727.rs
@@ -0,0 +1,38 @@
+// ICE Where clause `Binder(..)` was applicable to `Obligation(..)` but now is not
+// issue: rust-lang/rust#84727
+
+struct Cell<Fg, Bg = Fg> {
+    foreground: Color<Fg>,
+    //~^ ERROR cannot find type `Color` in this scope
+    background: Color<Bg>,
+    //~^ ERROR cannot find type `Color` in this scope
+}
+
+trait Over<Bottom, Output> {
+    fn over(self) -> Output;
+}
+
+impl<TopFg, TopBg, BottomFg, BottomBg, NewFg, NewBg>
+    Over<Cell<BottomFg, BottomBg>, Cell<NewFg, NewBg>> for Cell<TopFg, TopBg>
+where
+    Self: Over<Color<BottomBg>, Cell<NewFg>>,
+    //~^ ERROR cannot find type `Color` in this scope
+{
+    fn over(self) -> Cell<NewFg> {
+    //~^ ERROR mismatched types
+        self.over();
+    }
+}
+
+impl<'b, TopFg, TopBg, BottomFg, BottomBg> Over<&Cell<BottomFg, BottomBg>, ()>
+    for Cell<TopFg, TopBg>
+where
+    Cell<TopFg, TopBg>: Over<Cell<BottomFg>, Cell<BottomFg>>,
+{
+    fn over(self) -> Cell<NewBg> {
+    //~^ ERROR cannot find type `NewBg` in this scope
+        self.over();
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/trait-selection-ice-84727.stderr b/tests/ui/traits/trait-selection-ice-84727.stderr
new file mode 100644
index 00000000000..d4bc4163897
--- /dev/null
+++ b/tests/ui/traits/trait-selection-ice-84727.stderr
@@ -0,0 +1,47 @@
+error[E0412]: cannot find type `Color` in this scope
+  --> $DIR/trait-selection-ice-84727.rs:5:17
+   |
+LL |     foreground: Color<Fg>,
+   |                 ^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Color` in this scope
+  --> $DIR/trait-selection-ice-84727.rs:7:17
+   |
+LL |     background: Color<Bg>,
+   |                 ^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Color` in this scope
+  --> $DIR/trait-selection-ice-84727.rs:18:16
+   |
+LL |     Self: Over<Color<BottomBg>, Cell<NewFg>>,
+   |                ^^^^^ not found in this scope
+
+error[E0412]: cannot find type `NewBg` in this scope
+  --> $DIR/trait-selection-ice-84727.rs:32:27
+   |
+LL |     fn over(self) -> Cell<NewBg> {
+   |                           ^^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<'b, TopFg, TopBg, BottomFg, BottomBg, NewBg> Over<&Cell<BottomFg, BottomBg>, ()>
+   |                                          +++++++
+
+error[E0308]: mismatched types
+  --> $DIR/trait-selection-ice-84727.rs:21:22
+   |
+LL |     fn over(self) -> Cell<NewFg> {
+   |        ----          ^^^^^^^^^^^ expected `Cell<NewFg>`, found `()`
+   |        |
+   |        implicitly returns `()` as its body has no tail or `return` expression
+LL |
+LL |         self.over();
+   |                    - help: remove this semicolon to return this value
+   |
+   = note: expected struct `Cell<NewFg>`
+           found unit type `()`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0412.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index d7a0452727e..cd4982b2480 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -10,7 +10,7 @@ error: concrete type differs from previous defining opaque type use
   --> $DIR/hkl_forbidden4.rs:13:1
    |
 LL | async fn operation(_: &mut ()) -> () {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body@$DIR/hkl_forbidden4.rs:13:38: 16:2}`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
    |
 note: previous use here
   --> $DIR/hkl_forbidden4.rs:15:5
diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs
new file mode 100644
index 00000000000..109a70c766d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+type Sendable = impl Send + Duh;
+
+type Foo = impl Trait<Assoc = Sendable>;
+
+fn foo() -> Foo {
+    || 42
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs
new file mode 100644
index 00000000000..4f9d54737dc
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs
@@ -0,0 +1,29 @@
+//@ check-pass
+
+// See https://doc.rust-lang.org/1.77.0/nightly-rustc/rustc_lint/opaque_hidden_inferred_bound/static.OPAQUE_HIDDEN_INFERRED_BOUND.html#example
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+type Sendable = impl Send;
+
+type Foo = impl Trait<Assoc = Sendable>;
+                   //~^ WARNING opaque type `Foo` does not satisfy its associated type bounds
+
+fn foo() -> Foo {
+    || 42
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr
new file mode 100644
index 00000000000..68def454c7f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr
@@ -0,0 +1,13 @@
+warning: opaque type `Foo` does not satisfy its associated type bounds
+  --> $DIR/tait-in-function-return-type-issue-101903.rs:22:23
+   |
+LL |     type Assoc: Duh;
+   |                 --- this associated type bound is unsatisfied for `Sendable`
+...
+LL | type Foo = impl Trait<Assoc = Sendable>;
+   |                       ^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/triagebot.toml b/triagebot.toml
index a42bafe148c..62a706fafe1 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -424,7 +424,15 @@ message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*."
 
 [notify-zulip."A-edition-2021"]
 required_labels = ["C-bug"]
-zulip_stream = 268952 # #edition 2021
+zulip_stream = 268952 # #edition
+topic = "Edition Bugs"
+message_on_add = """\
+Issue #{number} "{title}" has been added (previous edition 2021).
+"""
+
+[notify-zulip."A-edition-2024"]
+required_labels = ["C-bug"]
+zulip_stream = 268952 # #edition
 topic = "Edition Bugs"
 message_on_add = """\
 Issue #{number} "{title}" has been added.