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--INSTALL.md4
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs16
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs32
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs379
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs18
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs157
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock56
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml12
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch2
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs12
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh54
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/returning.rs26
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs31
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs66
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs117
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs216
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/object.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/types.rs204
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs204
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/global_asm.rs34
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs164
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs8
-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.rs11
-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_const_eval/src/transform/validate.rs22
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs19
-rw-r--r--compiler/rustc_expand/src/base.rs42
-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.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs4
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs141
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs141
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs5
-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.rs120
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs43
-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_infer/messages.ftl3
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs18
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs41
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs27
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs9
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs1
-rw-r--r--compiler/rustc_interface/src/interface.rs13
-rw-r--r--compiler/rustc_interface/src/passes.rs1
-rw-r--r--compiler/rustc_interface/src/tests.rs55
-rw-r--r--compiler/rustc_interface/src/util.rs33
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs3
-rw-r--r--compiler/rustc_middle/src/mir/pretty.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/thir.rs2
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs17
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs53
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs6
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs15
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs80
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs8
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/region.rs10
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs19
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs25
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs46
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs43
-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_mir_transform/src/unreachable_prop.rs6
-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/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs24
-rw-r--r--compiler/rustc_passes/src/reachable.rs85
-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/diagnostics.rs20
-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.rs14
-rw-r--r--compiler/rustc_session/src/config.rs10
-rw-r--r--compiler/rustc_session/src/search_paths.rs17
-rw-r--r--compiler/rustc_span/src/def_id.rs24
-rw-r--r--compiler/rustc_span/src/lib.rs11
-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.rs43
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs23
-rw-r--r--compiler/rustc_transmute/src/layout/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs8
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs4
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs10
-rw-r--r--compiler/rustc_type_ir/src/interner.rs56
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs10
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs12
-rw-r--r--library/alloc/src/boxed.rs5
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs2
-rw-r--r--library/alloc/src/ffi/c_str.rs2
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/src/raw_vec.rs42
-rw-r--r--library/alloc/src/rc.rs5
-rw-r--r--library/alloc/src/slice.rs8
-rw-r--r--library/alloc/src/string.rs5
-rw-r--r--library/alloc/src/sync.rs5
-rw-r--r--library/alloc/src/task.rs4
-rw-r--r--library/alloc/src/vec/mod.rs28
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/vec.rs30
-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/macros/mod.rs20
-rw-r--r--library/core/src/net/parser.rs1
-rw-r--r--library/core/src/num/nonzero.rs26
-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/pin.rs2
-rw-r--r--library/core/src/prelude/common.rs (renamed from library/core/src/prelude/v1.rs)9
-rw-r--r--library/core/src/prelude/mod.rs34
-rw-r--r--library/core/src/ptr/alignment.rs1
-rw-r--r--library/core/src/result.rs2
-rw-r--r--library/core/src/sync/atomic.rs6
-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.rs6
-rw-r--r--library/std/src/os/unix/net/stream.rs8
-rw-r--r--library/std/src/prelude/common.rs (renamed from library/std/src/prelude/v1.rs)9
-rw-r--r--library/std/src/prelude/mod.rs26
-rw-r--r--library/std/src/sync/rwlock.rs13
-rw-r--r--library/std/src/sys/pal/unix/fd.rs28
-rw-r--r--library/std/src/sys/pal/unix/fs.rs4
-rw-r--r--library/std/src/sys/pal/unix/thread.rs2
-rw-r--r--library/std/src/sys_common/net.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.rs14
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
-rw-r--r--src/librustdoc/clean/mod.rs13
-rw-r--r--src/librustdoc/config.rs17
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs4
-rw-r--r--src/librustdoc/html/render/search_index.rs5
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.rs10
-rw-r--r--src/tools/compiletest/src/header/needs.rs5
-rw-r--r--src/tools/miri/README.md2
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs10
-rw-r--r--src/tools/miri/src/bin/miri.rs4
-rw-r--r--src/tools/miri/src/concurrency/thread.rs19
-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/run-make-support/src/lib.rs189
-rw-r--r--src/tools/run-make-support/src/run.rs67
-rw-r--r--src/tools/run-make-support/src/rustc.rs147
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs80
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt337
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/run_make_tests.rs89
-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/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs27
-rw-r--r--tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs2
-rw-r--r--tests/coverage/unreachable.cov-map6
-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-fulldeps/pretty-expanded/input.rs16
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs21
-rw-r--r--tests/run-make/a-b-a-linker-guard/rmake.rs44
-rw-r--r--tests/run-make/compiler-builtins/rmake.rs16
-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-make/rustdoc-test-args/rmake.rs9
-rw-r--r--tests/run-make/wasm-abi/rmake.rs21
-rw-r--r--tests/run-make/wasm-custom-section/rmake.rs13
-rw-r--r--tests/run-make/wasm-custom-sections-opt/rmake.rs10
-rw-r--r--tests/run-make/wasm-export-all-symbols/rmake.rs19
-rw-r--r--tests/run-make/wasm-import-module/rmake.rs19
-rw-r--r--tests/run-make/wasm-panic-small/rmake.rs19
-rw-r--r--tests/run-make/wasm-spurious-import/rmake.rs17
-rw-r--r--tests/run-make/wasm-stringify-ints-small/rmake.rs11
-rw-r--r--tests/run-make/wasm-symbols-different-module/rmake.rs11
-rw-r--r--tests/run-make/wasm-symbols-not-exported/rmake.rs23
-rw-r--r--tests/run-make/wasm-symbols-not-imported/rmake.rs23
-rw-r--r--tests/run-pass-valgrind/osx-frameworks.rs21
-rw-r--r--tests/rustdoc-gui/target.goml2
-rw-r--r--tests/ui/anonymous-higher-ranked-lifetime.stderr4
-rw-r--r--tests/ui/associated-consts/associated-const-ambiguity-report.stderr12
-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/binop/binary-op-suggest-deref.stderr14
-rw-r--r--tests/ui/binop/binop-mul-i32-f32.stderr4
-rw-r--r--tests/ui/binop/shift-various-bad-types.stderr48
-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/const-generics/exhaustive-value.stderr14
-rw-r--r--tests/ui/const-generics/generic_arg_infer/issue-91614.stderr4
-rw-r--r--tests/ui/const-generics/issues/issue-67185-2.stderr12
-rw-r--r--tests/ui/consts/auxiliary/issue-63226.rs13
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-3b.stderr4
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-4b.stderr4
-rw-r--r--tests/ui/consts/issue-63226.rs2
-rw-r--r--tests/ui/consts/missing-larger-array-impl.stderr14
-rw-r--r--tests/ui/consts/missing_assoc_const_type.rs28
-rw-r--r--tests/ui/consts/missing_assoc_const_type.stderr8
-rw-r--r--tests/ui/consts/missing_assoc_const_type2.rs21
-rw-r--r--tests/ui/consts/missing_assoc_const_type2.stderr8
-rw-r--r--tests/ui/consts/too_generic_eval_ice.stderr12
-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/bad-resolve.rs10
-rw-r--r--tests/ui/delegation/bad-resolve.stderr37
-rw-r--r--tests/ui/delegation/duplicate-definition-inside-trait-impl.rs2
-rw-r--r--tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr11
-rw-r--r--tests/ui/delegation/explicit-paths-in-traits-pass.rs2
-rw-r--r--tests/ui/delegation/explicit-paths-in-traits-pass.stderr11
-rw-r--r--tests/ui/delegation/explicit-paths-pass.rs13
-rw-r--r--tests/ui/delegation/explicit-paths-pass.stderr11
-rw-r--r--tests/ui/delegation/explicit-paths-signature-pass.rs2
-rw-r--r--tests/ui/delegation/explicit-paths-signature-pass.stderr11
-rw-r--r--tests/ui/delegation/explicit-paths.rs79
-rw-r--r--tests/ui/delegation/explicit-paths.stderr137
-rw-r--r--tests/ui/delegation/not-supported.rs2
-rw-r--r--tests/ui/delegation/not-supported.stderr11
-rw-r--r--tests/ui/delegation/parse.rs2
-rw-r--r--tests/ui/delegation/parse.stderr11
-rw-r--r--tests/ui/delegation/target-expr-pass.rs2
-rw-r--r--tests/ui/delegation/target-expr-pass.stderr11
-rw-r--r--tests/ui/delegation/target-expr.rs40
-rw-r--r--tests/ui/delegation/target-expr.stderr84
-rw-r--r--tests/ui/deriving/issue-103157.stderr10
-rw-r--r--tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr4
-rw-r--r--tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs16
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr66
-rw-r--r--tests/ui/fmt/ifmt-unimpl.stderr12
-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/impl-trait/defining-use-captured-non-universal-region.infer.stderr12
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.rs22
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr12
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs74
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs13
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs16
-rw-r--r--tests/ui/impl-trait/equality.stderr4
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr2
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr2
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.rs2
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs4
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr24
-rw-r--r--tests/ui/impl-trait/impl_trait_projections.stderr16
-rw-r--r--tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr13
-rw-r--r--tests/ui/impl-trait/no-method-suggested-traits.stderr8
-rw-r--r--tests/ui/impl-trait/rpit/early_bound.rs1
-rw-r--r--tests/ui/impl-trait/rpit/early_bound.stderr12
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs37
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr31
-rw-r--r--tests/ui/include-macros/parent_dir.rs12
-rw-r--r--tests/ui/include-macros/parent_dir.stderr50
-rw-r--r--tests/ui/issues/issue-11771.stderr32
-rw-r--r--tests/ui/issues/issue-18446.stderr14
-rw-r--r--tests/ui/issues/issue-24352.stderr4
-rw-r--r--tests/ui/issues/issue-3702-2.stderr20
-rw-r--r--tests/ui/issues/issue-50582.stderr16
-rw-r--r--tests/ui/iterators/invalid-iterator-chain-fixable.stderr6
-rw-r--r--tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr2
-rw-r--r--tests/ui/iterators/invalid-iterator-chain.stderr10
-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/lazy-type-alias/trailing-where-clause.stderr8
-rw-r--r--tests/ui/linkage-attr/framework.omit.stderr8
-rw-r--r--tests/ui/linkage-attr/framework.rs30
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.rs2
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.stderr4
-rw-r--r--tests/ui/match/postfix-match/no-unused-parens.rs8
-rw-r--r--tests/ui/methods/method-ambig-two-traits-cross-crate.stderr12
-rw-r--r--tests/ui/methods/method-ambig-two-traits-with-default-method.stderr16
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr4
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr24
-rw-r--r--tests/ui/methods/method-not-found-generic-arg-elision.stderr4
-rw-r--r--tests/ui/mismatched_types/binops.stderr72
-rw-r--r--tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr2
-rw-r--r--tests/ui/never_type/issue-13352.stderr4
-rw-r--r--tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr50
-rw-r--r--tests/ui/numbers-arithmetic/suggest-float-literal.stderr32
-rw-r--r--tests/ui/on-unimplemented/multiple-impls.stderr12
-rw-r--r--tests/ui/on-unimplemented/slice-index.stderr2
-rw-r--r--tests/ui/on-unimplemented/sum.stderr4
-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/range/range-1.stderr8
-rw-r--r--tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs38
-rw-r--r--tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs10
-rw-r--r--tests/ui/sanitizer/cfi-complex-receiver.rs10
-rw-r--r--tests/ui/sanitizer/cfi-drop-in-place.rs20
-rw-r--r--tests/ui/sanitizer/cfi-self-ref.rs10
-rw-r--r--tests/ui/sanitizer/cfi-virtual-auto.rs10
-rw-r--r--tests/ui/span/multiline-span-simple.stderr4
-rw-r--r--tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr2
-rw-r--r--tests/ui/suggestions/into-str.stderr8
-rw-r--r--tests/ui/suggestions/issue-71394-no-from-impl.stderr6
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr6
-rw-r--r--tests/ui/traits/method-on-unbounded-type-param.stderr16
-rw-r--r--tests/ui/traits/question-mark-result-err-mismatch.stderr8
-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/try-trait/bad-interconversion.stderr6
-rw-r--r--tests/ui/try-trait/issue-32709.stderr2
-rw-r--r--tests/ui/try-trait/option-to-result.stderr2
-rw-r--r--tests/ui/try-trait/try-on-option.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs18
-rw-r--r--tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs22
-rw-r--r--tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs37
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr59
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs52
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs38
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr27
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr69
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr53
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch4.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch4.stderr12
-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--tests/ui/type/type-check-defaults.stderr4
-rw-r--r--tests/ui/typeck/issue-81293.stderr4
-rw-r--r--tests/ui/typeck/issue-90101.stderr2
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.stderr23
-rw-r--r--tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr8
-rw-r--r--triagebot.toml13
430 files changed, 6695 insertions, 3066 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/INSTALL.md b/INSTALL.md
index a23ea4f1eee..9619ec2ce5c 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -151,8 +151,8 @@ toolchain.
    directory and uncomment the line `MSYS2_PATH_TYPE=inherit`.
 
    You could install and use MSYS2's version of git instead with `pacman`,
-   however this is not recommended as it's excrutiatingly slow, and not frequently
-   tested for compatability.
+   however this is not recommended as it's excruciatingly slow, and not frequently
+   tested for compatibility.
 
 3. Start a MINGW64 or MINGW32 shell (depending on whether you want 32-bit
    or 64-bit Rust) either from your start menu, or by running `mingw64.exe`
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 8bd8b6ac144..6eff70410cb 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -75,7 +75,7 @@ pub(crate) struct FixupContext {
 }
 
 /// The default amount of fixing is minimal fixing. Fixups should be turned on
-/// in a targetted fashion where needed.
+/// in a targeted fashion where needed.
 impl Default for FixupContext {
     fn default() -> Self {
         FixupContext {
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_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 54c516c960c..599f7dd18c3 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -95,9 +95,11 @@ pub struct RegionInferenceContext<'tcx> {
     /// visible from this index.
     scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
 
-    /// Contains a "representative" from each SCC. This will be the
-    /// minimal RegionVid belonging to that universe. It is used as a
-    /// kind of hacky way to manage checking outlives relationships,
+    /// Contains the "representative" region of each SCC.
+    /// It is defined as the one with the minimal RegionVid, favoring
+    /// free regions, then placeholders, then existential regions.
+    ///
+    /// It is a hacky way to manage checking regions for equality,
     /// since we can 'canonicalize' each region to the representative
     /// of its SCC and be sure that -- if they have the same repr --
     /// they *must* be equal (though not having the same repr does not
@@ -481,8 +483,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         scc_universes
     }
 
-    /// For each SCC, we compute a unique `RegionVid` (in fact, the
-    /// minimal one that belongs to the SCC). See
+    /// For each SCC, we compute a unique `RegionVid`. See the
     /// `scc_representatives` field of `RegionInferenceContext` for
     /// more details.
     fn compute_scc_representatives(
@@ -490,13 +491,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
     ) -> IndexVec<ConstraintSccIndex, ty::RegionVid> {
         let num_sccs = constraints_scc.num_sccs();
-        let next_region_vid = definitions.next_index();
-        let mut scc_representatives = IndexVec::from_elem_n(next_region_vid, num_sccs);
-
-        for region_vid in definitions.indices() {
-            let scc = constraints_scc.scc(region_vid);
-            let prev_min = scc_representatives[scc];
-            scc_representatives[scc] = region_vid.min(prev_min);
+        let mut scc_representatives = IndexVec::from_elem_n(RegionVid::MAX, num_sccs);
+
+        // Iterate over all RegionVids *in-order* and pick the least RegionVid as the
+        // representative of its SCC. This naturally prefers free regions over others.
+        for (vid, def) in definitions.iter_enumerated() {
+            let repr = &mut scc_representatives[constraints_scc.scc(vid)];
+            if *repr == ty::RegionVid::MAX {
+                *repr = vid;
+            } else if matches!(def.origin, NllRegionVariableOrigin::Placeholder(_))
+                && matches!(definitions[*repr].origin, NllRegionVariableOrigin::Existential { .. })
+            {
+                // Pick placeholders over existentials even if they have a greater RegionVid.
+                *repr = vid;
+            }
         }
 
         scc_representatives
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index d5875a226fe..63b80445817 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,15 +1,14 @@
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::OpaqueTyOrigin;
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::TyCtxtInferExt as _;
+use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_macros::extension;
 use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::RegionVid;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_span::Span;
@@ -18,76 +17,19 @@ use rustc_trait_selection::traits::ObligationCtxt;
 
 use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
 use crate::session_diagnostics::NonGenericOpaqueTypeParam;
+use crate::universal_regions::RegionClassification;
 
 use super::RegionInferenceContext;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
-    fn universal_name(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
-        let scc = self.constraint_sccs.scc(vid);
-        self.scc_values
-            .universal_regions_outlived_by(scc)
-            .find_map(|lb| self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?))
-    }
-
-    fn generic_arg_to_region(&self, arg: ty::GenericArg<'tcx>) -> Option<RegionVid> {
-        let region = arg.as_region()?;
-
-        if let ty::RePlaceholder(..) = region.kind() {
-            None
-        } else {
-            Some(self.to_region_vid(region))
-        }
-    }
-
-    /// Check that all opaque types have the same region parameters if they have the same
-    /// non-region parameters. This is necessary because within the new solver we perform various query operations
-    /// modulo regions, and thus could unsoundly select some impls that don't hold.
-    fn check_unique(
-        &self,
-        infcx: &InferCtxt<'tcx>,
-        opaque_ty_decls: &FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
-    ) {
-        for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() {
-            for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) {
-                if a.def_id != b.def_id {
-                    continue;
-                }
-                // Non-lifetime params differ -> ok
-                if infcx.tcx.erase_regions(a.args) != infcx.tcx.erase_regions(b.args) {
-                    continue;
-                }
-                trace!(?a, ?b);
-                for (a, b) in a.args.iter().zip(b.args) {
-                    trace!(?a, ?b);
-                    let Some(r1) = self.generic_arg_to_region(a) else {
-                        continue;
-                    };
-                    let Some(r2) = self.generic_arg_to_region(b) else {
-                        continue;
-                    };
-                    if self.eval_equal(r1, r2) {
-                        continue;
-                    }
-
-                    infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
-                        arg: self.universal_name(r1).unwrap().into(),
-                        prev: self.universal_name(r2).unwrap().into(),
-                        span: a_ty.span,
-                        prev_span: b_ty.span,
-                    });
-                }
-            }
-        }
-    }
-
     /// Resolve any opaque types that were encountered while borrow checking
     /// this item. This is then used to get the type in the `type_of` query.
     ///
     /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`.
     /// This is lowered to give HIR something like
     ///
-    /// type f<'a>::_Return<'_a> = impl Sized + '_a;
-    /// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x }
+    /// type f<'a>::_Return<'_x> = impl Sized + '_x;
+    /// fn f<'a>(x: &'a i32) -> f<'a>::_Return<'a> { x }
     ///
     /// When checking the return type record the type from the return and the
     /// type used in the return value. In this case they might be `_Return<'1>`
@@ -95,118 +37,102 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// Once we to this method, we have completed region inference and want to
     /// call `infer_opaque_definition_from_instantiation` to get the inferred
-    /// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation`
+    /// type of `_Return<'_x>`. `infer_opaque_definition_from_instantiation`
     /// compares lifetimes directly, so we need to map the inference variables
     /// back to concrete lifetimes: `'static`, `ReEarlyParam` or `ReLateParam`.
     ///
-    /// First we map all the lifetimes in the concrete type to an equal
-    /// universal region that occurs in the concrete type's args, in this case
-    /// this would result in `&'1 i32`. We only consider regions in the args
+    /// First we map the regions in the the generic parameters `_Return<'1>` to
+    /// their `external_name` giving `_Return<'a>`. This step is a bit involved.
+    /// See the [rustc-dev-guide chapter] for more info.
+    ///
+    /// Then we map all the lifetimes in the concrete type to an equal
+    /// universal region that occurs in the opaque type's args, in this case
+    /// this would result in `&'a i32`. We only consider regions in the args
     /// in case there is an equal region that does not. For example, this should
     /// be allowed:
     /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
     ///
-    /// Then we map the regions in both the type and the generic parameters to their
-    /// `external_name` giving `concrete_type = &'a i32`,
-    /// `args = ['static, 'a]`. This will then allow
-    /// `infer_opaque_definition_from_instantiation` to determine that
-    /// `_Return<'_a> = &'_a i32`.
+    /// This will then allow `infer_opaque_definition_from_instantiation` to
+    /// determine that `_Return<'_x> = &'_x i32`.
     ///
     /// There's a slight complication around closures. Given
     /// `fn f<'a: 'a>() { || {} }` the closure's type is something like
     /// `f::<'a>::{{closure}}`. The region parameter from f is essentially
     /// ignored by type checking so ends up being inferred to an empty region.
     /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
-    /// which has no `external_name` in which case we use `'empty` as the
+    /// which has no `external_name` in which case we use `'{erased}` as the
     /// region to pass to `infer_opaque_definition_from_instantiation`.
+    ///
+    /// [rustc-dev-guide chapter]:
+    /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
     #[instrument(level = "debug", skip(self, infcx), ret)]
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'tcx>,
         opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
     ) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
-        self.check_unique(infcx, &opaque_ty_decls);
-
         let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
-
-        let member_constraints: FxIndexMap<_, _> = self
-            .member_constraints
-            .all_indices()
-            .map(|ci| (self.member_constraints[ci].key, ci))
-            .collect();
-        debug!(?member_constraints);
+        let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
+            FxIndexMap::default();
 
         for (opaque_type_key, concrete_type) in opaque_ty_decls {
-            let args = opaque_type_key.args;
-            debug!(?concrete_type, ?args);
+            debug!(?opaque_type_key, ?concrete_type);
 
-            let mut arg_regions = vec![self.universal_regions.fr_static];
+            let mut arg_regions: Vec<(ty::RegionVid, ty::Region<'_>)> =
+                vec![(self.universal_regions.fr_static, infcx.tcx.lifetimes.re_static)];
 
-            let to_universal_region = |vid, arg_regions: &mut Vec<_>| match self.universal_name(vid)
-            {
-                Some(region) => {
-                    let vid = self.universal_regions.to_region_vid(region);
-                    arg_regions.push(vid);
-                    region
-                }
-                None => {
-                    arg_regions.push(vid);
-                    ty::Region::new_error_with_message(
-                        infcx.tcx,
-                        concrete_type.span,
-                        "opaque type with non-universal region args",
-                    )
-                }
-            };
+            let opaque_type_key =
+                opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |region| {
+                    // Use the SCC representative instead of directly using `region`.
+                    // See [rustc-dev-guide chapter] § "Strict lifetime equality".
+                    let scc = self.constraint_sccs.scc(region.as_var());
+                    let vid = self.scc_representatives[scc];
+                    let named = match self.definitions[vid].origin {
+                        // Iterate over all universal regions in a consistent order and find the
+                        // *first* equal region. This makes sure that equal lifetimes will have
+                        // the same name and simplifies subsequent handling.
+                        // See [rustc-dev-guide chapter] § "Semantic lifetime equality".
+                        NllRegionVariableOrigin::FreeRegion => self
+                            .universal_regions
+                            .universal_regions()
+                            .filter(|&ur| {
+                                // See [rustc-dev-guide chapter] § "Closure restrictions".
+                                !matches!(
+                                    self.universal_regions.region_classification(ur),
+                                    Some(RegionClassification::External)
+                                )
+                            })
+                            .find(|&ur| self.universal_region_relations.equal(vid, ur))
+                            .map(|ur| self.definitions[ur].external_name.unwrap()),
+                        NllRegionVariableOrigin::Placeholder(placeholder) => {
+                            Some(ty::Region::new_placeholder(infcx.tcx, placeholder))
+                        }
+                        NllRegionVariableOrigin::Existential { .. } => None,
+                    }
+                    .unwrap_or_else(|| {
+                        ty::Region::new_error_with_message(
+                            infcx.tcx,
+                            concrete_type.span,
+                            "opaque type with non-universal region args",
+                        )
+                    });
 
-            // Start by inserting universal regions from the member_constraint choice regions.
-            // This will ensure they get precedence when folding the regions in the concrete type.
-            if let Some(&ci) = member_constraints.get(&opaque_type_key) {
-                for &vid in self.member_constraints.choice_regions(ci) {
-                    to_universal_region(vid, &mut arg_regions);
-                }
-            }
-            debug!(?arg_regions);
-
-            // Next, insert universal regions from args, so we can translate regions that appear
-            // in them but are not subject to member constraints, for instance closure args.
-            let universal_args = infcx.tcx.fold_regions(args, |region, _| {
-                if let ty::RePlaceholder(..) = region.kind() {
-                    // Higher kinded regions don't need remapping, they don't refer to anything outside of this the args.
-                    return region;
-                }
-                let vid = self.to_region_vid(region);
-                to_universal_region(vid, &mut arg_regions)
-            });
-            debug!(?universal_args);
-            debug!(?arg_regions);
-
-            // Deduplicate the set of regions while keeping the chosen order.
-            let arg_regions = arg_regions.into_iter().collect::<FxIndexSet<_>>();
-            debug!(?arg_regions);
-
-            let universal_concrete_type =
-                infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
-                    ty::ReVar(vid) => arg_regions
-                        .iter()
-                        .find(|ur_vid| self.eval_equal(vid, **ur_vid))
-                        .and_then(|ur_vid| self.definitions[*ur_vid].external_name)
-                        .unwrap_or(infcx.tcx.lifetimes.re_erased),
-                    ty::RePlaceholder(_) => ty::Region::new_error_with_message(
-                        infcx.tcx,
-                        concrete_type.span,
-                        "hidden type contains placeholders, we don't support higher kinded opaques yet",
-                    ),
-                    _ => region,
+                    arg_regions.push((vid, named));
+                    named
                 });
-            debug!(?universal_concrete_type);
+            debug!(?opaque_type_key, ?arg_regions);
+
+            let concrete_type = infcx.tcx.fold_regions(concrete_type, |region, _| {
+                arg_regions
+                    .iter()
+                    .find(|&&(arg_vid, _)| self.eval_equal(region.as_var(), arg_vid))
+                    .map(|&(_, arg_named)| arg_named)
+                    .unwrap_or(infcx.tcx.lifetimes.re_erased)
+            });
+            debug!(?concrete_type);
 
-            let opaque_type_key =
-                OpaqueTypeKey { def_id: opaque_type_key.def_id, args: universal_args };
-            let ty = infcx.infer_opaque_definition_from_instantiation(
-                opaque_type_key,
-                universal_concrete_type,
-            );
+            let ty =
+                infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
             // Sometimes two opaque types are the same only after we remap the generic parameters
             // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
             // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
@@ -234,6 +160,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     OpaqueHiddenType { ty, span: concrete_type.span },
                 );
             }
+
+            // Check that all opaque types have the same region parameters if they have the same
+            // non-region parameters. This is necessary because within the new solver we perform
+            // various query operations modulo regions, and thus could unsoundly select some impls
+            // that don't hold.
+            if !ty.references_error()
+                && let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
+                    infcx.tcx.erase_regions(opaque_type_key),
+                    (opaque_type_key, concrete_type.span),
+                )
+                && let Some((arg1, arg2)) = std::iter::zip(
+                    prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
+                    opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
+                )
+                .find(|(arg1, arg2)| arg1 != arg2)
+            {
+                infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
+                    arg: arg1,
+                    prev: arg2,
+                    span: prev_span,
+                    prev_span: concrete_type.span,
+                });
+            }
         }
         result
     }
@@ -422,42 +371,46 @@ fn check_opaque_type_well_formed<'tcx>(
     }
 }
 
-fn check_opaque_type_parameter_valid(
-    tcx: TyCtxt<'_>,
-    opaque_type_key: OpaqueTypeKey<'_>,
+/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
+///
+/// [rustc-dev-guide chapter]:
+/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
+fn check_opaque_type_parameter_valid<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    opaque_type_key: OpaqueTypeKey<'tcx>,
     span: Span,
 ) -> Result<(), ErrorGuaranteed> {
-    let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
-    let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin {
-        OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true),
-        OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false),
-    };
-
-    let parent_generics = tcx.generics_of(parent);
+    let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
+    let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
     let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
 
-    // Only check the parent generics, which will ignore any of the
-    // duplicated lifetime args that come from reifying late-bounds.
-    for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() {
+    for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
         let arg_is_param = match arg.unpack() {
             GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
-            GenericArgKind::Lifetime(lt) if is_ty_alias => {
+            GenericArgKind::Lifetime(lt) => {
                 matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
+                    || (lt.is_static() && opaque_env.param_equal_static(i))
             }
-            // FIXME(#113916): we can't currently check for unique lifetime params,
-            // see that issue for more. We will also have to ignore unused lifetime
-            // params for RPIT, but that's comparatively trivial ✨
-            GenericArgKind::Lifetime(_) => continue,
             GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
         };
 
         if arg_is_param {
-            seen_params.entry(arg).or_default().push(i);
+            // Register if the same lifetime appears multiple times in the generic args.
+            // There is an exception when the opaque type *requires* the lifetimes to be equal.
+            // See [rustc-dev-guide chapter] § "An exception to uniqueness rule".
+            let seen_where = seen_params.entry(arg).or_default();
+            if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
+                seen_where.push(i);
+            }
         } else {
             // Prevent `fn foo() -> Foo<u32>` from being defining.
-            let opaque_param = parent_generics.param_at(i, tcx);
+            let opaque_param = opaque_generics.param_at(i, tcx);
             let kind = opaque_param.kind.descr();
 
+            if let Err(guar) = opaque_env.param_is_error(i) {
+                return Err(guar);
+            }
+
             return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
                 ty: arg,
                 kind,
@@ -469,10 +422,10 @@ fn check_opaque_type_parameter_valid(
 
     for (_, indices) in seen_params {
         if indices.len() > 1 {
-            let descr = parent_generics.param_at(indices[0], tcx).kind.descr();
+            let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
             let spans: Vec<_> = indices
                 .into_iter()
-                .map(|i| tcx.def_span(parent_generics.param_at(i, tcx).def_id))
+                .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
                 .collect();
             #[allow(rustc::diagnostic_outside_of_impl)]
             #[allow(rustc::untranslatable_diagnostic)]
@@ -486,3 +439,91 @@ fn check_opaque_type_parameter_valid(
 
     Ok(())
 }
+
+/// Computes if an opaque type requires a lifetime parameter to be equal to
+/// another one or to the `'static` lifetime.
+/// These requirements are derived from the explicit and implied bounds.
+struct LazyOpaqueTyEnv<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+
+    /// Equal parameters will have the same name. Computed Lazily.
+    /// Example:
+    ///     `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
+    ///     Identity args: `['a, 'b, 'c]`
+    ///     Canonical args: `['static, 'b, 'b]`
+    canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
+}
+
+impl<'tcx> LazyOpaqueTyEnv<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
+        Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
+    }
+
+    pub fn param_equal_static(&self, param_index: usize) -> bool {
+        self.get_canonical_args()[param_index].expect_region().is_static()
+    }
+
+    pub fn params_equal(&self, param1: usize, param2: usize) -> bool {
+        let canonical_args = self.get_canonical_args();
+        canonical_args[param1] == canonical_args[param2]
+    }
+
+    pub fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
+        self.get_canonical_args()[param_index].error_reported()
+    }
+
+    fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
+        use rustc_hir as hir;
+        use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+        use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
+
+        if let Some(&canonical_args) = self.canonical_args.get() {
+            return canonical_args;
+        }
+
+        let &Self { tcx, def_id, .. } = self;
+        let origin = tcx.opaque_type_origin(def_id);
+        let parent = match origin {
+            hir::OpaqueTyOrigin::FnReturn(parent)
+            | hir::OpaqueTyOrigin::AsyncFn(parent)
+            | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
+        };
+        let param_env = tcx.param_env(parent);
+        let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
+            tcx,
+            def_id.to_def_id(),
+            |param, _| {
+                tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
+            },
+        );
+
+        let infcx = tcx.infer_ctxt().build();
+        let ocx = ObligationCtxt::new(&infcx);
+
+        let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
+            tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
+            Default::default()
+        });
+        let implied_bounds = infcx.implied_bounds_tys(param_env, parent, &wf_tys);
+        let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+
+        let mut seen = vec![tcx.lifetimes.re_static];
+        let canonical_args = tcx.fold_regions(args, |r1, _| {
+            if r1.is_error() {
+                r1
+            } else if let Some(&r2) = seen.iter().find(|&&r2| {
+                let free_regions = outlives_env.free_region_map();
+                free_regions.sub_free_regions(tcx, r1, r2)
+                    && free_regions.sub_free_regions(tcx, r2, r1)
+            }) {
+                r2
+            } else {
+                seen.push(r1);
+                r1
+            }
+        });
+        self.canonical_args.set(canonical_args).unwrap();
+        canonical_args
+    }
+}
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 86d20599a2a..7553e3ee04f 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -164,6 +164,13 @@ impl UniversalRegionRelations<'_> {
         self.outlives.contains(fr1, fr2)
     }
 
+    /// Returns `true` if fr1 is known to equal fr2.
+    ///
+    /// This will only ever be true for universally quantified regions.
+    pub(crate) fn equal(&self, fr1: RegionVid, fr2: RegionVid) -> bool {
+        self.outlives.contains(fr1, fr2) && self.outlives.contains(fr2, fr1)
+    }
+
     /// Returns a vector of free regions `x` such that `fr1: x` is
     /// known to hold.
     pub(crate) fn regions_outlived_by(&self, fr1: RegionVid) -> Vec<RegionVid> {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index a206aac0467..b0bdf4af097 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -229,6 +229,22 @@ pub(crate) fn type_check<'mir, 'tcx>(
                 );
             }
 
+            // Convert all regions to nll vars.
+            let (opaque_type_key, hidden_type) =
+                infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| {
+                    match region.kind() {
+                        ty::ReVar(_) => region,
+                        ty::RePlaceholder(placeholder) => checker
+                            .borrowck_context
+                            .constraints
+                            .placeholder_region(infcx, placeholder),
+                        _ => ty::Region::new_var(
+                            infcx.tcx,
+                            checker.borrowck_context.universal_regions.to_region_vid(region),
+                        ),
+                    }
+                });
+
             (opaque_type_key, hidden_type)
         })
         .collect();
@@ -592,7 +608,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             }
             self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
         }
-        // If the region is live at at least one location in the promoted MIR,
+        // If the region is live at least one location in the promoted MIR,
         // then add a liveness constraint to the main MIR for this region
         // at the location provided as an argument to this method
         //
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index dbb86df6811..abcdfabcaed 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -3,17 +3,22 @@ use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast_pretty::pprust;
-use rustc_expand::base::{check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path};
+use rustc_data_structures::sync::Lrc;
+use rustc_expand::base::{
+    check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
+    resolve_path,
+};
 use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt};
 use rustc_expand::base::{MacEager, MacResult, MacroExpanderResult};
 use rustc_expand::module::DirOwnership;
 use rustc_parse::new_parser_from_file;
 use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
+use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Pos, Span};
-
 use smallvec::SmallVec;
+use std::path::{Path, PathBuf};
 use std::rc::Rc;
 
 // These macros all relate to the file system; they either return
@@ -182,35 +187,26 @@ pub fn expand_include_str(
     tts: TokenStream,
 ) -> MacroExpanderResult<'static> {
     let sp = cx.with_def_site_ctxt(sp);
-    let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
+    let ExpandResult::Ready(mac) = get_single_str_spanned_from_tts(cx, sp, tts, "include_str!")
+    else {
         return ExpandResult::Retry(());
     };
-    let file = match mac {
-        Ok(file) => file,
+    let (path, path_span) = match mac {
+        Ok(res) => res,
         Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
     };
-    let file = match resolve_path(&cx.sess, file.as_str(), sp) {
-        Ok(f) => f,
-        Err(err) => {
-            let guar = err.emit();
-            return ExpandResult::Ready(DummyResult::any(sp, guar));
-        }
-    };
-    ExpandResult::Ready(match cx.source_map().load_binary_file(&file) {
+    ExpandResult::Ready(match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) {
         Ok(bytes) => match std::str::from_utf8(&bytes) {
             Ok(src) => {
                 let interned_src = Symbol::intern(src);
                 MacEager::expr(cx.expr_str(sp, interned_src))
             }
             Err(_) => {
-                let guar = cx.dcx().span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
+                let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file"));
                 DummyResult::any(sp, guar)
             }
         },
-        Err(e) => {
-            let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
-            DummyResult::any(sp, guar)
-        }
+        Err(dummy) => dummy,
     })
 }
 
@@ -220,28 +216,127 @@ pub fn expand_include_bytes(
     tts: TokenStream,
 ) -> MacroExpanderResult<'static> {
     let sp = cx.with_def_site_ctxt(sp);
-    let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
+    let ExpandResult::Ready(mac) = get_single_str_spanned_from_tts(cx, sp, tts, "include_bytes!")
+    else {
         return ExpandResult::Retry(());
     };
-    let file = match mac {
-        Ok(file) => file,
+    let (path, path_span) = match mac {
+        Ok(res) => res,
         Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
     };
-    let file = match resolve_path(&cx.sess, file.as_str(), sp) {
-        Ok(f) => f,
+    ExpandResult::Ready(match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) {
+        Ok(bytes) => {
+            let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
+            MacEager::expr(expr)
+        }
+        Err(dummy) => dummy,
+    })
+}
+
+fn load_binary_file(
+    cx: &mut ExtCtxt<'_>,
+    original_path: &Path,
+    macro_span: Span,
+    path_span: Span,
+) -> Result<Lrc<[u8]>, Box<dyn MacResult>> {
+    let resolved_path = match resolve_path(&cx.sess, original_path, macro_span) {
+        Ok(path) => path,
         Err(err) => {
             let guar = err.emit();
-            return ExpandResult::Ready(DummyResult::any(sp, guar));
+            return Err(DummyResult::any(macro_span, guar));
         }
     };
-    ExpandResult::Ready(match cx.source_map().load_binary_file(&file) {
-        Ok(bytes) => {
-            let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
-            MacEager::expr(expr)
+    match cx.source_map().load_binary_file(&resolved_path) {
+        Ok(data) => Ok(data),
+        Err(io_err) => {
+            let mut err = cx.dcx().struct_span_err(
+                macro_span,
+                format!("couldn't read `{}`: {io_err}", resolved_path.display()),
+            );
+
+            if original_path.is_relative() {
+                let source_map = cx.sess.source_map();
+                let new_path = source_map
+                    .span_to_filename(macro_span.source_callsite())
+                    .into_local_path()
+                    .and_then(|src| find_path_suggestion(source_map, src.parent()?, original_path))
+                    .and_then(|path| path.into_os_string().into_string().ok());
+
+                if let Some(new_path) = new_path {
+                    err.span_suggestion(
+                        path_span,
+                        "there is a file with the same name in a different directory",
+                        format!("\"{}\"", new_path.replace('\\', "/").escape_debug()),
+                        rustc_lint_defs::Applicability::MachineApplicable,
+                    );
+                }
+            }
+            let guar = err.emit();
+            Err(DummyResult::any(macro_span, guar))
         }
-        Err(e) => {
-            let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
-            DummyResult::any(sp, guar)
+    }
+}
+
+fn find_path_suggestion(
+    source_map: &SourceMap,
+    base_dir: &Path,
+    wanted_path: &Path,
+) -> Option<PathBuf> {
+    // Fix paths that assume they're relative to cargo manifest dir
+    let mut base_c = base_dir.components();
+    let mut wanted_c = wanted_path.components();
+    let mut without_base = None;
+    while let Some(wanted_next) = wanted_c.next() {
+        if wanted_c.as_path().file_name().is_none() {
+            break;
         }
+        // base_dir may be absolute
+        while let Some(base_next) = base_c.next() {
+            if base_next == wanted_next {
+                without_base = Some(wanted_c.as_path());
+                break;
+            }
+        }
+    }
+    let root_absolute = without_base.into_iter().map(PathBuf::from);
+
+    let base_dir_components = base_dir.components().count();
+    // Avoid going all the way to the root dir
+    let max_parent_components = if base_dir.is_relative() {
+        base_dir_components + 1
+    } else {
+        base_dir_components.saturating_sub(1)
+    };
+
+    // Try with additional leading ../
+    let mut prefix = PathBuf::new();
+    let add = std::iter::from_fn(|| {
+        prefix.push("..");
+        Some(prefix.join(wanted_path))
     })
+    .take(max_parent_components.min(3));
+
+    // Try without leading directories
+    let mut trimmed_path = wanted_path;
+    let remove = std::iter::from_fn(|| {
+        let mut components = trimmed_path.components();
+        let removed = components.next()?;
+        trimmed_path = components.as_path();
+        let _ = trimmed_path.file_name()?; // ensure there is a file name left
+        Some([
+            Some(trimmed_path.to_path_buf()),
+            (removed != std::path::Component::ParentDir)
+                .then(|| Path::new("..").join(trimmed_path)),
+        ])
+    })
+    .flatten()
+    .flatten()
+    .take(4);
+
+    for new_path in root_absolute.chain(add).chain(remove) {
+        if source_map.file_exists(&base_dir.join(&new_path)) {
+            return Some(new_path);
+        }
+    }
+    None
 }
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index e308cf80284..8fdc1941de8 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9515fcc42b6cb5137f76b84c1a6f819782d0cf12473d145d3bc5cd67eedc8bc2"
+checksum = "6a535eb1cf5a6003197dc569320c40c1cb2d2f97ef5d5348eebf067f20957381"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad827c6071bfe6d22de1bc331296a29f9ddc506ff926d8415b435ec6a6efce0"
+checksum = "11b5066db32cec1492573827183af2142d2d88fe85a83cfc9e73f0f63d3788d4"
 dependencies = [
  "bumpalo",
  "cranelift-bforest",
@@ -76,39 +76,39 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10e6b36237a9ca2ce2fb4cc7741d418a080afa1327402138412ef85d5367bef1"
+checksum = "64942e5774308e835fbad4dd25f253105412c90324631910e1ec27963147bddb"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c36bf4bfb86898a94ccfa773a1f86e8a5346b1983ff72059bdd2db4600325251"
+checksum = "c39c33db9a86dd6d8d04166a10c53deb477aeea3500eaaefca682e4eda9bb986"
 
 [[package]]
 name = "cranelift-control"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cbf36560e7a6bd1409ca91e7b43b2cc7ed8429f343d7605eadf9046e8fac0d0"
+checksum = "4b7fc4937613aea3156a0538800a17bf56f345a5da2e79ae3df58488c93d867f"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a71e11061a75b1184c09bea97c026a88f08b59ade96a7bb1f259d4ea0df2e942"
+checksum = "f85575e79a153ce1ddbfb7fe1813519b4bfe1eb200cc9c8353b45ad123ae4d36"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af5d4da63143ee3485c7bcedde0a818727d737d1083484a0ceedb8950c89e495"
+checksum = "bbc31d6c0ab2249fe0c21e988256b42f5f401ab2673b4fc40076c82a698bdfb9"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -118,15 +118,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "457a9832b089e26f5eea70dcf49bed8ec6edafed630ce7c83161f24d46ab8085"
+checksum = "dc14f37e3314c0e4c53779c2f46753bf242efff76ee9473757a1fff3b495ad37"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0af95fe68d5a10919012c8db82b1d59820405b8001c8c6d05f94b08031334fa9"
+checksum = "cfdd1942f3233176a68c285380dbc84ff0440246a1bce308611c0a385b56ab18"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -144,9 +144,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11b0b201fa10a4014062d4c56c307c8d18fdf9a84cb5279efe6080241f42c7a7"
+checksum = "121b2b5a16912554a1b9aace75b9b21eca49f28e33cbfbad4786dd9bc5361a5c"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -155,9 +155,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b490d579df1ce365e1ea359e24ed86d82289fa785153327c2f6a69a59a731e4"
+checksum = "2ea5375f76ab31f9800a23fb2b440810286a6f669a3eb467cdd7ff255ea64268"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -166,9 +166,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.105.2"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb7e821ac6db471bcdbd004e5a4fa0d374f1046bd3a2ce278c332e0b0c01ca63"
+checksum = "f34e04419ab41661e973d90a73aa7b12771455394dae7a69b101a9b7e7589db7"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -392,9 +392,9 @@ dependencies = [
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.12"
+version = "0.12.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
+checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
 
 [[package]]
 name = "unicode-ident"
@@ -410,9 +410,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "18.0.2"
+version = "19.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33f4121cb29dda08139b2824a734dd095d83ce843f2d613a84eb580b9cfc17ac"
+checksum = "2796e4b4989db62899d2117e1e0258b839d088c044591b14e3a0396e7b3ae53a"
 dependencies = [
  "cfg-if",
  "libc",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index c0b9e27b179..d8a855b0383 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.105.2", default-features = false, features = ["std", "unwind", "all-arch"] }
-cranelift-frontend = { version = "0.105.2" }
-cranelift-module = { version = "0.105.2" }
-cranelift-native = { version = "0.105.2" }
-cranelift-jit = { version = "0.105.2", optional = true }
-cranelift-object = { version = "0.105.2" }
+cranelift-codegen = { version = "0.106.0", default-features = false, features = ["std", "unwind", "all-arch"] }
+cranelift-frontend = { version = "0.106.0" }
+cranelift-module = { version = "0.106.0" }
+cranelift-native = { version = "0.106.0" }
+cranelift-jit = { version = "0.106.0", optional = true }
+cranelift-object = { version = "0.106.0" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.28", default-features = false, features = ["write"]}
 object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
index 5442c3cef9e..7cf7f86700e 100644
--- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
@@ -39,6 +39,6 @@ index 42a26ae..5ac1042 100644
 +#![cfg(test)]
  #![feature(alloc_layout_extra)]
  #![feature(array_chunks)]
- #![feature(array_windows)]
+ #![feature(array_ptr_get)]
 --
 2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index f3cd4cbe493..612fc61ec27 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-03-16"
+channel = "nightly-2024-03-28"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
index 550f2051553..92defd21cd9 100644
--- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
@@ -26,9 +26,10 @@ fn main() {
         codegen_backend_arg.push(cg_clif_dylib_path);
         args.push(codegen_backend_arg);
     }
-    if !passed_args.iter().any(|arg| {
-        arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot="))
-    }) {
+    if !passed_args
+        .iter()
+        .any(|arg| arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot=")))
+    {
         args.push(OsString::from("--sysroot"));
         args.push(OsString::from(sysroot.to_str().unwrap()));
     }
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
index f7d1bdbc4c6..1cad312bb79 100644
--- a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
@@ -26,12 +26,18 @@ fn main() {
         codegen_backend_arg.push(cg_clif_dylib_path);
         args.push(codegen_backend_arg);
     }
-    if !passed_args.iter().any(|arg| {
-        arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot="))
-    }) {
+    if !passed_args
+        .iter()
+        .any(|arg| arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot=")))
+    {
         args.push(OsString::from("--sysroot"));
         args.push(OsString::from(sysroot.to_str().unwrap()));
     }
+    if passed_args.is_empty() {
+        // Don't pass any arguments when the user didn't pass any arguments
+        // either to ensure the help message is shown.
+        args.clear();
+    }
     args.extend(passed_args);
 
     let rustdoc = if let Some(rustdoc) = option_env!("RUSTDOC") {
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index f4e10f7dd19..f42a008dc0c 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -10,14 +10,6 @@ pushd rust
 
 command -v rg >/dev/null 2>&1 || cargo install ripgrep
 
-# FIXME(rust-lang/rust#122196) fix stage0 rmake.rs run-make tests and remove
-# this workaround
-for test in $(ls tests/run-make); do
-  if [[ -e "tests/run-make/$test/rmake.rs" ]]; then
-    rm -r "tests/run-make/$test"
-  fi
-done
-
 # FIXME remove this workaround once ICE tests no longer emit an outdated nightly message
 for test in $(rg -i --files-with-matches "//@(\[.*\])? failure-status: 101" tests/ui); do
   echo "rm $test"
@@ -42,7 +34,6 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
 # ================
 
 # vendor intrinsics
-rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
 rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
 
 # exotic linkages
@@ -59,12 +50,9 @@ rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg sup
 rm -r tests/run-pass-valgrind/unsized-locals
 
 # misc unimplemented things
-rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and nearbyintf64 intrinsics
 rm tests/ui/target-feature/missing-plusminus.rs # error not implemented
-rm -r tests/run-make/emit-named-files # requires full --emit support
 rm -r tests/run-make/repr128-dwarf # debuginfo test
 rm -r tests/run-make/split-debuginfo # same
-rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
 rm -r tests/run-make/target-specs # i686 not supported by Cranelift
 rm -r tests/run-make/mismatching-target-triples # same
 rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly
@@ -102,6 +90,17 @@ rm tests/ui/abi/stack-protector.rs # requires stack protector support
 rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
 rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
 
+# requires asm, llvm-ir and/or llvm-bc emit support
+# =============================================
+rm -r tests/run-make/emit-named-files
+rm -r tests/run-make/issue-30063
+rm -r tests/run-make/multiple-emits
+rm -r tests/run-make/output-type-permutations
+rm -r tests/run-make/emit-to-stdout
+rm -r tests/run-make/compressed-debuginfo
+rm -r tests/run-make/symbols-include-type-name
+
+
 # giving different but possibly correct results
 # =============================================
 rm tests/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
@@ -109,35 +108,21 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same
 rm tests/ui/consts/issue-33537.rs # same
 rm tests/ui/consts/const-mut-refs-crate.rs # same
 
-# rustdoc-clif passes extra args, suppressing the help message when no args are passed
-rm -r tests/run-make/issue-88756-default-output
-
 # doesn't work due to the way the rustc test suite is invoked.
 # should work when using ./x.py test the way it is intended
 # ============================================================
 rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
+rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contains the standard library source
 
 # genuine bugs
 # ============
 rm tests/incremental/spike-neg1.rs # errors out for some reason
 rm tests/incremental/spike-neg2.rs # same
-
-rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj
-rm -r tests/run-make/issue-30063 # same
-rm -r tests/run-make/multiple-emits # same
-rm -r tests/run-make/output-type-permutations # same
-rm -r tests/run-make/used # same
-rm -r tests/run-make/no-alloc-shim
-rm -r tests/run-make/emit-to-stdout
-rm -r tests/run-make/compressed-debuginfo
-
 rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
-
-rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug with Coroutine's
+rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
 
 # bugs in the test suite
 # ======================
-rm tests/ui/backtrace.rs # TODO warning
 rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
 
 rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
@@ -160,6 +145,19 @@ index ea06b620c4c..b969d0009c6 100644
  ifdef RUSTC_LINKER
  RUSTC := \$(RUSTC) -Clinker='\$(RUSTC_LINKER)'
  RUSTDOC := \$(RUSTDOC) -Clinker='\$(RUSTC_LINKER)'
+diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
+index 9607ff02f96..b7d97caf9a2 100644
+--- a/src/tools/run-make-support/src/rustdoc.rs
++++ b/src/tools/run-make-support/src/rustdoc.rs
+@@ -34,8 +34,6 @@ pub fn bare() -> Self {
+     /// Construct a \`rustdoc\` invocation with \`-L \$(TARGET_RPATH_DIR)\` set.
+     pub fn new() -> Self {
+         let mut cmd = setup_common();
+-        let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
+-        cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
+         Self { cmd }
+     }
+
 EOF
 
 echo "[TEST] rustc test suite"
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index b0af421008a..6363a0d59a4 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -222,17 +222,15 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
         Spread(Vec<Option<CValue<'tcx>>>),
     }
 
-    let fn_abi = fx.fn_abi.take().unwrap();
-
     // FIXME implement variadics in cranelift
-    if fn_abi.c_variadic {
+    if fx.fn_abi.c_variadic {
         fx.tcx.dcx().span_fatal(
             fx.mir.span,
             "Defining variadic functions is not yet supported by Cranelift",
         );
     }
 
-    let mut arg_abis_iter = fn_abi.args.iter();
+    let mut arg_abis_iter = fx.fn_abi.args.iter();
 
     let func_params = fx
         .mir
@@ -279,7 +277,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
     }
 
     assert!(arg_abis_iter.next().is_none(), "ArgAbi left behind");
-    fx.fn_abi = Some(fn_abi);
     assert!(block_params_iter.next().is_none(), "arg_value left behind");
 
     self::comments::add_locals_header_comment(fx);
diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs
index 0799a22c6e1..e0f399e616e 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs
@@ -12,27 +12,15 @@ pub(super) fn codegen_return_param<'tcx>(
     ssa_analyzed: &rustc_index::IndexSlice<Local, crate::analyze::SsaKind>,
     block_params_iter: &mut impl Iterator<Item = Value>,
 ) -> CPlace<'tcx> {
-    let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode {
+    let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.ret.mode {
         PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => {
-            let is_ssa =
-                ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty);
-            (
-                super::make_local_place(
-                    fx,
-                    RETURN_PLACE,
-                    fx.fn_abi.as_ref().unwrap().ret.layout,
-                    is_ssa,
-                ),
-                smallvec![],
-            )
+            let is_ssa = ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.ret.layout.ty);
+            (super::make_local_place(fx, RETURN_PLACE, fx.fn_abi.ret.layout, is_ssa), smallvec![])
         }
         PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
             let ret_param = block_params_iter.next().unwrap();
             assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type);
-            (
-                CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.as_ref().unwrap().ret.layout),
-                smallvec![ret_param],
-            )
+            (CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.ret.layout), smallvec![ret_param])
         }
         PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
             unreachable!("unsized return value")
@@ -45,8 +33,8 @@ pub(super) fn codegen_return_param<'tcx>(
         Some(RETURN_PLACE),
         None,
         &ret_param,
-        &fx.fn_abi.as_ref().unwrap().ret.mode,
-        fx.fn_abi.as_ref().unwrap().ret.layout,
+        &fx.fn_abi.ret.mode,
+        fx.fn_abi.ret.layout,
     );
 
     ret_place
@@ -115,7 +103,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
 
 /// Codegen a return instruction with the right return value(s) if any.
 pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
-    match fx.fn_abi.as_ref().unwrap().ret.mode {
+    match fx.fn_abi.ret.mode {
         PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
             fx.bcx.ins().return_(&[]);
         }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index dbce6d165d2..b4ea4e10a3d 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
 
 use crate::constant::ConstantCx;
-use crate::debuginfo::FunctionDebugContext;
+use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
 use crate::prelude::*;
 use crate::pretty_clif::CommentWriter;
 
@@ -26,6 +26,7 @@ pub(crate) struct CodegenedFunction {
 pub(crate) fn codegen_fn<'tcx>(
     tcx: TyCtxt<'tcx>,
     cx: &mut crate::CodegenCx,
+    type_dbg: &mut TypeDebugContext<'tcx>,
     cached_func: Function,
     module: &mut dyn Module,
     instance: Instance<'tcx>,
@@ -69,8 +70,10 @@ pub(crate) fn codegen_fn<'tcx>(
     let pointer_type = target_config.pointer_type();
     let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);
 
+    let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty());
+
     let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
-        Some(debug_context.define_function(tcx, &symbol_name, mir.span))
+        Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span))
     } else {
         None
     };
@@ -87,7 +90,7 @@ pub(crate) fn codegen_fn<'tcx>(
         instance,
         symbol_name,
         mir,
-        fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())),
+        fn_abi,
 
         bcx,
         block_map,
@@ -95,7 +98,6 @@ pub(crate) fn codegen_fn<'tcx>(
         caller_location: None, // set by `codegen_fn_prelude`
 
         clif_comments,
-        last_source_file: None,
         next_ssa_var: 0,
     };
 
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index a7c3d68ff8c..cf0b065414d 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -1,12 +1,9 @@
 use cranelift_codegen::isa::TargetFrontendConfig;
-use gimli::write::FileId;
-use rustc_data_structures::sync::Lrc;
 use rustc_index::IndexVec;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
 };
 use rustc_span::source_map::Spanned;
-use rustc_span::SourceFile;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
 use rustc_target::spec::{HasTargetSpec, Target};
@@ -294,7 +291,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
     pub(crate) instance: Instance<'tcx>,
     pub(crate) symbol_name: String,
     pub(crate) mir: &'tcx Body<'tcx>,
-    pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
+    pub(crate) fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
 
     pub(crate) bcx: FunctionBuilder<'clif>,
     pub(crate) block_map: IndexVec<BasicBlock, Block>,
@@ -305,11 +302,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
 
     pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
 
-    /// Last accessed source file and it's debuginfo file id.
-    ///
-    /// For optimization purposes only
-    pub(crate) last_source_file: Option<(Lrc<SourceFile>, FileId)>,
-
     /// This should only be accessed by `CPlace::new_var`.
     pub(crate) next_ssa_var: u32,
 }
@@ -419,25 +411,8 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
 
     pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
         if let Some(debug_context) = &mut self.cx.debug_context {
-            let (file, line, column) =
-                DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span);
-
-            // add_source_file is very slow.
-            // Optimize for the common case of the current file not being changed.
-            let mut cached_file_id = None;
-            if let Some((ref last_source_file, last_file_id)) = self.last_source_file {
-                // If the allocations are not equal, the files may still be equal, but that
-                // doesn't matter, as this is just an optimization.
-                if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) {
-                    cached_file_id = Some(last_file_id);
-                }
-            }
-
-            let file_id = if let Some(file_id) = cached_file_id {
-                file_id
-            } else {
-                debug_context.add_source_file(&file)
-            };
+            let (file_id, line, column) =
+                debug_context.get_span_loc(self.tcx, self.mir.span, source_info.span);
 
             let source_loc =
                 self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column);
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index fc9b0f6ef02..635ed6c8e88 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -6,17 +6,16 @@ use cranelift_module::*;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{read_target_uint, AllocId, GlobalAlloc, Scalar};
-use rustc_middle::ty::ScalarInt;
+use rustc_middle::ty::{Binder, ExistentialTraitRef, ScalarInt};
 
 use crate::prelude::*;
 
 pub(crate) struct ConstantCx {
     todo: Vec<TodoItem>,
-    done: FxHashSet<DataId>,
     anon_allocs: FxHashMap<AllocId, DataId>,
 }
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 enum TodoItem {
     Alloc(AllocId),
     Static(DefId),
@@ -24,19 +23,24 @@ enum TodoItem {
 
 impl ConstantCx {
     pub(crate) fn new() -> Self {
-        ConstantCx { todo: vec![], done: FxHashSet::default(), anon_allocs: FxHashMap::default() }
+        ConstantCx { todo: vec![], anon_allocs: FxHashMap::default() }
     }
 
     pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
         define_all_allocs(tcx, module, &mut self);
-        self.done.clear();
     }
 }
 
-pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) {
+pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) -> DataId {
     let mut constants_cx = ConstantCx::new();
     constants_cx.todo.push(TodoItem::Static(def_id));
     constants_cx.finalize(tcx, module);
+
+    data_id_for_static(
+        tcx, module, def_id, false,
+        // For a declaration the stated mutability doesn't matter.
+        false,
+    )
 }
 
 pub(crate) fn codegen_tls_ref<'tcx>(
@@ -153,14 +157,12 @@ pub(crate) fn codegen_const_value<'tcx>(
                         fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
                     }
                     GlobalAlloc::VTable(ty, trait_ref) => {
-                        let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref));
-                        let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
-                        // FIXME: factor this common code with the `Memory` arm into a function?
-                        let data_id = data_id_for_alloc_id(
+                        let data_id = data_id_for_vtable(
+                            fx.tcx,
                             &mut fx.constants_cx,
                             fx.module,
-                            alloc_id,
-                            alloc.inner().mutability,
+                            ty,
+                            trait_ref,
                         );
                         let local_data_id =
                             fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
@@ -208,12 +210,8 @@ fn pointer_for_allocation<'tcx>(
     alloc_id: AllocId,
 ) -> crate::pointer::Pointer {
     let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
-    let data_id = data_id_for_alloc_id(
-        &mut fx.constants_cx,
-        &mut *fx.module,
-        alloc_id,
-        alloc.inner().mutability,
-    );
+    let data_id =
+        data_id_for_alloc_id(&mut fx.constants_cx, fx.module, alloc_id, alloc.inner().mutability);
 
     let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
     if fx.clif_comments.enabled() {
@@ -235,6 +233,17 @@ pub(crate) fn data_id_for_alloc_id(
         .or_insert_with(|| module.declare_anonymous_data(mutability.is_mut(), false).unwrap())
 }
 
+pub(crate) fn data_id_for_vtable<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cx: &mut ConstantCx,
+    module: &mut dyn Module,
+    ty: Ty<'tcx>,
+    trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
+) -> DataId {
+    let alloc_id = tcx.vtable_allocation((ty, trait_ref));
+    data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
+}
+
 fn data_id_for_static(
     tcx: TyCtxt<'_>,
     module: &mut dyn Module,
@@ -327,7 +336,12 @@ fn data_id_for_static(
 }
 
 fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
+    let mut done = FxHashSet::default();
     while let Some(todo_item) = cx.todo.pop() {
+        if !done.insert(todo_item) {
+            continue;
+        }
+
         let (data_id, alloc, section_name) = match todo_item {
             TodoItem::Alloc(alloc_id) => {
                 let alloc = match tcx.global_alloc(alloc_id) {
@@ -358,10 +372,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
             }
         };
 
-        if cx.done.contains(&data_id) {
-            continue;
-        }
-
         let mut data = DataDescription::new();
         let alloc = alloc.inner();
         data.set_align(alloc.align.bytes());
@@ -384,13 +394,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
         }
 
         let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec();
-        if bytes.is_empty() {
-            // FIXME(bytecodealliance/wasmtime#7918) cranelift-jit has a bug where it causes UB on
-            // empty data objects
-            data.define(Box::new([0]));
-        } else {
-            data.define(bytes.into_boxed_slice());
-        }
+        data.define(bytes.into_boxed_slice());
 
         for &(offset, prov) in alloc.provenance().ptrs().iter() {
             let alloc_id = prov.alloc_id();
@@ -418,8 +422,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                     data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability)
                 }
                 GlobalAlloc::VTable(ty, trait_ref) => {
-                    let alloc_id = tcx.vtable_allocation((ty, trait_ref));
-                    data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
+                    data_id_for_vtable(tcx, cx, module, ty, trait_ref)
                 }
                 GlobalAlloc::Static(def_id) => {
                     if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
@@ -446,7 +449,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
         }
 
         module.define_data(data_id, &data).unwrap();
-        cx.done.insert(data_id);
     }
 
     assert!(cx.todo.is_empty(), "{:?}", cx.todo);
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
index 81b819a5546..36af7d4450d 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
@@ -1,5 +1,6 @@
 //! Write the debuginfo into an object file.
 
+use cranelift_module::{DataId, FuncId};
 use cranelift_object::ObjectProduct;
 use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
 use gimli::{RunTimeEndian, SectionId};
@@ -8,6 +9,18 @@ use rustc_data_structures::fx::FxHashMap;
 use super::object::WriteDebugInfo;
 use super::DebugContext;
 
+pub(super) fn address_for_func(func_id: FuncId) -> Address {
+    let symbol = func_id.as_u32();
+    assert!(symbol & 1 << 31 == 0);
+    Address::Symbol { symbol: symbol as usize, addend: 0 }
+}
+
+pub(super) fn address_for_data(data_id: DataId) -> Address {
+    let symbol = data_id.as_u32();
+    assert!(symbol & 1 << 31 == 0);
+    Address::Symbol { symbol: (symbol | 1 << 31) as usize, addend: 0 }
+}
+
 impl DebugContext {
     pub(crate) fn emit(&mut self, product: &mut ObjectProduct) {
         let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
@@ -171,6 +184,7 @@ impl Writer for WriterRelocate {
                 gimli::DW_EH_PE_pcrel => {
                     let size = match eh_pe.format() {
                         gimli::DW_EH_PE_sdata4 => 4,
+                        gimli::DW_EH_PE_sdata8 => 8,
                         _ => return Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
                     };
                     self.relocs.push(DebugReloc {
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
index d1b21d0a0b6..380eba437c2 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
@@ -5,14 +5,12 @@ use std::path::{Component, Path};
 
 use cranelift_codegen::binemit::CodeOffset;
 use cranelift_codegen::MachSrcLoc;
-use gimli::write::{
-    Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,
-};
-use rustc_data_structures::sync::Lrc;
+use gimli::write::{AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable};
 use rustc_span::{
     FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
 };
 
+use crate::debuginfo::emit::address_for_func;
 use crate::debuginfo::FunctionDebugContext;
 use crate::prelude::*;
 
@@ -60,10 +58,11 @@ fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
 
 impl DebugContext {
     pub(crate) fn get_span_loc(
+        &mut self,
         tcx: TyCtxt<'_>,
         function_span: Span,
         span: Span,
-    ) -> (Lrc<SourceFile>, u64, u64) {
+    ) -> (FileId, u64, u64) {
         // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
         // In order to have a good line stepping behavior in debugger, we overwrite debug
         // locations of macro expansions with that of the outermost expansion site (when the macro is
@@ -71,61 +70,66 @@ impl DebugContext {
         let span = tcx.collapsed_debuginfo(span, function_span);
         match tcx.sess.source_map().lookup_line(span.lo()) {
             Ok(SourceFileAndLine { sf: file, line }) => {
+                let file_id = self.add_source_file(&file);
                 let line_pos = file.lines()[line];
                 let col = file.relative_position(span.lo()) - line_pos;
 
-                (file, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
+                (file_id, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
             }
-            Err(file) => (file, 0, 0),
+            Err(file) => (self.add_source_file(&file), 0, 0),
         }
     }
 
     pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId {
-        let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
-        let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
-
-        match &source_file.name {
-            FileName::Real(path) => {
-                let (dir_path, file_name) =
-                    split_path_dir_and_file(if self.should_remap_filepaths {
-                        path.remapped_path_if_available()
-                    } else {
-                        path.local_path_if_available()
-                    });
-                let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
-                let file_name = osstr_as_utf8_bytes(file_name);
-
-                let dir_id = if !dir_name.is_empty() {
-                    let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings);
-                    line_program.add_directory(dir_name)
-                } else {
-                    line_program.default_directory()
-                };
-                let file_name = LineString::new(file_name, line_program.encoding(), line_strings);
-
-                let info = make_file_info(source_file.src_hash);
-
-                line_program.file_has_md5 &= info.is_some();
-                line_program.add_file(file_name, dir_id, info)
-            }
-            // FIXME give more appropriate file names
-            filename => {
-                let dir_id = line_program.default_directory();
-                let dummy_file_name = LineString::new(
-                    filename
-                        .display(if self.should_remap_filepaths {
-                            FileNameDisplayPreference::Remapped
+        let cache_key = (source_file.stable_id, source_file.src_hash);
+        *self.created_files.entry(cache_key).or_insert_with(|| {
+            let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
+            let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
+
+            match &source_file.name {
+                FileName::Real(path) => {
+                    let (dir_path, file_name) =
+                        split_path_dir_and_file(if self.should_remap_filepaths {
+                            path.remapped_path_if_available()
                         } else {
-                            FileNameDisplayPreference::Local
-                        })
-                        .to_string()
-                        .into_bytes(),
-                    line_program.encoding(),
-                    line_strings,
-                );
-                line_program.add_file(dummy_file_name, dir_id, None)
+                            path.local_path_if_available()
+                        });
+                    let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
+                    let file_name = osstr_as_utf8_bytes(file_name);
+
+                    let dir_id = if !dir_name.is_empty() {
+                        let dir_name =
+                            LineString::new(dir_name, line_program.encoding(), line_strings);
+                        line_program.add_directory(dir_name)
+                    } else {
+                        line_program.default_directory()
+                    };
+                    let file_name =
+                        LineString::new(file_name, line_program.encoding(), line_strings);
+
+                    let info = make_file_info(source_file.src_hash);
+
+                    line_program.file_has_md5 &= info.is_some();
+                    line_program.add_file(file_name, dir_id, info)
+                }
+                filename => {
+                    let dir_id = line_program.default_directory();
+                    let dummy_file_name = LineString::new(
+                        filename
+                            .display(if self.should_remap_filepaths {
+                                FileNameDisplayPreference::Remapped
+                            } else {
+                                FileNameDisplayPreference::Local
+                            })
+                            .to_string()
+                            .into_bytes(),
+                        line_program.encoding(),
+                        line_strings,
+                    );
+                    line_program.add_file(dummy_file_name, dir_id, None)
+                }
             }
-        }
+        })
     }
 }
 
@@ -138,7 +142,7 @@ impl FunctionDebugContext {
     pub(super) fn create_debug_lines(
         &mut self,
         debug_context: &mut DebugContext,
-        symbol: usize,
+        func_id: FuncId,
         context: &Context,
     ) -> CodeOffset {
         let create_row_for_span =
@@ -151,11 +155,7 @@ impl FunctionDebugContext {
                 debug_context.dwarf.unit.line_program.generate_row();
             };
 
-        debug_context
-            .dwarf
-            .unit
-            .line_program
-            .begin_sequence(Some(Address::Symbol { symbol, addend: 0 }));
+        debug_context.dwarf.unit.line_program.begin_sequence(Some(address_for_func(func_id)));
 
         let mut func_end = 0;
 
@@ -178,10 +178,7 @@ impl FunctionDebugContext {
         assert_ne!(func_end, 0);
 
         let entry = debug_context.dwarf.unit.get_mut(self.entry_id);
-        entry.set(
-            gimli::DW_AT_low_pc,
-            AttributeValue::Address(Address::Symbol { symbol, addend: 0 }),
-        );
+        entry.set(gimli::DW_AT_low_pc, AttributeValue::Address(address_for_func(func_id)));
         entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(func_end)));
 
         func_end
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index 2d9c2ecdbc2..1bb0e590513 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -3,20 +3,29 @@
 mod emit;
 mod line_info;
 mod object;
+mod types;
 mod unwind;
 
 use cranelift_codegen::ir::Endianness;
 use cranelift_codegen::isa::TargetIsa;
+use cranelift_module::DataId;
 use gimli::write::{
-    Address, AttributeValue, DwarfUnit, FileId, LineProgram, LineString, Range, RangeList,
-    UnitEntryId,
+    Address, AttributeValue, DwarfUnit, Expression, FileId, LineProgram, LineString, Range,
+    RangeList, UnitEntryId,
 };
-use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
+use gimli::{AArch64, Encoding, Format, LineEncoding, Register, RiscV, RunTimeEndian, X86_64};
 use indexmap::IndexSet;
+use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefIdMap;
 use rustc_session::Session;
+use rustc_span::{SourceFileHash, StableSourceFileId};
+use rustc_target::abi::call::FnAbi;
 
 pub(crate) use self::emit::{DebugReloc, DebugRelocName};
+pub(crate) use self::types::TypeDebugContext;
 pub(crate) use self::unwind::UnwindContext;
+use crate::debuginfo::emit::{address_for_data, address_for_func};
 use crate::prelude::*;
 
 pub(crate) fn producer(sess: &Session) -> String {
@@ -28,6 +37,10 @@ pub(crate) struct DebugContext {
 
     dwarf: DwarfUnit,
     unit_range_list: RangeList,
+    created_files: FxHashMap<(StableSourceFileId, SourceFileHash), FileId>,
+    stack_pointer_register: Register,
+    namespace_map: DefIdMap<UnitEntryId>,
+    array_size_type: UnitEntryId,
 
     should_remap_filepaths: bool,
 }
@@ -39,7 +52,7 @@ pub(crate) struct FunctionDebugContext {
 }
 
 impl DebugContext {
-    pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa) -> Self {
+    pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, cgu_name: &str) -> Self {
         let encoding = Encoding {
             format: Format::Dwarf32,
             // FIXME this should be configurable
@@ -60,6 +73,15 @@ impl DebugContext {
             Endianness::Big => RunTimeEndian::Big,
         };
 
+        let stack_pointer_register = match isa.triple().architecture {
+            target_lexicon::Architecture::Aarch64(_) => AArch64::SP,
+            target_lexicon::Architecture::Riscv64(_) => RiscV::SP,
+            target_lexicon::Architecture::X86_64 | target_lexicon::Architecture::X86_64h => {
+                X86_64::RSP
+            }
+            _ => Register(u16::MAX),
+        };
+
         let mut dwarf = DwarfUnit::new(encoding);
 
         let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen();
@@ -95,7 +117,7 @@ impl DebugContext {
         dwarf.unit.line_program = line_program;
 
         {
-            let name = dwarf.strings.add(name);
+            let name = dwarf.strings.add(format!("{name}/@/{cgu_name}"));
             let comp_dir = dwarf.strings.add(comp_dir);
 
             let root = dwarf.unit.root();
@@ -103,41 +125,134 @@ impl DebugContext {
             root.set(gimli::DW_AT_producer, AttributeValue::StringRef(dwarf.strings.add(producer)));
             root.set(gimli::DW_AT_language, AttributeValue::Language(gimli::DW_LANG_Rust));
             root.set(gimli::DW_AT_name, AttributeValue::StringRef(name));
+
+            // This will be replaced when emitting the debuginfo. It is only
+            // defined here to ensure that the order of the attributes matches
+            // rustc.
+            root.set(gimli::DW_AT_stmt_list, AttributeValue::Udata(0));
+
             root.set(gimli::DW_AT_comp_dir, AttributeValue::StringRef(comp_dir));
             root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0)));
         }
 
+        let array_size_type = dwarf.unit.add(dwarf.unit.root(), gimli::DW_TAG_base_type);
+        let array_size_type_entry = dwarf.unit.get_mut(array_size_type);
+        array_size_type_entry.set(
+            gimli::DW_AT_name,
+            AttributeValue::StringRef(dwarf.strings.add("__ARRAY_SIZE_TYPE__")),
+        );
+        array_size_type_entry
+            .set(gimli::DW_AT_encoding, AttributeValue::Encoding(gimli::DW_ATE_unsigned));
+        array_size_type_entry.set(
+            gimli::DW_AT_byte_size,
+            AttributeValue::Udata(isa.frontend_config().pointer_bytes().into()),
+        );
+
         DebugContext {
             endian,
             dwarf,
             unit_range_list: RangeList(Vec::new()),
+            created_files: FxHashMap::default(),
+            stack_pointer_register,
+            namespace_map: DefIdMap::default(),
+            array_size_type,
             should_remap_filepaths,
         }
     }
 
-    pub(crate) fn define_function(
+    fn item_namespace(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> UnitEntryId {
+        if let Some(&scope) = self.namespace_map.get(&def_id) {
+            return scope;
+        }
+
+        let def_key = tcx.def_key(def_id);
+        let parent_scope = def_key
+            .parent
+            .map(|parent| self.item_namespace(tcx, DefId { krate: def_id.krate, index: parent }))
+            .unwrap_or(self.dwarf.unit.root());
+
+        let namespace_name = {
+            let mut output = String::new();
+            type_names::push_item_name(tcx, def_id, false, &mut output);
+            output
+        };
+        let namespace_name_id = self.dwarf.strings.add(namespace_name);
+
+        let scope = self.dwarf.unit.add(parent_scope, gimli::DW_TAG_namespace);
+        let scope_entry = self.dwarf.unit.get_mut(scope);
+        scope_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(namespace_name_id));
+
+        self.namespace_map.insert(def_id, scope);
+        scope
+    }
+
+    pub(crate) fn define_function<'tcx>(
         &mut self,
-        tcx: TyCtxt<'_>,
-        name: &str,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        instance: Instance<'tcx>,
+        fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
+        linkage_name: &str,
         function_span: Span,
     ) -> FunctionDebugContext {
-        let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span);
+        let (file_id, line, column) = self.get_span_loc(tcx, function_span, function_span);
+
+        let scope = self.item_namespace(tcx, tcx.parent(instance.def_id()));
+
+        let mut name = String::new();
+        type_names::push_item_name(tcx, instance.def_id(), false, &mut name);
 
-        let file_id = self.add_source_file(&file);
+        // Find the enclosing function, in case this is a closure.
+        let enclosing_fn_def_id = tcx.typeck_root_def_id(instance.def_id());
 
-        // FIXME: add to appropriate scope instead of root
-        let scope = self.dwarf.unit.root();
+        // We look up the generics of the enclosing function and truncate the args
+        // to their length in order to cut off extra stuff that might be in there for
+        // closures or coroutines.
+        let generics = tcx.generics_of(enclosing_fn_def_id);
+        let args = instance.args.truncate_to(tcx, generics);
+
+        type_names::push_generic_params(
+            tcx,
+            tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
+            enclosing_fn_def_id,
+            &mut name,
+        );
 
         let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_subprogram);
         let entry = self.dwarf.unit.get_mut(entry_id);
+        let linkage_name_id =
+            if name != linkage_name { Some(self.dwarf.strings.add(linkage_name)) } else { None };
         let name_id = self.dwarf.strings.add(name);
+
+        // These will be replaced in FunctionDebugContext::finalize. They are
+        // only defined here to ensure that the order of the attributes matches
+        // rustc.
+        entry.set(gimli::DW_AT_low_pc, AttributeValue::Udata(0));
+        entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(0));
+
+        let mut frame_base_expr = Expression::new();
+        frame_base_expr.op_reg(self.stack_pointer_register);
+        entry.set(gimli::DW_AT_frame_base, AttributeValue::Exprloc(frame_base_expr));
+
+        if let Some(linkage_name_id) = linkage_name_id {
+            entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
+        }
         // Gdb requires DW_AT_name. Otherwise the DW_TAG_subprogram is skipped.
         entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
-        entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id));
 
         entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
         entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
-        entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column));
+
+        if !fn_abi.ret.is_ignore() {
+            let return_dw_ty = self.debug_type(tcx, type_dbg, fn_abi.ret.layout.ty);
+            let entry = self.dwarf.unit.get_mut(entry_id);
+            entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(return_dw_ty));
+        }
+
+        if tcx.is_reachable_non_generic(instance.def_id()) {
+            let entry = self.dwarf.unit.get_mut(entry_id);
+            entry.set(gimli::DW_AT_external, AttributeValue::FlagPresent);
+        }
 
         FunctionDebugContext {
             entry_id,
@@ -145,6 +260,62 @@ impl DebugContext {
             source_loc_set: IndexSet::new(),
         }
     }
+
+    // Adapted from https://github.com/rust-lang/rust/blob/10a7aa14fed9b528b74b0f098c4899c37c09a9c7/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs#L1288-L1346
+    pub(crate) fn define_static<'tcx>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        def_id: DefId,
+        data_id: DataId,
+    ) {
+        let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
+        if nested {
+            return;
+        }
+
+        let scope = self.item_namespace(tcx, tcx.parent(def_id));
+
+        let span = tcx.def_span(def_id);
+        let (file_id, line, _column) = self.get_span_loc(tcx, span, span);
+
+        let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::ParamEnv::reveal_all());
+        let static_layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(static_type)).unwrap();
+        // FIXME use the actual type layout
+        let type_id = self.debug_type(tcx, type_dbg, static_type);
+
+        let name = tcx.item_name(def_id);
+        let linkage_name = tcx.symbol_name(Instance::mono(tcx, def_id)).name;
+
+        let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_variable);
+        let entry = self.dwarf.unit.get_mut(entry_id);
+        let linkage_name_id = if name.as_str() != linkage_name {
+            Some(self.dwarf.strings.add(linkage_name))
+        } else {
+            None
+        };
+        let name_id = self.dwarf.strings.add(name.as_str());
+
+        entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
+        entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(type_id));
+
+        if tcx.is_reachable_non_generic(def_id) {
+            entry.set(gimli::DW_AT_external, AttributeValue::FlagPresent);
+        }
+
+        entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
+        entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
+
+        entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.pref.bytes()));
+
+        let mut expr = Expression::new();
+        expr.op_addr(address_for_data(data_id));
+        entry.set(gimli::DW_AT_location, AttributeValue::Exprloc(expr));
+
+        if let Some(linkage_name_id) = linkage_name_id {
+            entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
+        }
+    }
 }
 
 impl FunctionDebugContext {
@@ -154,21 +325,16 @@ impl FunctionDebugContext {
         func_id: FuncId,
         context: &Context,
     ) {
-        let symbol = func_id.as_u32() as usize;
-
-        let end = self.create_debug_lines(debug_context, symbol, context);
+        let end = self.create_debug_lines(debug_context, func_id, context);
 
-        debug_context.unit_range_list.0.push(Range::StartLength {
-            begin: Address::Symbol { symbol, addend: 0 },
-            length: u64::from(end),
-        });
+        debug_context
+            .unit_range_list
+            .0
+            .push(Range::StartLength { begin: address_for_func(func_id), length: u64::from(end) });
 
         let func_entry = debug_context.dwarf.unit.get_mut(self.entry_id);
         // Gdb requires both DW_AT_low_pc and DW_AT_high_pc. Otherwise the DW_TAG_subprogram is skipped.
-        func_entry.set(
-            gimli::DW_AT_low_pc,
-            AttributeValue::Address(Address::Symbol { symbol, addend: 0 }),
-        );
+        func_entry.set(gimli::DW_AT_low_pc, AttributeValue::Address(address_for_func(func_id)));
         // Using Udata for DW_AT_high_pc requires at least DWARF4
         func_entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(end)));
     }
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
index f1840a7bf73..27eabd8a0a6 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
@@ -1,4 +1,4 @@
-use cranelift_module::FuncId;
+use cranelift_module::{DataId, FuncId};
 use cranelift_object::ObjectProduct;
 use gimli::SectionId;
 use object::write::{Relocation, StandardSegment};
@@ -57,10 +57,13 @@ impl WriteDebugInfo for ObjectProduct {
         let (symbol, symbol_offset) = match reloc.name {
             DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
             DebugRelocName::Symbol(id) => {
-                let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
-                self.object
-                    .symbol_section_and_offset(symbol_id)
-                    .expect("Debug reloc for undef sym???")
+                let id = id.try_into().unwrap();
+                let symbol_id = if id & 1 << 31 == 0 {
+                    self.function_symbol(FuncId::from_u32(id))
+                } else {
+                    self.data_symbol(DataId::from_u32(id & !(1 << 31)))
+                };
+                self.object.symbol_section_and_offset(symbol_id).unwrap_or((symbol_id, 0))
             }
         };
         self.object
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
new file mode 100644
index 00000000000..7baf0a3868d
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
@@ -0,0 +1,204 @@
+// Adapted from https://github.com/rust-lang/rust/blob/10a7aa14fed9b528b74b0f098c4899c37c09a9c7/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+
+use gimli::write::{AttributeValue, UnitEntryId};
+use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+use crate::{has_ptr_meta, DebugContext, RevealAllLayoutCx};
+
+#[derive(Default)]
+pub(crate) struct TypeDebugContext<'tcx> {
+    type_map: FxHashMap<Ty<'tcx>, UnitEntryId>,
+}
+
+/// Returns from the enclosing function if the type debuginfo node with the given
+/// unique ID can be found in the type map.
+macro_rules! return_if_type_created_in_meantime {
+    ($type_dbg:expr, $ty:expr) => {
+        if let Some(&type_id) = $type_dbg.type_map.get(&$ty) {
+            return type_id;
+        }
+    };
+}
+
+impl DebugContext {
+    pub(crate) fn debug_type<'tcx>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> UnitEntryId {
+        if let Some(&type_id) = type_dbg.type_map.get(&ty) {
+            return type_id;
+        }
+
+        let type_id = match ty.kind() {
+            ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
+                self.basic_type(tcx, ty)
+            }
+            ty::Tuple(elems) if elems.is_empty() => self.basic_type(tcx, ty),
+            ty::Array(elem_ty, len) => self.array_type(
+                tcx,
+                type_dbg,
+                ty,
+                *elem_ty,
+                len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
+            ),
+            // ty::Slice(_) | ty::Str
+            // ty::Dynamic
+            // ty::Foreign
+            ty::RawPtr(pointee_type, _) | ty::Ref(_, pointee_type, _) => {
+                self.pointer_type(tcx, type_dbg, ty, *pointee_type)
+            }
+            // ty::Adt(def, args) if def.is_box() && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst())
+            // ty::FnDef(..) | ty::FnPtr(..)
+            // ty::Closure(..)
+            // ty::Adt(def, ..)
+            ty::Tuple(components) => self.tuple_type(tcx, type_dbg, ty, *components),
+            // ty::Param(_)
+            // FIXME implement remaining types and add unreachable!() to the fallback branch
+            _ => self.placeholder_for_type(tcx, type_dbg, ty),
+        };
+
+        type_dbg.type_map.insert(ty, type_id);
+
+        type_id
+    }
+
+    fn basic_type<'tcx>(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> UnitEntryId {
+        let (name, encoding) = match ty.kind() {
+            ty::Never => ("!", gimli::DW_ATE_unsigned),
+            ty::Tuple(elems) if elems.is_empty() => ("()", gimli::DW_ATE_unsigned),
+            ty::Bool => ("bool", gimli::DW_ATE_boolean),
+            ty::Char => ("char", gimli::DW_ATE_UTF),
+            ty::Int(int_ty) => (int_ty.name_str(), gimli::DW_ATE_signed),
+            ty::Uint(uint_ty) => (uint_ty.name_str(), gimli::DW_ATE_unsigned),
+            ty::Float(float_ty) => (float_ty.name_str(), gimli::DW_ATE_float),
+            _ => unreachable!(),
+        };
+
+        let type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_base_type);
+        let type_entry = self.dwarf.unit.get_mut(type_id);
+        type_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
+        type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(encoding));
+        type_entry.set(
+            gimli::DW_AT_byte_size,
+            AttributeValue::Udata(RevealAllLayoutCx(tcx).layout_of(ty).size.bytes()),
+        );
+
+        type_id
+    }
+
+    fn array_type<'tcx>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        array_ty: Ty<'tcx>,
+        elem_ty: Ty<'tcx>,
+        len: u64,
+    ) -> UnitEntryId {
+        let elem_dw_ty = self.debug_type(tcx, type_dbg, elem_ty);
+
+        return_if_type_created_in_meantime!(type_dbg, array_ty);
+
+        let array_type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_array_type);
+        let array_type_entry = self.dwarf.unit.get_mut(array_type_id);
+        array_type_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(elem_dw_ty));
+
+        let subrange_id = self.dwarf.unit.add(array_type_id, gimli::DW_TAG_subrange_type);
+        let subrange_entry = self.dwarf.unit.get_mut(subrange_id);
+        subrange_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(self.array_size_type));
+        subrange_entry.set(gimli::DW_AT_lower_bound, AttributeValue::Udata(0));
+        subrange_entry.set(gimli::DW_AT_count, AttributeValue::Udata(len));
+
+        array_type_id
+    }
+
+    fn pointer_type<'tcx>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        ptr_type: Ty<'tcx>,
+        pointee_type: Ty<'tcx>,
+    ) -> UnitEntryId {
+        let pointee_dw_ty = self.debug_type(tcx, type_dbg, pointee_type);
+
+        return_if_type_created_in_meantime!(type_dbg, ptr_type);
+
+        let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true);
+
+        if !has_ptr_meta(tcx, ptr_type) {
+            let pointer_type_id =
+                self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type);
+            let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id);
+            pointer_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(pointee_dw_ty));
+            pointer_entry
+                .set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
+
+            pointer_type_id
+        } else {
+            // FIXME implement debuginfo for fat pointers
+            self.placeholder_for_type(tcx, type_dbg, ptr_type)
+        }
+    }
+
+    fn tuple_type<'tcx>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        tuple_type: Ty<'tcx>,
+        components: &'tcx [Ty<'tcx>],
+    ) -> UnitEntryId {
+        let components = components
+            .into_iter()
+            .map(|&ty| (ty, self.debug_type(tcx, type_dbg, ty)))
+            .collect::<Vec<_>>();
+
+        return_if_type_created_in_meantime!(type_dbg, tuple_type);
+
+        let name = type_names::compute_debuginfo_type_name(tcx, tuple_type, false);
+        let layout = RevealAllLayoutCx(tcx).layout_of(tuple_type);
+
+        let tuple_type_id =
+            self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_structure_type);
+        let tuple_entry = self.dwarf.unit.get_mut(tuple_type_id);
+        tuple_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
+        tuple_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes()));
+        tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.pref.bytes()));
+
+        for (i, (ty, dw_ty)) in components.into_iter().enumerate() {
+            let member_id = self.dwarf.unit.add(tuple_type_id, gimli::DW_TAG_member);
+            let member_entry = self.dwarf.unit.get_mut(member_id);
+            member_entry.set(
+                gimli::DW_AT_name,
+                AttributeValue::StringRef(self.dwarf.strings.add(format!("__{i}"))),
+            );
+            member_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(dw_ty));
+            member_entry.set(
+                gimli::DW_AT_alignment,
+                AttributeValue::Udata(RevealAllLayoutCx(tcx).layout_of(ty).align.pref.bytes()),
+            );
+            member_entry.set(
+                gimli::DW_AT_data_member_location,
+                AttributeValue::Udata(layout.fields.offset(i).bytes()),
+            );
+        }
+
+        tuple_type_id
+    }
+
+    fn placeholder_for_type<'tcx>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        type_dbg: &mut TypeDebugContext<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> UnitEntryId {
+        self.debug_type(
+            tcx,
+            type_dbg,
+            Ty::new_array(tcx, tcx.types.u8, RevealAllLayoutCx(tcx).layout_of(ty).size.bytes()),
+        )
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
index 35278e6fb29..96ab7a29205 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
@@ -3,9 +3,10 @@
 use cranelift_codegen::ir::Endianness;
 use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa};
 use cranelift_object::ObjectProduct;
-use gimli::write::{Address, CieId, EhFrame, FrameTable, Section};
+use gimli::write::{CieId, EhFrame, FrameTable, Section};
 use gimli::RunTimeEndian;
 
+use super::emit::address_for_func;
 use super::object::WriteDebugInfo;
 use crate::prelude::*;
 
@@ -47,11 +48,8 @@ impl UnwindContext {
 
         match unwind_info {
             UnwindInfo::SystemV(unwind_info) => {
-                self.frame_table.add_fde(
-                    self.cie_id.unwrap(),
-                    unwind_info
-                        .to_fde(Address::Symbol { symbol: func_id.as_u32() as usize, addend: 0 }),
-                );
+                self.frame_table
+                    .add_fde(self.cie_id.unwrap(), unwind_info.to_fde(address_for_func(func_id)));
             }
             UnwindInfo::WindowsX64(_) => {
                 // FIXME implement this
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 757082a5fed..75268341a4f 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -1,25 +1,29 @@
 //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
 //! standalone executable.
 
-use std::fs::File;
-use std::path::PathBuf;
+use std::fs::{self, File};
+use std::path::{Path, PathBuf};
 use std::sync::Arc;
 use std::thread::JoinHandle;
 
 use cranelift_object::{ObjectBuilder, ObjectModule};
 use rustc_codegen_ssa::assert_module_sources::CguReuse;
+use rustc_codegen_ssa::back::link::ensure_removed;
 use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
 use rustc_codegen_ssa::base::determine_cgu_reuse;
+use rustc_codegen_ssa::errors as ssa_errors;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_metadata::fs::copy_to_stdout;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
-use rustc_session::config::{DebugInfo, OutputFilenames, OutputType};
+use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
 use rustc_session::Session;
 
 use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
+use crate::debuginfo::TypeDebugContext;
 use crate::global_asm::GlobalAsmConfig;
 use crate::{prelude::*, BackendConfig};
 
@@ -53,6 +57,7 @@ impl OngoingCodegen {
     pub(crate) fn join(
         self,
         sess: &Session,
+        outputs: &OutputFilenames,
         backend_config: &BackendConfig,
     ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
         let mut work_products = FxIndexMap::default();
@@ -110,17 +115,183 @@ impl OngoingCodegen {
 
         sess.dcx().abort_if_errors();
 
-        (
-            CodegenResults {
-                modules,
-                allocator_module: self.allocator_module,
-                metadata_module: self.metadata_module,
-                metadata: self.metadata,
-                crate_info: self.crate_info,
-            },
-            work_products,
-        )
+        let codegen_results = CodegenResults {
+            modules,
+            allocator_module: self.allocator_module,
+            metadata_module: self.metadata_module,
+            metadata: self.metadata,
+            crate_info: self.crate_info,
+        };
+
+        produce_final_output_artifacts(sess, &codegen_results, outputs);
+
+        (codegen_results, work_products)
+    }
+}
+
+// Adapted from https://github.com/rust-lang/rust/blob/73476d49904751f8d90ce904e16dfbc278083d2c/compiler/rustc_codegen_ssa/src/back/write.rs#L547C1-L706C2
+fn produce_final_output_artifacts(
+    sess: &Session,
+    codegen_results: &CodegenResults,
+    crate_output: &OutputFilenames,
+) {
+    let user_wants_bitcode = false;
+    let mut user_wants_objects = false;
+
+    // Produce final compile outputs.
+    let copy_gracefully = |from: &Path, to: &OutFileName| match to {
+        OutFileName::Stdout => {
+            if let Err(e) = copy_to_stdout(from) {
+                sess.dcx().emit_err(ssa_errors::CopyPath::new(from, to.as_path(), e));
+            }
+        }
+        OutFileName::Real(path) => {
+            if let Err(e) = fs::copy(from, path) {
+                sess.dcx().emit_err(ssa_errors::CopyPath::new(from, path, e));
+            }
+        }
+    };
+
+    let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| {
+        if codegen_results.modules.len() == 1 {
+            // 1) Only one codegen unit. In this case it's no difficulty
+            //    to copy `foo.0.x` to `foo.x`.
+            let module_name = Some(&codegen_results.modules[0].name[..]);
+            let path = crate_output.temp_path(output_type, module_name);
+            let output = crate_output.path(output_type);
+            if !output_type.is_text_output() && output.is_tty() {
+                sess.dcx()
+                    .emit_err(ssa_errors::BinaryOutputToTty { shorthand: output_type.shorthand() });
+            } else {
+                copy_gracefully(&path, &output);
+            }
+            if !sess.opts.cg.save_temps && !keep_numbered {
+                // The user just wants `foo.x`, not `foo.#module-name#.x`.
+                ensure_removed(sess.dcx(), &path);
+            }
+        } else {
+            let extension = crate_output
+                .temp_path(output_type, None)
+                .extension()
+                .unwrap()
+                .to_str()
+                .unwrap()
+                .to_owned();
+
+            if crate_output.outputs.contains_explicit_name(&output_type) {
+                // 2) Multiple codegen units, with `--emit foo=some_name`. We have
+                //    no good solution for this case, so warn the user.
+                sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension });
+            } else if crate_output.single_output_file.is_some() {
+                // 3) Multiple codegen units, with `-o some_name`. We have
+                //    no good solution for this case, so warn the user.
+                sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension });
+            } else {
+                // 4) Multiple codegen units, but no explicit name. We
+                //    just leave the `foo.0.x` files in place.
+                // (We don't have to do any work in this case.)
+            }
+        }
+    };
+
+    // Flag to indicate whether the user explicitly requested bitcode.
+    // Otherwise, we produced it only as a temporary output, and will need
+    // to get rid of it.
+    for output_type in crate_output.outputs.keys() {
+        match *output_type {
+            OutputType::Bitcode => {
+                // Cranelift doesn't have bitcode
+                // user_wants_bitcode = true;
+                // // Copy to .bc, but always keep the .0.bc. There is a later
+                // // check to figure out if we should delete .0.bc files, or keep
+                // // them for making an rlib.
+                // copy_if_one_unit(OutputType::Bitcode, true);
+            }
+            OutputType::LlvmAssembly => {
+                // Cranelift IR text already emitted during codegen
+                // copy_if_one_unit(OutputType::LlvmAssembly, false);
+            }
+            OutputType::Assembly => {
+                // Currently no support for emitting raw assembly files
+                // copy_if_one_unit(OutputType::Assembly, false);
+            }
+            OutputType::Object => {
+                user_wants_objects = true;
+                copy_if_one_unit(OutputType::Object, true);
+            }
+            OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {}
+        }
+    }
+
+    // Clean up unwanted temporary files.
+
+    // We create the following files by default:
+    //  - #crate#.#module-name#.bc
+    //  - #crate#.#module-name#.o
+    //  - #crate#.crate.metadata.bc
+    //  - #crate#.crate.metadata.o
+    //  - #crate#.o (linked from crate.##.o)
+    //  - #crate#.bc (copied from crate.##.bc)
+    // We may create additional files if requested by the user (through
+    // `-C save-temps` or `--emit=` flags).
+
+    if !sess.opts.cg.save_temps {
+        // Remove the temporary .#module-name#.o objects. If the user didn't
+        // explicitly request bitcode (with --emit=bc), and the bitcode is not
+        // needed for building an rlib, then we must remove .#module-name#.bc as
+        // well.
+
+        // Specific rules for keeping .#module-name#.bc:
+        //  - If the user requested bitcode (`user_wants_bitcode`), and
+        //    codegen_units > 1, then keep it.
+        //  - If the user requested bitcode but codegen_units == 1, then we
+        //    can toss .#module-name#.bc because we copied it to .bc earlier.
+        //  - If we're not building an rlib and the user didn't request
+        //    bitcode, then delete .#module-name#.bc.
+        // If you change how this works, also update back::link::link_rlib,
+        // where .#module-name#.bc files are (maybe) deleted after making an
+        // rlib.
+        let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);
+
+        let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units().as_usize() > 1;
+
+        let keep_numbered_objects =
+            needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1);
+
+        for module in codegen_results.modules.iter() {
+            if let Some(ref path) = module.object {
+                if !keep_numbered_objects {
+                    ensure_removed(sess.dcx(), path);
+                }
+            }
+
+            if let Some(ref path) = module.dwarf_object {
+                if !keep_numbered_objects {
+                    ensure_removed(sess.dcx(), path);
+                }
+            }
+
+            if let Some(ref path) = module.bytecode {
+                if !keep_numbered_bitcode {
+                    ensure_removed(sess.dcx(), path);
+                }
+            }
+        }
+
+        if !user_wants_bitcode {
+            if let Some(ref allocator_module) = codegen_results.allocator_module {
+                if let Some(ref path) = allocator_module.bytecode {
+                    ensure_removed(sess.dcx(), path);
+                }
+            }
+        }
     }
+
+    // We leave the following files around by default:
+    //  - #crate#.o
+    //  - #crate#.crate.metadata.o
+    //  - #crate#.bc
+    // These are used in linking steps and will be cleaned up afterward.
 }
 
 fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule {
@@ -290,6 +461,7 @@ fn module_codegen(
                 tcx.sess.opts.debuginfo != DebugInfo::None,
                 cgu_name,
             );
+            let mut type_dbg = TypeDebugContext::default();
             super::predefine_mono_items(tcx, &mut module, &mono_items);
             let mut codegened_functions = vec![];
             for (mono_item, _) in mono_items {
@@ -298,6 +470,7 @@ fn module_codegen(
                         let codegened_function = crate::base::codegen_fn(
                             tcx,
                             &mut cx,
+                            &mut type_dbg,
                             Function::new(),
                             &mut module,
                             inst,
@@ -305,7 +478,10 @@ fn module_codegen(
                         codegened_functions.push(codegened_function);
                     }
                     MonoItem::Static(def_id) => {
-                        crate::constant::codegen_static(tcx, &mut module, def_id)
+                        let data_id = crate::constant::codegen_static(tcx, &mut module, def_id);
+                        if let Some(debug_context) = &mut cx.debug_context {
+                            debug_context.define_static(tcx, &mut type_dbg, def_id, data_id);
+                        }
                     }
                     MonoItem::GlobalAsm(item_id) => {
                         crate::global_asm::codegen_global_asm_item(
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 6b2b946db02..6dbc3f19127 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -12,6 +12,7 @@ use rustc_middle::mir::mono::MonoItem;
 use rustc_session::Session;
 use rustc_span::Symbol;
 
+use crate::debuginfo::TypeDebugContext;
 use crate::{prelude::*, BackendConfig};
 use crate::{CodegenCx, CodegenMode};
 
@@ -229,7 +230,14 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
             crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
 
         let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
-        let codegened_func = crate::base::codegen_fn(tcx, cx, cached_func, module, instance);
+        let codegened_func = crate::base::codegen_fn(
+            tcx,
+            cx,
+            &mut TypeDebugContext::default(),
+            cached_func,
+            module,
+            instance,
+        );
 
         crate::base::compile_fn(cx, cached_context, module, codegened_func);
     });
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 44650898de8..5a0cd3990f2 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -8,6 +8,7 @@ use std::sync::Arc;
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::{InlineAsmOperand, ItemId};
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_session::config::{OutputFilenames, OutputType};
 use rustc_target::asm::InlineAsmArch;
 
@@ -32,18 +33,27 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
                 InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: op_sp } => {
                     match asm.operands[operand_idx].0 {
                         InlineAsmOperand::Const { ref anon_const } => {
-                            let const_value =
-                                tcx.const_eval_poly(anon_const.def_id.to_def_id()).unwrap_or_else(
-                                    |_| span_bug!(op_sp, "asm const cannot be resolved"),
-                                );
-                            let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
-                            let string = rustc_codegen_ssa::common::asm_const_to_str(
-                                tcx,
-                                op_sp,
-                                const_value,
-                                RevealAllLayoutCx(tcx).layout_of(ty),
-                            );
-                            global_asm.push_str(&string);
+                            match tcx.const_eval_poly(anon_const.def_id.to_def_id()) {
+                                Ok(const_value) => {
+                                    let ty = tcx
+                                        .typeck_body(anon_const.body)
+                                        .node_type(anon_const.hir_id);
+                                    let string = rustc_codegen_ssa::common::asm_const_to_str(
+                                        tcx,
+                                        op_sp,
+                                        const_value,
+                                        RevealAllLayoutCx(tcx).layout_of(ty),
+                                    );
+                                    global_asm.push_str(&string);
+                                }
+                                Err(ErrorHandled::Reported { .. }) => {
+                                    // An error has already been reported and compilation is
+                                    // guaranteed to fail if execution hits this path.
+                                }
+                                Err(ErrorHandled::TooGeneric(_)) => {
+                                    span_bug!(op_sp, "asm const cannot be resolved; too generic");
+                                }
+                            }
                         }
                         InlineAsmOperand::SymFn { anon_const } => {
                             if cfg!(not(feature = "inline_asm_sym")) {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 25694af78f1..0b213ff8269 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -341,6 +341,8 @@ fn codegen_float_intrinsic_call<'tcx>(
         sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64),
         sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32),
         sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64),
+        sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32),
+        sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64),
         sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32),
         sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64),
         sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32),
@@ -392,6 +394,8 @@ fn codegen_float_intrinsic_call<'tcx>(
         | sym::ceilf64
         | sym::truncf32
         | sym::truncf64
+        | sym::nearbyintf32
+        | sym::nearbyintf64
         | sym::sqrtf32
         | sym::sqrtf64 => {
             let val = match intrinsic {
@@ -399,6 +403,7 @@ fn codegen_float_intrinsic_call<'tcx>(
                 sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
                 sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
                 sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
+                sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]),
                 sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]),
                 _ => unreachable!(),
             };
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index a59a39074f8..d0ab64a5584 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -148,7 +148,7 @@ impl CodegenCx {
         let unwind_context =
             UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
         let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows {
-            Some(DebugContext::new(tcx, isa))
+            Some(DebugContext::new(tcx, isa, cgu_name.as_str()))
         } else {
             None
         };
@@ -233,12 +233,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
         &self,
         ongoing_codegen: Box<dyn Any>,
         sess: &Session,
-        _outputs: &OutputFilenames,
+        outputs: &OutputFilenames,
     ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
-        ongoing_codegen
-            .downcast::<driver::aot::OngoingCodegen>()
-            .unwrap()
-            .join(sess, self.config.borrow().as_ref().unwrap())
+        ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(
+            sess,
+            outputs,
+            self.config.borrow().as_ref().unwrap(),
+        )
     }
 
     fn link(
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index d2254d4c15e..86ebf37d105 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -2,7 +2,7 @@
 //!
 //! See `rustc_codegen_ssa/src/meth.rs` for reference.
 
-use crate::constant::data_id_for_alloc_id;
+use crate::constant::data_id_for_vtable;
 use crate::prelude::*;
 
 pub(crate) fn vtable_memflags() -> MemFlags {
@@ -92,12 +92,10 @@ pub(crate) fn get_vtable<'tcx>(
     ty: Ty<'tcx>,
     trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
 ) -> Value {
-    let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref));
-    let data_id =
-        data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
+    let data_id = data_id_for_vtable(fx.tcx, &mut fx.constants_cx, fx.module, ty, trait_ref);
     let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
     if fx.clif_comments.enabled() {
-        fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id));
+        fx.add_comment(local_data_id, "vtable");
     }
     fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
 }
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/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index ee7ea342301..0fbc624389b 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -6,9 +6,8 @@ use crate::llvm;
 
 use itertools::Itertools as _;
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_index::IndexVec;
 use rustc_middle::bug;
 use rustc_middle::mir;
@@ -335,16 +334,9 @@ fn save_function_record(
     );
 }
 
-/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for
-/// the functions that went through codegen; such as public functions and "used" functions
-/// (functions referenced by other "used" or public items). Any other functions considered unused,
-/// or "Unreachable", were still parsed and processed through the MIR stage, but were not
-/// codegenned. (Note that `-Clink-dead-code` can force some unused code to be codegenned, but
-/// that flag is known to cause other errors, when combined with `-C instrument-coverage`; and
-/// `-Clink-dead-code` will not generate code for unused generic functions.)
-///
-/// We can find the unused functions (including generic functions) by the set difference of all MIR
-/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`codegenned_and_inlined_items`).
+/// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
+/// But since we don't want unused functions to disappear from coverage reports, we also scan for
+/// functions that were instrumented but are not participating in codegen.
 ///
 /// These unused functions don't need to be codegenned, but we do need to add them to the function
 /// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
@@ -354,75 +346,109 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
     assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
 
     let tcx = cx.tcx;
+    let usage = prepare_usage_sets(tcx);
+
+    let is_unused_fn = |def_id: LocalDefId| -> bool {
+        let def_id = def_id.to_def_id();
+
+        // To be eligible for "unused function" mappings, a definition must:
+        // - Be function-like
+        // - Not participate directly in codegen (or have lost all its coverage statements)
+        // - Not have any coverage statements inlined into codegenned functions
+        tcx.def_kind(def_id).is_fn_like()
+            && (!usage.all_mono_items.contains(&def_id)
+                || usage.missing_own_coverage.contains(&def_id))
+            && !usage.used_via_inlining.contains(&def_id)
+    };
 
-    let eligible_def_ids = tcx.mir_keys(()).iter().filter_map(|local_def_id| {
-        let def_id = local_def_id.to_def_id();
-        let kind = tcx.def_kind(def_id);
-        // `mir_keys` will give us `DefId`s for all kinds of things, not
-        // just "functions", like consts, statics, etc. Filter those out.
-        if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) {
-            return None;
-        }
+    // Scan for unused functions that were instrumented for coverage.
+    for def_id in tcx.mir_keys(()).iter().copied().filter(|&def_id| is_unused_fn(def_id)) {
+        // Get the coverage info from MIR, skipping functions that were never instrumented.
+        let body = tcx.optimized_mir(def_id);
+        let Some(function_coverage_info) = body.function_coverage_info.as_deref() else { continue };
 
         // FIXME(79651): Consider trying to filter out dummy instantiations of
         // unused generic functions from library crates, because they can produce
         // "unused instantiation" in coverage reports even when they are actually
         // used by some downstream crate in the same binary.
 
-        Some(local_def_id.to_def_id())
-    });
-
-    let codegenned_def_ids = codegenned_and_inlined_items(tcx);
-
-    // For each `DefId` that should have coverage instrumentation but wasn't
-    // codegenned, add it to the function coverage map as an unused function.
-    for def_id in eligible_def_ids.filter(|id| !codegenned_def_ids.contains(id)) {
-        // Skip any function that didn't have coverage data added to it by the
-        // coverage instrumentor.
-        let body = tcx.instance_mir(ty::InstanceDef::Item(def_id));
-        let Some(function_coverage_info) = body.function_coverage_info.as_deref() else {
-            continue;
-        };
-
         debug!("generating unused fn: {def_id:?}");
-        let instance = declare_unused_fn(tcx, def_id);
-        add_unused_function_coverage(cx, instance, function_coverage_info);
+        add_unused_function_coverage(cx, def_id, function_coverage_info);
     }
 }
 
-/// All items participating in code generation together with (instrumented)
-/// items inlined into them.
-fn codegenned_and_inlined_items(tcx: TyCtxt<'_>) -> DefIdSet {
-    let (items, cgus) = tcx.collect_and_partition_mono_items(());
-    let mut visited = DefIdSet::default();
-    let mut result = items.clone();
-
-    for cgu in cgus {
-        for item in cgu.items().keys() {
-            if let mir::mono::MonoItem::Fn(ref instance) = item {
-                let did = instance.def_id();
-                if !visited.insert(did) {
-                    continue;
-                }
-                let body = tcx.instance_mir(instance.def);
-                for block in body.basic_blocks.iter() {
-                    for statement in &block.statements {
-                        let mir::StatementKind::Coverage(_) = statement.kind else { continue };
-                        let scope = statement.source_info.scope;
-                        if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
-                            result.insert(inlined.def_id());
-                        }
-                    }
-                }
+struct UsageSets<'tcx> {
+    all_mono_items: &'tcx DefIdSet,
+    used_via_inlining: FxHashSet<DefId>,
+    missing_own_coverage: FxHashSet<DefId>,
+}
+
+/// Prepare sets of definitions that are relevant to deciding whether something
+/// is an "unused function" for coverage purposes.
+fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
+    let (all_mono_items, cgus) = tcx.collect_and_partition_mono_items(());
+
+    // Obtain a MIR body for each function participating in codegen, via an
+    // arbitrary instance.
+    let mut def_ids_seen = FxHashSet::default();
+    let def_and_mir_for_all_mono_fns = cgus
+        .iter()
+        .flat_map(|cgu| cgu.items().keys())
+        .filter_map(|item| match item {
+            mir::mono::MonoItem::Fn(instance) => Some(instance),
+            mir::mono::MonoItem::Static(_) | mir::mono::MonoItem::GlobalAsm(_) => None,
+        })
+        // We only need one arbitrary instance per definition.
+        .filter(move |instance| def_ids_seen.insert(instance.def_id()))
+        .map(|instance| {
+            // We don't care about the instance, just its underlying MIR.
+            let body = tcx.instance_mir(instance.def);
+            (instance.def_id(), body)
+        });
+
+    // Functions whose coverage statments were found inlined into other functions.
+    let mut used_via_inlining = FxHashSet::default();
+    // Functions that were instrumented, but had all of their coverage statements
+    // removed by later MIR transforms (e.g. UnreachablePropagation).
+    let mut missing_own_coverage = FxHashSet::default();
+
+    for (def_id, body) in def_and_mir_for_all_mono_fns {
+        let mut saw_own_coverage = false;
+
+        // Inspect every coverage statement in the function's MIR.
+        for stmt in body
+            .basic_blocks
+            .iter()
+            .flat_map(|block| &block.statements)
+            .filter(|stmt| matches!(stmt.kind, mir::StatementKind::Coverage(_)))
+        {
+            if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) {
+                // This coverage statement was inlined from another function.
+                used_via_inlining.insert(inlined.def_id());
+            } else {
+                // Non-inlined coverage statements belong to the enclosing function.
+                saw_own_coverage = true;
             }
         }
+
+        if !saw_own_coverage && body.function_coverage_info.is_some() {
+            missing_own_coverage.insert(def_id);
+        }
     }
 
-    result
+    UsageSets { all_mono_items, used_via_inlining, missing_own_coverage }
 }
 
-fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tcx> {
-    ty::Instance::new(
+fn add_unused_function_coverage<'tcx>(
+    cx: &CodegenCx<'_, 'tcx>,
+    def_id: LocalDefId,
+    function_coverage_info: &'tcx mir::coverage::FunctionCoverageInfo,
+) {
+    let tcx = cx.tcx;
+    let def_id = def_id.to_def_id();
+
+    // Make a dummy instance that fills in all generics with placeholders.
+    let instance = ty::Instance::new(
         def_id,
         ty::GenericArgs::for_item(tcx, def_id, |param, _| {
             if let ty::GenericParamDefKind::Lifetime = param.kind {
@@ -431,14 +457,8 @@ fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tc
                 tcx.mk_param_from_def(param)
             }
         }),
-    )
-}
+    );
 
-fn add_unused_function_coverage<'tcx>(
-    cx: &CodegenCx<'_, 'tcx>,
-    instance: ty::Instance<'tcx>,
-    function_coverage_info: &'tcx mir::coverage::FunctionCoverageInfo,
-) {
     // An unused function's mappings will automatically be rewritten to map to
     // zero, because none of its counters/expressions are marked as seen.
     let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 4792b0798df..4edef14422e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -683,7 +683,8 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
         _ => unreachable!(),
     };
 
-    let coroutine_layout = cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
+    let coroutine_layout =
+        cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
 
     let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
     let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 3dbe820b8ff..115d5187eaf 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -135,7 +135,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
     let coroutine_type = unique_type_id.expect_ty();
-    let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else {
+    let &ty::Coroutine(coroutine_def_id, coroutine_args) = coroutine_type.kind() else {
         bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
     };
 
@@ -158,8 +158,10 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
             DIFlags::FlagZero,
         ),
         |cx, coroutine_type_di_node| {
-            let coroutine_layout =
-                cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
+            let coroutine_layout = cx
+                .tcx
+                .coroutine_layout(coroutine_def_id, coroutine_args.as_coroutine().kind_ty())
+                .unwrap();
 
             let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
                 coroutine_type_and_layout.variants
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..4283ebc99d2 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)?;
@@ -402,7 +409,7 @@ fn const_validate_mplace<'mir, 'tcx>(
             }
         };
         ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
-            // Instead of just reporting the `InterpError` via the usual machinery, we give a more targetted
+            // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
             // error about the validation failure.
             .map_err(|error| report_validation_error(&ecx, error, alloc_id))?;
         inner = true;
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_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 08e3e42a82e..378b168a50c 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -101,18 +101,17 @@ impl<'tcx> MirPass<'tcx> for Validator {
         }
 
         // Enforce that coroutine-closure layouts are identical.
-        if let Some(layout) = body.coroutine_layout()
+        if let Some(layout) = body.coroutine_layout_raw()
             && let Some(by_move_body) = body.coroutine_by_move_body()
-            && let Some(by_move_layout) = by_move_body.coroutine_layout()
+            && let Some(by_move_layout) = by_move_body.coroutine_layout_raw()
         {
-            if layout != by_move_layout {
-                // If this turns out not to be true, please let compiler-errors know.
-                // It is possible to support, but requires some changes to the layout
-                // computation code.
+            // FIXME(async_closures): We could do other validation here?
+            if layout.variant_fields.len() != by_move_layout.variant_fields.len() {
                 cfg_checker.fail(
                     Location::START,
                     format!(
-                        "Coroutine layout differs from by-move coroutine layout:\n\
+                        "Coroutine layout has different number of variant fields from \
+                        by-move coroutine layout:\n\
                         layout: {layout:#?}\n\
                         by_move_layout: {by_move_layout:#?}",
                     ),
@@ -715,13 +714,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             // args of the coroutine. Otherwise, we prefer to use this body
                             // since we may be in the process of computing this MIR in the
                             // first place.
-                            let gen_body = if def_id == self.caller_body.source.def_id() {
-                                self.caller_body
+                            let layout = if def_id == self.caller_body.source.def_id() {
+                                // FIXME: This is not right for async closures.
+                                self.caller_body.coroutine_layout_raw()
                             } else {
-                                self.tcx.optimized_mir(def_id)
+                                self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty())
                             };
 
-                            let Some(layout) = gen_body.coroutine_layout() else {
+                            let Some(layout) = layout else {
                                 self.fail(
                                     location,
                                     format!("No coroutine layout for {parent_ty:?}"),
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_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 30ee02ea3c0..b25dd8fe67b 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1252,21 +1252,18 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe
     // after macro expansion (that is, they are unhygienic).
     if !path.is_absolute() {
         let callsite = span.source_callsite();
-        let mut result = match sess.source_map().span_to_filename(callsite) {
-            FileName::Real(name) => name
-                .into_local_path()
-                .expect("attempting to resolve a file path in an external file"),
-            FileName::DocTest(path, _) => path,
-            other => {
-                return Err(sess.dcx().create_err(errors::ResolveRelativePath {
-                    span,
-                    path: sess.source_map().filename_for_diagnostics(&other).to_string(),
-                }));
-            }
+        let source_map = sess.source_map();
+        let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else {
+            return Err(sess.dcx().create_err(errors::ResolveRelativePath {
+                span,
+                path: source_map
+                    .filename_for_diagnostics(&source_map.span_to_filename(callsite))
+                    .to_string(),
+            }));
         };
-        result.pop();
-        result.push(path);
-        Ok(result)
+        base_path.pop();
+        base_path.push(path);
+        Ok(base_path)
     } else {
         Ok(path)
     }
@@ -1379,6 +1376,15 @@ pub fn get_single_str_from_tts(
     tts: TokenStream,
     name: &str,
 ) -> ExpandResult<Result<Symbol, ErrorGuaranteed>, ()> {
+    get_single_str_spanned_from_tts(cx, span, tts, name).map(|res| res.map(|(s, _)| s))
+}
+
+pub fn get_single_str_spanned_from_tts(
+    cx: &mut ExtCtxt<'_>,
+    span: Span,
+    tts: TokenStream,
+    name: &str,
+) -> ExpandResult<Result<(Symbol, Span), ErrorGuaranteed>, ()> {
     let mut p = cx.new_parser_from_tts(tts);
     if p.token == token::Eof {
         let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
@@ -1393,7 +1399,13 @@ pub fn get_single_str_from_tts(
     if p.token != token::Eof {
         cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
     }
-    expr_to_string(cx, ret, "argument must be a string literal").map(|s| s.map(|(s, _)| s))
+    expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| {
+        res.map_err(|err| match err {
+            Ok((err, _)) => err.emit(),
+            Err(guar) => guar,
+        })
+        .map(|(symbol, _style, span)| (symbol, span))
+    })
 }
 
 /// Extracts comma-separated expressions from `tts`.
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..d9d36f5299b 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 preceded 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..8886a78c6ec 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2212,6 +2212,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             try_emit("delegation with early bound generics");
         }
 
+        // There is no way to instantiate `Self` param for caller if
+        // 1. callee is a trait method
+        // 2. delegation item isn't an associative item
+        if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
+            && let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
+            && self.tcx().associated_item(sig_id).container
+                == ty::AssocItemContainer::TraitContainer
+        {
+            try_emit("delegation to a trait method from a free function");
+        }
+
         if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
             try_emit("delegation to async functions");
         }
@@ -2339,12 +2350,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_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 8077acea52e..d3bb22d715d 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -1,14 +1,14 @@
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_middle::ty::{self, Region, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::Span;
 use smallvec::smallvec;
-use std::collections::BTreeMap;
 
 /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
 /// must be added to the struct header.
 pub(crate) type RequiredPredicates<'tcx> =
-    BTreeMap<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>, Span>;
+    FxIndexMap<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>, Span>;
 
 /// Given a requirement `T: 'a` or `'b: 'a`, deduce the
 /// outlives_component and add it to `required_predicates`
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 0ca958302f7..f7af438ad16 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -122,6 +122,10 @@ hir_typeck_return_stmt_outside_of_fn_body =
     .encl_body_label = the {$statement_kind} is part of this body...
     .encl_fn_label = ...not the enclosing function body
 
+hir_typeck_rpit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
+
+hir_typeck_rpit_change_return_type = you could change the return type to be a boxed trait object
+
 hir_typeck_rustcall_incorrect_args =
     functions with the "rust-call" ABI must take a single non-self tuple argument
 
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 9b7db9e4c8e..2a2fd0a41a6 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -1,17 +1,13 @@
 use crate::coercion::{AsCoercionSite, CoerceMany};
 use crate::{Diverges, Expectation, FnCtxt, Needs};
 use rustc_errors::{Applicability, Diag};
-use rustc_hir::{
-    self as hir,
-    def::{CtorOf, DefKind, Res},
-    ExprKind, PatKind,
-};
+use rustc_hir::def::{CtorOf, DefKind, Res};
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::{self as hir, ExprKind, PatKind};
 use rustc_hir_pretty::ty_to_string;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::Obligation;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
 };
@@ -91,10 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             let arm_ty = self.check_expr_with_expectation(arm.body, expected);
             all_arms_diverge &= self.diverges.get();
-
-            let opt_suggest_box_span = prior_arm.and_then(|(_, prior_arm_ty, _)| {
-                self.opt_suggest_box_span(prior_arm_ty, arm_ty, orig_expected)
-            });
+            let tail_defines_return_position_impl_trait =
+                self.return_position_impl_trait_from_match_expectation(orig_expected);
 
             let (arm_block_id, arm_span) = if let hir::ExprKind::Block(blk, _) = arm.body.kind {
                 (Some(blk.hir_id), self.find_block_span(blk))
@@ -120,7 +114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         scrut_span: scrut.span,
                         source: match_src,
                         prior_non_diverging_arms: prior_non_diverging_arms.clone(),
-                        opt_suggest_box_span,
+                        tail_defines_return_position_impl_trait,
                     })),
                 ),
             };
@@ -243,7 +237,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`.
@@ -422,7 +416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         else_expr: &'tcx hir::Expr<'tcx>,
         then_ty: Ty<'tcx>,
         else_ty: Ty<'tcx>,
-        opt_suggest_box_span: Option<Span>,
+        tail_defines_return_position_impl_trait: Option<LocalDefId>,
     ) -> ObligationCause<'tcx> {
         let mut outer_span = if self.tcx.sess.source_map().is_multiline(span) {
             // The `if`/`else` isn't in one line in the output, include some context to make it
@@ -513,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 then_ty,
                 else_ty,
                 outer_span,
-                opt_suggest_box_span,
+                tail_defines_return_position_impl_trait,
             })),
         )
     }
@@ -593,96 +587,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    /// When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
-    /// we check if the different arms would work with boxed trait objects instead and
-    /// provide a structured suggestion in that case.
-    pub(crate) fn opt_suggest_box_span(
+    // Does the expectation of the match define an RPIT?
+    // (e.g. we're in the tail of a function body)
+    //
+    // Returns the `LocalDefId` of the RPIT, which is always identity-substituted.
+    pub fn return_position_impl_trait_from_match_expectation(
         &self,
-        first_ty: Ty<'tcx>,
-        second_ty: Ty<'tcx>,
-        orig_expected: Expectation<'tcx>,
-    ) -> Option<Span> {
-        // FIXME(compiler-errors): This really shouldn't need to be done during the
-        // "good" path of typeck, but here we are.
-        match orig_expected {
-            Expectation::ExpectHasType(expected) => {
-                let TypeVariableOrigin {
-                    span,
-                    kind: TypeVariableOriginKind::OpaqueTypeInference(rpit_def_id),
-                    ..
-                } = self.type_var_origin(expected)?
-                else {
-                    return None;
-                };
-
-                let Some(rpit_local_def_id) = rpit_def_id.as_local() else {
-                    return None;
-                };
-                if !matches!(
-                    self.tcx.hir().expect_item(rpit_local_def_id).expect_opaque_ty().origin,
-                    hir::OpaqueTyOrigin::FnReturn(..)
-                ) {
-                    return None;
-                }
-
-                let sig = self.body_fn_sig()?;
-
-                let args = sig.output().walk().find_map(|arg| {
-                    if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                        && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *ty.kind()
-                        && def_id == rpit_def_id
-                    {
-                        Some(args)
-                    } else {
-                        None
-                    }
-                })?;
-
-                if !self.can_coerce(first_ty, expected) || !self.can_coerce(second_ty, expected) {
-                    return None;
-                }
-
-                for ty in [first_ty, second_ty] {
-                    for (clause, _) in self
-                        .tcx
-                        .explicit_item_super_predicates(rpit_def_id)
-                        .iter_instantiated_copied(self.tcx, args)
-                    {
-                        let pred = clause.kind().rebind(match clause.kind().skip_binder() {
-                            ty::ClauseKind::Trait(trait_pred) => {
-                                assert!(matches!(
-                                    *trait_pred.trait_ref.self_ty().kind(),
-                                    ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. })
-                                    if def_id == rpit_def_id && args == alias_args
-                                ));
-                                ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
-                            }
-                            ty::ClauseKind::Projection(mut proj_pred) => {
-                                assert!(matches!(
-                                    *proj_pred.projection_ty.self_ty().kind(),
-                                    ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. })
-                                    if def_id == rpit_def_id && args == alias_args
-                                ));
-                                proj_pred = proj_pred.with_self_ty(self.tcx, ty);
-                                ty::ClauseKind::Projection(proj_pred)
-                            }
-                            _ => continue,
-                        });
-                        if !self.predicate_must_hold_modulo_regions(&Obligation::new(
-                            self.tcx,
-                            ObligationCause::misc(span, self.body_id),
-                            self.param_env,
-                            pred,
-                        )) {
-                            return None;
-                        }
-                    }
-                }
-
-                Some(span)
-            }
-            _ => None,
+        expectation: Expectation<'tcx>,
+    ) -> Option<LocalDefId> {
+        let expected_ty = expectation.to_option(self)?;
+        let (def_id, args) = match *expected_ty.kind() {
+            // FIXME: Could also check that the RPIT is not defined
+            ty::Alias(ty::Opaque, alias_ty) => (alias_ty.def_id.as_local()?, alias_ty.args),
+            // FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
+            ty::Infer(ty::TyVar(_)) => self
+                .inner
+                .borrow()
+                .iter_opaque_types()
+                .find(|(_, v)| v.ty == expected_ty)
+                .map(|(k, _)| (k.def_id, k.args))?,
+            _ => return None,
+        };
+        let hir::OpaqueTyOrigin::FnReturn(parent_def_id) = self.tcx.opaque_type_origin(def_id)
+        else {
+            return None;
+        };
+        if &args[0..self.tcx.generics_of(parent_def_id).count()]
+            != ty::GenericArgs::identity_for_item(self.tcx, parent_def_id).as_slice()
+        {
+            return None;
         }
+        Some(def_id)
     }
 }
 
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/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 3328177634b..44b19318d5d 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -35,17 +35,18 @@
 //! // and are then unable to coerce `&7i32` to `&mut i32`.
 //! ```
 
+use crate::errors::SuggestBoxingForReturnImplTrait;
 use crate::FnCtxt;
 use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::Expr;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
-use rustc_infer::traits::TraitEngine;
 use rustc_infer::traits::TraitEngineExt as _;
+use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine};
 use rustc_infer::traits::{Obligation, PredicateObligation};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::traits::BuiltinImplSource;
@@ -59,6 +60,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::DesugaringKind;
+use rustc_span::{BytePos, Span};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -1638,6 +1640,77 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             unsized_return = self.is_return_ty_definitely_unsized(fcx);
                         }
                     }
+                    ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                        arm_span,
+                        arm_ty,
+                        prior_arm_ty,
+                        ref prior_non_diverging_arms,
+                        tail_defines_return_position_impl_trait: Some(rpit_def_id),
+                        ..
+                    }) => {
+                        err = fcx.err_ctxt().report_mismatched_types(
+                            cause,
+                            expected,
+                            found,
+                            coercion_error,
+                        );
+                        // Check that we're actually in the second or later arm
+                        if prior_non_diverging_arms.len() > 0 {
+                            self.suggest_boxing_tail_for_return_position_impl_trait(
+                                fcx,
+                                &mut err,
+                                rpit_def_id,
+                                arm_ty,
+                                prior_arm_ty,
+                                prior_non_diverging_arms
+                                    .iter()
+                                    .chain(std::iter::once(&arm_span))
+                                    .copied(),
+                            );
+                        }
+                    }
+                    ObligationCauseCode::IfExpression(box IfExpressionCause {
+                        then_id,
+                        else_id,
+                        then_ty,
+                        else_ty,
+                        tail_defines_return_position_impl_trait: Some(rpit_def_id),
+                        ..
+                    }) => {
+                        err = fcx.err_ctxt().report_mismatched_types(
+                            cause,
+                            expected,
+                            found,
+                            coercion_error,
+                        );
+                        let then_span = fcx.find_block_span_from_hir_id(then_id);
+                        let else_span = fcx.find_block_span_from_hir_id(else_id);
+                        // don't suggest wrapping either blocks in `if .. {} else {}`
+                        let is_empty_arm = |id| {
+                            let hir::Node::Block(blk) = fcx.tcx.hir_node(id) else {
+                                return false;
+                            };
+                            if blk.expr.is_some() || !blk.stmts.is_empty() {
+                                return false;
+                            }
+                            let Some((_, hir::Node::Expr(expr))) =
+                                fcx.tcx.hir().parent_iter(id).nth(1)
+                            else {
+                                return false;
+                            };
+                            matches!(expr.kind, hir::ExprKind::If(..))
+                        };
+                        if !is_empty_arm(then_id) && !is_empty_arm(else_id) {
+                            self.suggest_boxing_tail_for_return_position_impl_trait(
+                                fcx,
+                                &mut err,
+                                rpit_def_id,
+                                then_ty,
+                                else_ty,
+                                [then_span, else_span].into_iter(),
+                            );
+                        }
+                    }
                     _ => {
                         err = fcx.err_ctxt().report_mismatched_types(
                             cause,
@@ -1677,6 +1750,70 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         }
     }
 
+    fn suggest_boxing_tail_for_return_position_impl_trait(
+        &self,
+        fcx: &FnCtxt<'_, 'tcx>,
+        err: &mut Diag<'_>,
+        rpit_def_id: LocalDefId,
+        a_ty: Ty<'tcx>,
+        b_ty: Ty<'tcx>,
+        arm_spans: impl Iterator<Item = Span>,
+    ) {
+        let compatible = |ty: Ty<'tcx>| {
+            fcx.probe(|_| {
+                let ocx = ObligationCtxt::new(fcx);
+                ocx.register_obligations(
+                    fcx.tcx
+                        .item_super_predicates(rpit_def_id)
+                        .instantiate_identity_iter()
+                        .filter_map(|clause| {
+                            let predicate = clause
+                                .kind()
+                                .map_bound(|clause| match clause {
+                                    ty::ClauseKind::Trait(trait_pred) => Some(
+                                        ty::ClauseKind::Trait(trait_pred.with_self_ty(fcx.tcx, ty)),
+                                    ),
+                                    ty::ClauseKind::Projection(proj_pred) => {
+                                        Some(ty::ClauseKind::Projection(
+                                            proj_pred.with_self_ty(fcx.tcx, ty),
+                                        ))
+                                    }
+                                    _ => None,
+                                })
+                                .transpose()?;
+                            Some(Obligation::new(
+                                fcx.tcx,
+                                ObligationCause::dummy(),
+                                fcx.param_env,
+                                predicate,
+                            ))
+                        }),
+                );
+                ocx.select_where_possible().is_empty()
+            })
+        };
+
+        if !compatible(a_ty) || !compatible(b_ty) {
+            return;
+        }
+
+        let rpid_def_span = fcx.tcx.def_span(rpit_def_id);
+        err.subdiagnostic(
+            fcx.tcx.dcx(),
+            SuggestBoxingForReturnImplTrait::ChangeReturnType {
+                start_sp: rpid_def_span.with_hi(rpid_def_span.lo() + BytePos(4)),
+                end_sp: rpid_def_span.shrink_to_hi(),
+            },
+        );
+
+        let (starts, ends) =
+            arm_spans.map(|span| (span.shrink_to_lo(), span.shrink_to_hi())).unzip();
+        err.subdiagnostic(
+            fcx.tcx.dcx(),
+            SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends },
+        );
+    }
+
     fn note_unreachable_loop_return(
         &self,
         err: &mut Diag<'_>,
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index eee4ac5ad23..f9b2ec69730 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -621,3 +621,21 @@ pub struct NoteCallerChoosesTyForTyParam<'tcx> {
     pub ty_param_name: Symbol,
     pub found_ty: Ty<'tcx>,
 }
+
+#[derive(Subdiagnostic)]
+pub enum SuggestBoxingForReturnImplTrait {
+    #[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")]
+    ChangeReturnType {
+        #[suggestion_part(code = "Box<dyn")]
+        start_sp: Span,
+        #[suggestion_part(code = ">")]
+        end_sp: Span,
+    },
+    #[multipart_suggestion(hir_typeck_rpit_box_return_expr, applicability = "maybe-incorrect")]
+    BoxReturnExpr {
+        #[suggestion_part(code = "Box::new(")]
+        starts: Vec<Span>,
+        #[suggestion_part(code = ")")]
+        ends: Vec<Span>,
+    },
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f38f04fce43..d3e6eb124f7 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1088,7 +1088,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let else_ty = self.check_expr_with_expectation(else_expr, expected);
             let else_diverges = self.diverges.get();
 
-            let opt_suggest_box_span = self.opt_suggest_box_span(then_ty, else_ty, orig_expected);
+            let tail_defines_return_position_impl_trait =
+                self.return_position_impl_trait_from_match_expectation(orig_expected);
             let if_cause = self.if_cause(
                 sp,
                 cond_expr.span,
@@ -1096,7 +1097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 else_expr,
                 then_ty,
                 else_ty,
-                opt_suggest_box_span,
+                tail_defines_return_position_impl_trait,
             );
 
             coerce.coerce(self, &if_cause, else_expr, else_ty);
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..80fd4be53e1 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;
@@ -83,20 +83,6 @@ macro_rules! type_error_struct {
     })
 }
 
-/// If this `DefId` is a "primary tables entry", returns
-/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
-///
-/// If this function returns `Some`, then `typeck_results(def_id)` will
-/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
-/// may not succeed. In some cases where this function returns `None`
-/// (notably closures), `typeck_results(def_id)` would wind up
-/// redirecting to the owning function.
-fn primary_body_of(
-    node: Node<'_>,
-) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
-    Some((node.body_id()?, node.ty(), node.fn_sig()))
-}
-
 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
@@ -106,7 +92,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     }
 
     if let Some(def_id) = def_id.as_local() {
-        primary_body_of(tcx.hir_node_by_def_id(def_id)).is_some()
+        tcx.hir_node_by_def_id(def_id).body_id().is_some()
     } else {
         false
     }
@@ -163,20 +149,20 @@ fn typeck_with_fallback<'tcx>(
     let span = tcx.hir().span(id);
 
     // Figure out what primary body this item has.
-    let (body_id, body_ty, fn_sig) = primary_body_of(node).unwrap_or_else(|| {
+    let body_id = node.body_id().unwrap_or_else(|| {
         span_bug!(span, "can't type-check body of {:?}", def_id);
     });
     let body = tcx.hir().body(body_id);
 
     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 {
+    if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
         let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
             fcx.lowerer().lower_fn_ty(id, header.unsafety, header.abi, decl, None, None)
         } else {
@@ -191,42 +177,7 @@ fn typeck_with_fallback<'tcx>(
 
         check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params);
     } else {
-        let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty {
-            Some(fcx.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span,
-            }))
-        } else if let Node::AnonConst(_) = node {
-            match tcx.parent_hir_node(id) {
-                Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), .. })
-                    if anon_const.hir_id == id =>
-                {
-                    Some(fcx.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::TypeInference,
-                        span,
-                    }))
-                }
-                Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
-                | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
-                    asm.operands.iter().find_map(|(op, _op_sp)| match op {
-                        hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
-                            // Inline assembly constants must be integers.
-                            Some(fcx.next_int_var())
-                        }
-                        hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
-                            Some(fcx.next_ty_var(TypeVariableOrigin {
-                                kind: TypeVariableOriginKind::MiscVariable,
-                                span,
-                            }))
-                        }
-                        _ => None,
-                    })
-                }
-                _ => None,
-            }
-        } else {
-            None
-        };
+        let expected_type = infer_type_if_missing(&fcx, node);
         let expected_type = expected_type.unwrap_or_else(fallback);
 
         let expected_type = fcx.normalize(body.value.span, expected_type);
@@ -296,6 +247,59 @@ fn typeck_with_fallback<'tcx>(
     typeck_results
 }
 
+fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> {
+    let tcx = fcx.tcx;
+    let def_id = fcx.body_id;
+    let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() {
+        if let Some(item) = tcx.opt_associated_item(def_id.into())
+            && let ty::AssocKind::Const = item.kind
+            && let ty::ImplContainer = item.container
+            && let Some(trait_item) = item.trait_item_def_id
+        {
+            let args =
+                tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
+            Some(tcx.type_of(trait_item).instantiate(tcx, args))
+        } else {
+            Some(fcx.next_ty_var(TypeVariableOrigin {
+                kind: TypeVariableOriginKind::TypeInference,
+                span,
+            }))
+        }
+    } else if let Node::AnonConst(_) = node {
+        let id = tcx.local_def_id_to_hir_id(def_id);
+        match tcx.parent_hir_node(id) {
+            Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. })
+                if anon_const.hir_id == id =>
+            {
+                Some(fcx.next_ty_var(TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::TypeInference,
+                    span,
+                }))
+            }
+            Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
+            | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
+                asm.operands.iter().find_map(|(op, _op_sp)| match op {
+                    hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
+                        // Inline assembly constants must be integers.
+                        Some(fcx.next_int_var())
+                    }
+                    hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
+                        Some(fcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::MiscVariable,
+                            span,
+                        }))
+                    }
+                    _ => None,
+                })
+            }
+            _ => None,
+        }
+    } else {
+        None
+    };
+    expected_type
+}
+
 /// When `check_fn` is invoked on a coroutine (i.e., a body that
 /// includes yield), it returns back some information about the yield
 /// points.
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index e9752d7a4a8..39d54f1a25e 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -81,7 +81,7 @@ pub struct NoMatchData<'tcx> {
 
 // A pared down enum describing just the places from which a method
 // candidate can arise. Used for error reporting only.
-#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum CandidateSource {
     Impl(DefId),
     Trait(DefId /* trait id */),
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0dcde0cdecb..12f522d1adc 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -49,7 +49,6 @@ use std::borrow::Cow;
 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
 use rustc_hir::intravisit::Visitor;
-use std::cmp::{self, Ordering};
 use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -1186,7 +1185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         })
                         .collect::<Vec<_>>();
                     if !inherent_impls_candidate.is_empty() {
-                        inherent_impls_candidate.sort();
+                        inherent_impls_candidate.sort_by_key(|id| self.tcx.def_path_str(id));
                         inherent_impls_candidate.dedup();
 
                         // number of types to show at most
@@ -1567,7 +1566,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sources: &mut Vec<CandidateSource>,
         sugg_span: Option<Span>,
     ) {
-        sources.sort();
+        sources.sort_by_key(|source| match source {
+            CandidateSource::Trait(id) => (0, self.tcx.def_path_str(id)),
+            CandidateSource::Impl(id) => (1, self.tcx.def_path_str(id)),
+        });
         sources.dedup();
         // Dynamic limit to avoid hiding just one candidate, which is silly.
         let limit = if sources.len() == 5 { 5 } else { 4 };
@@ -2549,7 +2551,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => None,
             })
             .collect();
-        preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
+        preds.sort_by_key(|pred| pred.trait_ref.to_string());
         let def_ids = preds
             .iter()
             .filter_map(|pred| match pred.self_ty().kind() {
@@ -2663,7 +2665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 traits.push(trait_pred.def_id());
             }
         }
-        traits.sort();
+        traits.sort_by_key(|id| self.tcx.def_path_str(id));
         traits.dedup();
 
         let len = traits.len();
@@ -2886,7 +2888,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         if !valid_out_of_scope_traits.is_empty() {
             let mut candidates = valid_out_of_scope_traits;
-            candidates.sort();
+            candidates.sort_by_key(|id| self.tcx.def_path_str(id));
             candidates.dedup();
 
             // `TryFrom` and `FromIterator` have no methods
@@ -3212,8 +3214,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if !candidates.is_empty() {
-            // Sort from most relevant to least relevant.
-            candidates.sort_by_key(|&info| cmp::Reverse(info));
+            // Sort local crate results before others
+            candidates
+                .sort_by_key(|&info| (!info.def_id.is_local(), self.tcx.def_path_str(info.def_id)));
             candidates.dedup();
 
             let param_type = match rcvr_ty.kind() {
@@ -3561,33 +3564,11 @@ pub enum SelfSource<'a> {
     MethodCall(&'a hir::Expr<'a> /* rcvr */),
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, PartialEq, Eq)]
 pub struct TraitInfo {
     pub def_id: DefId,
 }
 
-impl PartialEq for TraitInfo {
-    fn eq(&self, other: &TraitInfo) -> bool {
-        self.cmp(other) == Ordering::Equal
-    }
-}
-impl Eq for TraitInfo {}
-impl PartialOrd for TraitInfo {
-    fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-impl Ord for TraitInfo {
-    fn cmp(&self, other: &TraitInfo) -> Ordering {
-        // Local crates are more important than remote ones (local:
-        // `cnum == 0`), and otherwise we throw in the defid for totality.
-
-        let lhs = (other.def_id.krate, other.def_id);
-        let rhs = (self.def_id.krate, self.def_id);
-        lhs.cmp(&rhs)
-    }
-}
-
 /// Retrieves all traits in this crate and any dependent crates,
 /// and wraps them into `TraitInfo` for custom sorting.
 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
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_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 521c65c6009..fdb6ab8f59b 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -270,9 +270,6 @@ infer_ril_introduced_by = requirement introduced by this return type
 infer_ril_introduced_here = `'static` requirement introduced here
 infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
 
-infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
-
-infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
 infer_source_kind_closure_return =
     try giving this closure an explicit return type
 
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index d0b1f2848ff..6192eaf3c3a 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1263,24 +1263,6 @@ pub enum SuggestAccessingField<'a> {
 }
 
 #[derive(Subdiagnostic)]
-pub enum SuggestBoxingForReturnImplTrait {
-    #[multipart_suggestion(infer_sbfrit_change_return_type, applicability = "maybe-incorrect")]
-    ChangeReturnType {
-        #[suggestion_part(code = "Box<dyn")]
-        start_sp: Span,
-        #[suggestion_part(code = ">")]
-        end_sp: Span,
-    },
-    #[multipart_suggestion(infer_sbfrit_box_return_expr, applicability = "maybe-incorrect")]
-    BoxReturnExpr {
-        #[suggestion_part(code = "Box::new(")]
-        starts: Vec<Span>,
-        #[suggestion_part(code = ")")]
-        ends: Vec<Span>,
-    },
-}
-
-#[derive(Subdiagnostic)]
 #[multipart_suggestion(infer_stp_wrap_one, applicability = "maybe-incorrect")]
 pub struct SuggestTuplePatternOne {
     pub variant: String,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 82634f7308d..0911e4f5063 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -784,7 +784,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 prior_arm_ty,
                 source,
                 ref prior_non_diverging_arms,
-                opt_suggest_box_span,
                 scrut_span,
                 ..
             }) => match source {
@@ -853,17 +852,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ) {
                         err.subdiagnostic(self.dcx(), subdiag);
                     }
-                    if let Some(ret_sp) = opt_suggest_box_span {
-                        // Get return type span and point to it.
-                        self.suggest_boxing_for_return_impl_trait(
-                            err,
-                            ret_sp,
-                            prior_non_diverging_arms
-                                .iter()
-                                .chain(std::iter::once(&arm_span))
-                                .copied(),
-                        );
-                    }
                 }
             },
             ObligationCauseCode::IfExpression(box IfExpressionCause {
@@ -872,7 +860,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 then_ty,
                 else_ty,
                 outer_span,
-                opt_suggest_box_span,
+                ..
             }) => {
                 let then_span = self.find_block_span_from_hir_id(then_id);
                 let else_span = self.find_block_span_from_hir_id(else_id);
@@ -890,30 +878,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ) {
                     err.subdiagnostic(self.dcx(), subdiag);
                 }
-                // don't suggest wrapping either blocks in `if .. {} else {}`
-                let is_empty_arm = |id| {
-                    let hir::Node::Block(blk) = self.tcx.hir_node(id) else {
-                        return false;
-                    };
-                    if blk.expr.is_some() || !blk.stmts.is_empty() {
-                        return false;
-                    }
-                    let Some((_, hir::Node::Expr(expr))) = self.tcx.hir().parent_iter(id).nth(1)
-                    else {
-                        return false;
-                    };
-                    matches!(expr.kind, hir::ExprKind::If(..))
-                };
-                if let Some(ret_sp) = opt_suggest_box_span
-                    && !is_empty_arm(then_id)
-                    && !is_empty_arm(else_id)
-                {
-                    self.suggest_boxing_for_return_impl_trait(
-                        err,
-                        ret_sp,
-                        [then_span, else_span].into_iter(),
-                    );
-                }
             }
             ObligationCauseCode::LetElse => {
                 err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
@@ -1074,7 +1038,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let (sig, reg) = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS)
                 .name_all_regions(sig)
                 .unwrap();
-            let lts: Vec<String> = reg.into_values().map(|kind| kind.to_string()).collect();
+            let lts: Vec<String> =
+                reg.into_items().map(|(_, kind)| kind.to_string()).into_sorted_stable_ord();
             (if lts.is_empty() { String::new() } else { format!("for<{}> ", lts.join(", ")) }, sig)
         };
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index e220c4d02a2..9a05fb1c30f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -19,9 +19,8 @@ use rustc_span::{sym, BytePos, Span};
 
 use crate::errors::{
     ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
-    FunctionPointerSuggestion, SuggestAccessingField, SuggestBoxingForReturnImplTrait,
-    SuggestRemoveSemiOrReturnBinding, SuggestTuplePatternMany, SuggestTuplePatternOne,
-    TypeErrorAdditionalDiags,
+    FunctionPointerSuggestion, SuggestAccessingField, SuggestRemoveSemiOrReturnBinding,
+    SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
 };
 
 use super::TypeErrCtxt;
@@ -80,28 +79,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
     }
 
-    pub(super) fn suggest_boxing_for_return_impl_trait(
-        &self,
-        err: &mut Diag<'_>,
-        return_sp: Span,
-        arm_spans: impl Iterator<Item = Span>,
-    ) {
-        let sugg = SuggestBoxingForReturnImplTrait::ChangeReturnType {
-            start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)),
-            end_sp: return_sp.shrink_to_hi(),
-        };
-        err.subdiagnostic(self.dcx(), sugg);
-
-        let mut starts = Vec::new();
-        let mut ends = Vec::new();
-        for span in arm_spans {
-            starts.push(span.shrink_to_lo());
-            ends.push(span.shrink_to_hi());
-        }
-        let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends };
-        err.subdiagnostic(self.dcx(), sugg);
-    }
-
     pub(super) fn suggest_tuple_pattern(
         &self,
         cause: &ObligationCause<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index a3ff655b609..339c8ac10b3 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -229,6 +229,15 @@ impl<'tcx> InferCtxtInner<'tcx> {
             .expect("region constraints already solved")
             .with_log(&mut self.undo_log)
     }
+
+    // Iterates through the opaque type definitions without taking them; this holds the
+    // `InferCtxtInner` lock, so make sure to not do anything with `InferCtxt` side-effects
+    // while looping through this.
+    pub fn iter_opaque_types(
+        &self,
+    ) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> + '_ {
+        self.opaque_type_storage.opaque_types.iter().map(|(&k, v)| (k, v.hidden_type))
+    }
 }
 
 pub struct InferCtxt<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 02b8ded285f..01430e830e5 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -73,7 +73,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     // for opaque types, and then use that kind to fix the spans for type errors
                     // that we see later on.
                     let ty_var = self.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::OpaqueTypeInference(def_id),
+                        kind: TypeVariableOriginKind::MiscVariable,
                         span,
                     });
                     obligations.extend(
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index 3630b0f439f..55c6c92a584 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -47,7 +47,6 @@ pub enum TypeVariableOriginKind {
     MiscVariable,
     NormalizeProjectionType,
     TypeInference,
-    OpaqueTypeInference(DefId),
     TypeParameterDefinition(Symbol, DefId),
 
     /// One of the upvars or closure kind parameters in a `ClosureArgs`
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 656c7ffae19..da2fb490a36 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -10,7 +10,9 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
 use rustc_errors::{DiagCtxt, ErrorGuaranteed};
 use rustc_lint::LintStore;
+
 use rustc_middle::ty;
+use rustc_middle::ty::CurrentGcx;
 use rustc_middle::util::Providers;
 use rustc_parse::maybe_new_parser_from_source_str;
 use rustc_query_impl::QueryCtxt;
@@ -39,6 +41,7 @@ pub struct Compiler {
     pub sess: Session,
     pub codegen_backend: Box<dyn CodegenBackend>,
     pub(crate) override_queries: Option<fn(&Session, &mut Providers)>,
+    pub(crate) current_gcx: CurrentGcx,
 }
 
 /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`.
@@ -336,7 +339,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
     util::run_in_thread_pool_with_globals(
         config.opts.edition,
         config.opts.unstable_opts.threads,
-        || {
+        |current_gcx| {
             crate::callbacks::setup_callbacks();
 
             let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
@@ -430,8 +433,12 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             }
             sess.lint_store = Some(Lrc::new(lint_store));
 
-            let compiler =
-                Compiler { sess, codegen_backend, override_queries: config.override_queries };
+            let compiler = Compiler {
+                sess,
+                codegen_backend,
+                override_queries: config.override_queries,
+                current_gcx,
+            };
 
             rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || {
                 // There are two paths out of `f`.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 4b4c1d6cf67..d763a12f816 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -680,6 +680,7 @@ pub fn create_global_ctxt<'tcx>(
                     incremental,
                 ),
                 providers.hooks,
+                compiler.current_gcx.clone(),
             )
         })
     })
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 8a27e9a6453..3b78e6a43ab 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -315,30 +315,39 @@ fn test_search_paths_tracking_hash_different_order() {
         json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
     };
 
+    let push = |opts: &mut Options, search_path| {
+        opts.search_paths.push(SearchPath::from_cli_opt(
+            "not-a-sysroot".as_ref(),
+            &opts.target_triple,
+            &early_dcx,
+            search_path,
+        ));
+    };
+
     // Reference
-    v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
-    v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
-    v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
-    v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
-    v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
-
-    v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
-    v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
-    v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
-    v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
-    v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
-
-    v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
-    v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
-    v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
-    v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
-    v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
-
-    v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
-    v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
-    v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
-    v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
-    v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
+    push(&mut v1, "native=abc");
+    push(&mut v1, "crate=def");
+    push(&mut v1, "dependency=ghi");
+    push(&mut v1, "framework=jkl");
+    push(&mut v1, "all=mno");
+
+    push(&mut v2, "native=abc");
+    push(&mut v2, "dependency=ghi");
+    push(&mut v2, "crate=def");
+    push(&mut v2, "framework=jkl");
+    push(&mut v2, "all=mno");
+
+    push(&mut v3, "crate=def");
+    push(&mut v3, "framework=jkl");
+    push(&mut v3, "native=abc");
+    push(&mut v3, "dependency=ghi");
+    push(&mut v3, "all=mno");
+
+    push(&mut v4, "all=mno");
+    push(&mut v4, "native=abc");
+    push(&mut v4, "crate=def");
+    push(&mut v4, "dependency=ghi");
+    push(&mut v4, "framework=jkl");
 
     assert_same_hash(&v1, &v2);
     assert_same_hash(&v1, &v3);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index d09f8d7d7cf..d0f04fccc48 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -5,6 +5,7 @@ use rustc_codegen_ssa::traits::CodegenBackend;
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sync;
 use rustc_metadata::{load_symbol_from_dylib, DylibError};
+use rustc_middle::ty::CurrentGcx;
 use rustc_parse::validate_attr;
 use rustc_session as session;
 use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes};
@@ -64,7 +65,7 @@ fn init_stack_size() -> usize {
     })
 }
 
-pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     f: F,
 ) -> R {
@@ -82,7 +83,9 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
         // `unwrap` is ok here because `spawn_scoped` only panics if the thread
         // name contains null bytes.
         let r = builder
-            .spawn_scoped(s, move || rustc_span::create_session_globals_then(edition, f))
+            .spawn_scoped(s, move || {
+                rustc_span::create_session_globals_then(edition, || f(CurrentGcx::new()))
+            })
             .unwrap()
             .join();
 
@@ -94,7 +97,7 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
 }
 
 #[cfg(not(parallel_compiler))]
-pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     _threads: usize,
     f: F,
@@ -103,7 +106,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
 }
 
 #[cfg(parallel_compiler)]
-pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     threads: usize,
     f: F,
@@ -117,24 +120,34 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
     let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
 
     if !sync::is_dyn_thread_safe() {
-        return run_in_thread_with_globals(edition, || {
+        return run_in_thread_with_globals(edition, |current_gcx| {
             // Register the thread for use with the `WorkerLocal` type.
             registry.register();
 
-            f()
+            f(current_gcx)
         });
     }
 
+    let current_gcx = FromDyn::from(CurrentGcx::new());
+    let current_gcx2 = current_gcx.clone();
+
     let builder = rayon::ThreadPoolBuilder::new()
         .thread_name(|_| "rustc".to_string())
         .acquire_thread_handler(jobserver::acquire_thread)
         .release_thread_handler(jobserver::release_thread)
         .num_threads(threads)
-        .deadlock_handler(|| {
+        .deadlock_handler(move || {
             // On deadlock, creates a new thread and forwards information in thread
             // locals to it. The new thread runs the deadlock handler.
-            let query_map =
-                FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs()));
+
+            // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a
+            // `TyCtxt` TLS reference here.
+            let query_map = current_gcx2.access(|gcx| {
+                tls::enter_context(&tls::ImplicitCtxt::new(gcx), || {
+                    tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())
+                })
+            });
+            let query_map = FromDyn::from(query_map);
             let registry = rayon_core::Registry::current();
             thread::Builder::new()
                 .name("rustc query cycle handler".to_string())
@@ -171,7 +184,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
                         })
                     },
                     // Run `f` on the first thread in the thread pool.
-                    move |pool: &rayon::ThreadPool| pool.install(f),
+                    move |pool: &rayon::ThreadPool| pool.install(|| f(current_gcx.into_inner())),
                 )
                 .unwrap()
         })
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 0b757f95a99..111a4fdcea1 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -865,7 +865,9 @@ trait UnusedDelimLint {
                 (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
             }
 
-            Match(ref head, ..) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
+            Match(ref head, _, ast::MatchKind::Prefix)
+                if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
+            {
                 let left = e.span.lo() + rustc_span::BytePos(5);
                 (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true)
             }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index f6ec410bfac..8ec1f5a99e7 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1992,7 +1992,11 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
         }
       }
       if (DiagnosticHandlerCallback) {
+#if LLVM_VERSION_GE(19, 0)
+        DiagnosticHandlerCallback(&DI, DiagnosticHandlerContext);
+#else
         DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
+#endif
         return true;
       }
       return false;
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/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index e4dce2bdc9e..02af55fbf0e 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -652,8 +652,9 @@ impl<'tcx> Body<'tcx> {
         self.coroutine.as_ref().and_then(|coroutine| coroutine.resume_ty)
     }
 
+    /// Prefer going through [`TyCtxt::coroutine_layout`] rather than using this directly.
     #[inline]
-    pub fn coroutine_layout(&self) -> Option<&CoroutineLayout<'tcx>> {
+    pub fn coroutine_layout_raw(&self) -> Option<&CoroutineLayout<'tcx>> {
         self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_layout.as_ref())
     }
 
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index f0499cf344f..41df2e3b587 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -126,7 +126,7 @@ fn dump_matched_mir_node<'tcx, F>(
             Some(promoted) => write!(file, "::{promoted:?}`")?,
         }
         writeln!(file, " {disambiguator} {pass_name}")?;
-        if let Some(ref layout) = body.coroutine_layout() {
+        if let Some(ref layout) = body.coroutine_layout_raw() {
             writeln!(file, "/* coroutine_layout = {layout:#?} */")?;
         }
         writeln!(file)?;
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/thir.rs b/compiler/rustc_middle/src/thir.rs
index f684f83a261..b1162a34cda 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -1018,7 +1018,7 @@ impl<'tcx> PatRangeBoundary<'tcx> {
             (Finite(mir::Const::Ty(a)), Finite(mir::Const::Ty(b)))
                 if matches!(ty.kind(), ty::Uint(_) | ty::Char) =>
             {
-                return Some(a.kind().cmp(&b.kind()));
+                return Some(a.to_valtree().cmp(&b.to_valtree()));
             }
             (
                 Finite(mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _)),
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index a04bd636622..efea2a66bb2 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -571,7 +571,8 @@ pub struct MatchExpressionArmCause<'tcx> {
     pub scrut_span: Span,
     pub source: hir::MatchSource,
     pub prior_non_diverging_arms: Vec<Span>,
-    pub opt_suggest_box_span: Option<Span>,
+    // Is the expectation of this match expression an RPIT?
+    pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -582,7 +583,8 @@ pub struct IfExpressionCause<'tcx> {
     pub then_ty: Ty<'tcx>,
     pub else_ty: Ty<'tcx>,
     pub outer_span: Option<Span>,
-    pub opt_suggest_box_span: Option<Span>,
+    // Is the expectation of this match expression an RPIT?
+    pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index a7144316769..a7f1ba46b61 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -18,7 +18,6 @@ use rustc_span::symbol::sym;
 use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
 
 use std::cell::RefCell;
-use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
 use std::ops::Range;
 use std::str;
@@ -102,20 +101,6 @@ pub struct AdtDefData {
     repr: ReprOptions,
 }
 
-impl PartialOrd for AdtDefData {
-    fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `Ord` only based on `did`.
-impl Ord for AdtDefData {
-    fn cmp(&self, other: &AdtDefData) -> Ordering {
-        self.did.cmp(&other.did)
-    }
-}
-
 impl PartialEq for AdtDefData {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
@@ -180,7 +165,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>);
 
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 0d621cd1cfd..3713883eb00 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -23,7 +23,7 @@ pub use valtree::*;
 pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
 
 /// Use this rather than `ConstData`, whenever possible.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
 
@@ -52,7 +52,7 @@ impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> {
 }
 
 /// Typed constant value.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable)]
 pub struct ConstData<'tcx> {
     pub ty: Ty<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 705987d92fe..ea02faca5f3 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 
 /// An unevaluated (potentially generic) constant used in the type-system.
-#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: DefId,
@@ -62,7 +62,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
 pub enum Expr<'tcx> {
     Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 3393f444843..188cb50849d 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -32,6 +32,7 @@ use crate::ty::{
 };
 use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use rustc_ast::{self as ast, attr};
+use rustc_data_structures::defer;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::intern::Interned;
@@ -39,7 +40,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal};
+use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, RwLock, WorkerLocal};
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_data_structures::unord::UnordSet;
@@ -723,6 +724,8 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Stores memory for globals (statics/consts).
     pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
+
+    current_gcx: CurrentGcx,
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
@@ -733,6 +736,19 @@ impl<'tcx> GlobalCtxt<'tcx> {
         F: FnOnce(TyCtxt<'tcx>) -> R,
     {
         let icx = tls::ImplicitCtxt::new(self);
+
+        // Reset `current_gcx` to `None` when we exit.
+        let _on_drop = defer(move || {
+            *self.current_gcx.value.write() = None;
+        });
+
+        // Set this `GlobalCtxt` as the current one.
+        {
+            let mut guard = self.current_gcx.value.write();
+            assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
+            *guard = Some(self as *const _ as *const ());
+        }
+
         tls::enter_context(&icx, || f(icx.tcx))
     }
 
@@ -741,6 +757,39 @@ impl<'tcx> GlobalCtxt<'tcx> {
     }
 }
 
+/// This is used to get a reference to a `GlobalCtxt` if one is available.
+///
+/// This is needed to allow the deadlock handler access to `GlobalCtxt` to look for query cycles.
+/// It cannot use the `TLV` global because that's only guaranteed to be defined on the thread
+/// creating the `GlobalCtxt`. Other threads have access to the `TLV` only inside Rayon jobs, but
+/// the deadlock handler is not called inside such a job.
+#[derive(Clone)]
+pub struct CurrentGcx {
+    /// This stores a pointer to a `GlobalCtxt`. This is set to `Some` inside `GlobalCtxt::enter`
+    /// and reset to `None` when that function returns or unwinds.
+    value: Lrc<RwLock<Option<*const ()>>>,
+}
+
+#[cfg(parallel_compiler)]
+unsafe impl DynSend for CurrentGcx {}
+#[cfg(parallel_compiler)]
+unsafe impl DynSync for CurrentGcx {}
+
+impl CurrentGcx {
+    pub fn new() -> Self {
+        Self { value: Lrc::new(RwLock::new(None)) }
+    }
+
+    pub fn access<R>(&self, f: impl for<'tcx> FnOnce(&'tcx GlobalCtxt<'tcx>) -> R) -> R {
+        let read_guard = self.value.read();
+        let gcx: *const GlobalCtxt<'_> = read_guard.unwrap() as *const _;
+        // SAFETY: We hold the read lock for the `GlobalCtxt` pointer. That prevents
+        // `GlobalCtxt::enter` from returning as it would first acquire the write lock.
+        // This ensures the `GlobalCtxt` is live during `f`.
+        f(unsafe { &*gcx })
+    }
+}
+
 impl<'tcx> TyCtxt<'tcx> {
     /// Expects a body and returns its codegen attributes.
     ///
@@ -859,6 +908,7 @@ impl<'tcx> TyCtxt<'tcx> {
         query_kinds: &'tcx [DepKindStruct<'tcx>],
         query_system: QuerySystem<'tcx>,
         hooks: crate::hooks::Providers,
+        current_gcx: CurrentGcx,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.dcx().emit_fatal(err);
@@ -893,6 +943,7 @@ impl<'tcx> TyCtxt<'tcx> {
             canonical_param_env_cache: Default::default(),
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
+            current_gcx,
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index b57d4f372a7..fd3bee16e26 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -2,8 +2,6 @@ use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::def_id::DefId;
 
-use std::collections::BTreeMap;
-
 pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 
 ///////////////////////////////////////////////////////////////////////////
@@ -254,12 +252,12 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         value: Binder<'tcx, T>,
         mut fld_r: F,
-    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+    ) -> (T, FxIndexMap<ty::BoundRegion, ty::Region<'tcx>>)
     where
         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        let mut region_map = BTreeMap::new();
+        let mut region_map = FxIndexMap::default();
         let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
         let value = self.instantiate_bound_regions_uncached(value, real_fld_r);
         (value, region_map)
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 02b58c035d4..19cef927faf 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -17,7 +17,6 @@ use rustc_type_ir::WithCachedTypeInfo;
 use smallvec::SmallVec;
 
 use core::intrinsics;
-use std::cmp::Ordering;
 use std::marker::PhantomData;
 use std::mem;
 use std::num::NonZero;
@@ -68,7 +67,7 @@ const TYPE_TAG: usize = 0b00;
 const REGION_TAG: usize = 0b01;
 const CONST_TAG: usize = 0b10;
 
-#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, HashStable)]
 pub enum GenericArgKind<'tcx> {
     Lifetime(ty::Region<'tcx>),
     Type(Ty<'tcx>),
@@ -100,18 +99,6 @@ impl<'tcx> GenericArgKind<'tcx> {
     }
 }
 
-impl<'tcx> Ord for GenericArg<'tcx> {
-    fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering {
-        self.unpack().cmp(&other.unpack())
-    }
-}
-
-impl<'tcx> PartialOrd for GenericArg<'tcx> {
-    fn partial_cmp(&self, other: &GenericArg<'tcx>) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
 impl<'tcx> From<ty::Region<'tcx>> for GenericArg<'tcx> {
     #[inline]
     fn from(r: ty::Region<'tcx>) -> GenericArg<'tcx> {
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/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6ce53ccc8cd..66fee515ab2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -60,6 +60,7 @@ pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
 pub use vtable::*;
 
+use std::assert_matches::assert_matches;
 use std::fmt::Debug;
 use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
@@ -86,8 +87,8 @@ pub use self::consts::{
     Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
-    tls, CtxtInterners, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
-    TyCtxtFeed,
+    tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
+    TyCtxt, TyCtxtFeed,
 };
 pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
 pub use self::list::List;
@@ -214,7 +215,6 @@ pub struct ResolverAstLowering {
     pub next_node_id: ast::NodeId,
 
     pub node_id_to_def_id: NodeMap<LocalDefId>,
-    pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
 
     pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
     /// List functions and methods for which lifetime elision was successful.
@@ -516,7 +516,7 @@ pub struct CReaderCacheKey {
 }
 
 /// Use this rather than `TyKind`, whenever possible.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
 #[rustc_diagnostic_item = "Ty"]
 #[rustc_pass_by_value]
 pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
@@ -701,7 +701,7 @@ const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
 const CONST_TAG: usize = 0b01;
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable)]
 pub enum TermKind<'tcx> {
     Ty(Ty<'tcx>),
@@ -832,6 +832,38 @@ pub struct OpaqueTypeKey<'tcx> {
     pub args: GenericArgsRef<'tcx>,
 }
 
+impl<'tcx> OpaqueTypeKey<'tcx> {
+    pub fn iter_captured_args(
+        self,
+        tcx: TyCtxt<'tcx>,
+    ) -> impl Iterator<Item = (usize, GenericArg<'tcx>)> {
+        std::iter::zip(self.args, tcx.variances_of(self.def_id)).enumerate().filter_map(
+            |(i, (arg, v))| match (arg.unpack(), v) {
+                (_, ty::Invariant) => Some((i, arg)),
+                (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None,
+                _ => bug!("unexpected opaque type arg variance"),
+            },
+        )
+    }
+
+    pub fn fold_captured_lifetime_args(
+        self,
+        tcx: TyCtxt<'tcx>,
+        mut f: impl FnMut(Region<'tcx>) -> Region<'tcx>,
+    ) -> Self {
+        let Self { def_id, args } = self;
+        let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| {
+            match (arg.unpack(), v) {
+                (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
+                (ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(),
+                _ => arg,
+            }
+        });
+        let args = tcx.mk_args_from_iter(args);
+        Self { def_id, args }
+    }
+}
+
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
 pub struct OpaqueHiddenType<'tcx> {
     /// The span of this particular definition of the opaque type. So
@@ -979,7 +1011,7 @@ impl PlaceholderLike for PlaceholderType {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
-#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
+#[derive(TyEncodable, TyDecodable)]
 pub struct BoundConst<'tcx> {
     pub var: BoundVar,
     pub ty: Ty<'tcx>,
@@ -1826,8 +1858,40 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Returns layout of a coroutine. Layout might be unavailable if the
     /// coroutine is tainted by errors.
-    pub fn coroutine_layout(self, def_id: DefId) -> Option<&'tcx CoroutineLayout<'tcx>> {
-        self.optimized_mir(def_id).coroutine_layout()
+    ///
+    /// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
+    /// e.g. `args.as_coroutine().kind_ty()`.
+    pub fn coroutine_layout(
+        self,
+        def_id: DefId,
+        coroutine_kind_ty: Ty<'tcx>,
+    ) -> Option<&'tcx CoroutineLayout<'tcx>> {
+        let mir = self.optimized_mir(def_id);
+        // Regular coroutine
+        if coroutine_kind_ty.is_unit() {
+            mir.coroutine_layout_raw()
+        } else {
+            // If we have a `Coroutine` that comes from an coroutine-closure,
+            // then it may be a by-move or by-ref body.
+            let ty::Coroutine(_, identity_args) =
+                *self.type_of(def_id).instantiate_identity().kind()
+            else {
+                unreachable!();
+            };
+            let identity_kind_ty = identity_args.as_coroutine().kind_ty();
+            // If the types differ, then we must be getting the by-move body of
+            // a by-ref coroutine.
+            if identity_kind_ty == coroutine_kind_ty {
+                mir.coroutine_layout_raw()
+            } else {
+                assert_matches!(coroutine_kind_ty.to_opt_closure_kind(), Some(ClosureKind::FnOnce));
+                assert_matches!(
+                    identity_kind_ty.to_opt_closure_kind(),
+                    Some(ClosureKind::Fn | ClosureKind::FnMut)
+                );
+                mir.coroutine_by_move_body().unwrap().coroutine_layout_raw()
+            }
+        }
     }
 
     /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index d3bc7dd22e7..05156dd5205 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -192,7 +192,7 @@ impl<'tcx> Clause<'tcx> {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub enum ExistentialPredicate<'tcx> {
     /// E.g., `Iterator`.
@@ -336,7 +336,7 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
 ///
 /// Trait references also appear in object types like `Foo<U>`, but in
 /// that case the `Self` parameter is absent from the generic parameters.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
@@ -420,7 +420,7 @@ impl<'tcx> IntoDiagArg for TraitRef<'tcx> {
 /// ```
 /// The generic parameters don't include the erased `Self`, only trait
 /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialTraitRef<'tcx> {
     pub def_id: DefId,
@@ -476,7 +476,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
 }
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialProjection<'tcx> {
     pub def_id: DefId,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3f0a3a1a7bf..5ff98dc8c87 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -10,6 +10,7 @@ use crate::ty::{
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::unord::UnordMap;
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -24,7 +25,6 @@ use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 
 use std::cell::Cell;
-use std::collections::BTreeMap;
 use std::fmt::{self, Write as _};
 use std::iter;
 use std::ops::{Deref, DerefMut};
@@ -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));
@@ -2529,7 +2537,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
 struct RegionFolder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     current_index: ty::DebruijnIndex,
-    region_map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+    region_map: UnordMap<ty::BoundRegion, ty::Region<'tcx>>,
     name: &'a mut (
                 dyn FnMut(
         Option<ty::DebruijnIndex>, // Debruijn index of the folded late-bound region
@@ -2606,7 +2614,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
     pub fn name_all_regions<T>(
         &mut self,
         value: &ty::Binder<'tcx, T>,
-    ) -> Result<(T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
+    ) -> Result<(T, UnordMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -2683,7 +2691,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                 write!(self, "{var:?}")?;
             }
             start_or_continue(self, "", "> ");
-            (value.clone().skip_binder(), BTreeMap::default())
+            (value.clone().skip_binder(), UnordMap::default())
         } else {
             let tcx = self.tcx;
 
@@ -2755,7 +2763,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                 tcx,
                 current_index: ty::INNERMOST,
                 name: &mut name,
-                region_map: BTreeMap::new(),
+                region_map: UnordMap::default(),
             };
             let new_value = value.clone().skip_binder().fold_with(&mut folder);
             let region_map = folder.region_map;
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index c66b9864e46..867faf63261 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -14,7 +14,7 @@ use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
 pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
 
 /// Use this rather than `RegionKind`, whenever possible.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
 
@@ -327,7 +327,7 @@ impl<'tcx> Deref for Region<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct EarlyParamRegion {
     pub def_id: DefId,
@@ -358,7 +358,7 @@ impl Atom for RegionVid {
     }
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
+#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
 #[derive(HashStable)]
 /// The parameter representation of late-bound function parameters, "some region
 /// at least as big as the scope `fr.scope`".
@@ -367,7 +367,7 @@ pub struct LateParamRegion {
     pub bound_region: BoundRegionKind,
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
+#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
 #[derive(HashStable)]
 pub enum BoundRegionKind {
     /// An anonymous region parameter for a given fn (&T)
@@ -384,7 +384,7 @@ pub enum BoundRegionKind {
     BrEnv,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct BoundRegion {
     pub var: BoundVar,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c85ee140fa4..57a675e4453 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -694,7 +694,8 @@ impl<'tcx> CoroutineArgs<'tcx> {
     #[inline]
     pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
         // FIXME requires optimized MIR
-        FIRST_VARIANT..tcx.coroutine_layout(def_id).unwrap().variant_fields.next_index()
+        FIRST_VARIANT
+            ..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index()
     }
 
     /// The discriminant for the given variant. Panics if the `variant_index` is
@@ -754,7 +755,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
     ) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
-        let layout = tcx.coroutine_layout(def_id).unwrap();
+        let layout = tcx.coroutine_layout(def_id, self.kind_ty()).unwrap();
         layout.variant_fields.iter().map(move |variant| {
             variant.iter().map(move |field| {
                 ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)
@@ -867,7 +868,7 @@ impl<'tcx> InlineConstArgs<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundVariableKind {
     Ty(BoundTyKind),
@@ -907,7 +908,7 @@ impl BoundVariableKind {
 /// e.g., `liberate_late_bound_regions`).
 ///
 /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[derive(HashStable, Lift)]
 pub struct Binder<'tcx, T> {
     value: T,
@@ -1108,7 +1109,7 @@ where
 /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
 /// * For an inherent projection, this would be `Ty::N<...>`.
 /// * For an opaque type, there is no explicit syntax.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct AliasTy<'tcx> {
     /// The parameters of the associated or opaque item.
@@ -1277,7 +1278,7 @@ pub struct GenSig<'tcx> {
 /// - `inputs`: is the list of arguments and their modes.
 /// - `output`: is the return type.
 /// - `c_variadic`: indicates whether this is a C-variadic function.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct FnSig<'tcx> {
     pub inputs_and_output: &'tcx List<Ty<'tcx>>,
@@ -1402,14 +1403,14 @@ impl ParamConst {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct BoundTy {
     pub var: BoundVar,
     pub kind: BoundTyKind,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundTyKind {
     Anon,
@@ -2660,7 +2661,7 @@ impl<'tcx> Ty<'tcx> {
 /// a miscompilation or unsoundness.
 ///
 /// When in doubt, use `VarianceDiagInfo::default()`
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
 pub enum VarianceDiagInfo<'tcx> {
     /// No additional information - this is the default.
     /// We will not add any additional information to error messages.
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 f4f452d474f..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,
@@ -1106,7 +1111,10 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
 #[derive(Debug, Clone)]
 pub(crate) struct MatchPair<'pat, 'tcx> {
     /// This place...
-    place: PlaceBuilder<'tcx>,
+    // This can be `None` if it referred to a non-captured place in a closure.
+    // Invariant: place.is_none() => test_case is Irrefutable
+    // In other words this must be `Some(_)` after simplification.
+    place: Option<Place<'tcx>>,
 
     /// ... must pass this test...
     // Invariant: after creation and simplification in `Candidate::new()`, this must not be
@@ -1277,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;
             }
         }
@@ -1287,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(
@@ -1298,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,
@@ -1531,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;
@@ -1550,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 &=
@@ -1559,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);
@@ -1587,11 +1598,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn pick_test(
         &mut self,
         candidates: &mut [&mut Candidate<'_, 'tcx>],
-    ) -> (PlaceBuilder<'tcx>, Test<'tcx>) {
+    ) -> (Place<'tcx>, Test<'tcx>) {
         // Extract the match-pair from the highest priority candidate
         let match_pair = &candidates.first().unwrap().match_pairs[0];
         let test = self.test(match_pair);
-        let match_place = match_pair.place.clone();
+        // Unwrap is ok after simplification.
+        let match_place = match_pair.place.unwrap();
         debug!(?test, ?match_pair);
 
         (match_place, test)
@@ -1632,7 +1644,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
     fn sort_candidates<'b, 'c, 'pat>(
         &mut self,
-        match_place: &PlaceBuilder<'tcx>,
+        match_place: Place<'tcx>,
         test: &Test<'tcx>,
         mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
     ) -> (
@@ -1650,7 +1662,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // sorting.
         while let Some(candidate) = candidates.first_mut() {
             let Some(branch) =
-                self.sort_candidate(&match_place, test, candidate, &target_candidates)
+                self.sort_candidate(match_place, test, candidate, &target_candidates)
             else {
                 break;
             };
@@ -1778,7 +1790,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // For each of the N possible test outcomes, build the vector of candidates that applies if
         // the test has that particular outcome.
         let (remaining_candidates, target_candidates) =
-            self.sort_candidates(&match_place, &test, candidates);
+            self.sort_candidates(match_place, &test, candidates);
 
         // The block that we should branch to if none of the
         // `target_candidates` match.
@@ -1818,7 +1830,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             scrutinee_span,
             start_block,
             remainder_start,
-            &match_place,
+            match_place,
             &test,
             target_blocks,
         );
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_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 9d77bd063e1..b66dd83b7ec 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -5,7 +5,6 @@
 // identify what tests are needed, perform the tests, and then filter
 // the candidates based on the result.
 
-use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind};
 use crate::build::Builder;
 use rustc_data_structures::fx::FxIndexMap;
@@ -55,18 +54,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         Test { span: match_pair.pattern.span, kind }
     }
 
-    #[instrument(skip(self, target_blocks, place_builder), level = "debug")]
+    #[instrument(skip(self, target_blocks, place), level = "debug")]
     pub(super) fn perform_test(
         &mut self,
         match_start_span: Span,
         scrutinee_span: Span,
         block: BasicBlock,
         otherwise_block: BasicBlock,
-        place_builder: &PlaceBuilder<'tcx>,
+        place: Place<'tcx>,
         test: &Test<'tcx>,
         target_blocks: FxIndexMap<TestBranch<'tcx>, BasicBlock>,
     ) {
-        let place = place_builder.to_place(self);
         let place_ty = place.ty(&self.local_decls, self.tcx);
         debug!(?place, ?place_ty);
         let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block);
@@ -475,7 +473,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// tighter match code if we do something a bit different.
     pub(super) fn sort_candidate(
         &mut self,
-        test_place: &PlaceBuilder<'tcx>,
+        test_place: Place<'tcx>,
         test: &Test<'tcx>,
         candidate: &mut Candidate<'_, 'tcx>,
         sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
@@ -486,8 +484,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // than one, but it'd be very unusual to have two sides that
         // both require tests; you'd expect one side to be simplified
         // away.)
-        let (match_pair_index, match_pair) =
-            candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
+        let (match_pair_index, match_pair) = candidate
+            .match_pairs
+            .iter()
+            .enumerate()
+            .find(|&(_, mp)| mp.place == Some(test_place))?;
 
         let fully_matched;
         let ret = match (&test.kind, &match_pair.test_case) {
@@ -521,7 +522,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     candidate
                         .match_pairs
                         .iter()
-                        .any(|mp| mp.place == *test_place && is_covering_range(&mp.test_case))
+                        .any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case))
                 };
                 if sorted_candidates
                     .get(&TestBranch::Failure)
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 1148cd19a01..bc6f0a26582 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -95,35 +95,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
     pub(in crate::build) fn new(
-        mut place: PlaceBuilder<'tcx>,
+        mut place_builder: PlaceBuilder<'tcx>,
         pattern: &'pat Pat<'tcx>,
         cx: &mut Builder<'_, 'tcx>,
     ) -> MatchPair<'pat, 'tcx> {
         // Force the place type to the pattern's type.
         // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
-        if let Some(resolved) = place.resolve_upvar(cx) {
-            place = resolved;
+        if let Some(resolved) = place_builder.resolve_upvar(cx) {
+            place_builder = resolved;
         }
 
         // Only add the OpaqueCast projection if the given place is an opaque type and the
         // expected type from the pattern is not.
-        let may_need_cast = match place.base() {
+        let may_need_cast = match place_builder.base() {
             PlaceBase::Local(local) => {
-                let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
+                let ty =
+                    Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx).ty;
                 ty != pattern.ty && ty.has_opaque_types()
             }
             _ => true,
         };
         if may_need_cast {
-            place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
+            place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
         }
 
+        let place = place_builder.try_to_place(cx);
         let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
         let mut subpairs = Vec::new();
         let test_case = match pattern.kind {
             PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
             PatKind::Or { ref pats } => TestCase::Or {
-                pats: pats.iter().map(|pat| FlatPat::new(place.clone(), pat, cx)).collect(),
+                pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
             },
 
             PatKind::Range(ref range) => {
@@ -142,13 +144,13 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                 ..
             } => {
                 // Apply the type ascription to the value at `match_pair.place`
-                let ascription = place.try_to_place(cx).map(|source| super::Ascription {
+                let ascription = place.map(|source| super::Ascription {
                     annotation: annotation.clone(),
                     source,
                     variance,
                 });
 
-                subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
+                subpairs.push(MatchPair::new(place_builder, subpattern, cx));
                 TestCase::Irrefutable { ascription, binding: None }
             }
 
@@ -161,7 +163,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                 ref subpattern,
                 is_primary: _,
             } => {
-                let binding = place.try_to_place(cx).map(|source| super::Binding {
+                let binding = place.map(|source| super::Binding {
                     span: pattern.span,
                     source,
                     var_id: var,
@@ -170,14 +172,14 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
 
                 if let Some(subpattern) = subpattern.as_ref() {
                     // this is the `x @ P` case; have to keep matching against `P` now
-                    subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
+                    subpairs.push(MatchPair::new(place_builder, subpattern, cx));
                 }
                 TestCase::Irrefutable { ascription: None, binding }
             }
 
             PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
                 // Apply a type ascription for the inline constant to the value at `match_pair.place`
-                let ascription = place.try_to_place(cx).map(|source| {
+                let ascription = place.map(|source| {
                     let span = pattern.span;
                     let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
                     let args = ty::InlineConstArgs::new(
@@ -203,16 +205,16 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                     super::Ascription { annotation, source, variance: ty::Contravariant }
                 });
 
-                subpairs.push(MatchPair::new(place.clone(), pattern, cx));
+                subpairs.push(MatchPair::new(place_builder, pattern, cx));
                 TestCase::Irrefutable { ascription, binding: None }
             }
 
             PatKind::Array { ref prefix, ref slice, ref suffix } => {
-                cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
+                cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix);
                 default_irrefutable()
             }
             PatKind::Slice { ref prefix, ref slice, ref suffix } => {
-                cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
+                cx.prefix_slice_suffix(&mut subpairs, &place_builder, prefix, slice, suffix);
 
                 if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
                     default_irrefutable()
@@ -225,7 +227,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
             }
 
             PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => {
-                let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
+                let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)`
                 subpairs = cx.field_match_pairs(downcast_place, subpatterns);
 
                 let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
@@ -247,13 +249,12 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
             }
 
             PatKind::Leaf { ref subpatterns } => {
-                subpairs = cx.field_match_pairs(place.clone(), subpatterns);
+                subpairs = cx.field_match_pairs(place_builder, subpatterns);
                 default_irrefutable()
             }
 
             PatKind::Deref { ref subpattern } => {
-                let place_builder = place.clone().deref();
-                subpairs.push(MatchPair::new(place_builder, subpattern, cx));
+                subpairs.push(MatchPair::new(place_builder.deref(), subpattern, cx));
                 default_irrefutable()
             }
 
@@ -310,8 +311,8 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
             }
         } else {
             // Insert a Shallow borrow of any place that is switched on.
-            if let Some(resolved_place) = match_pair.place.try_to_place(self.cx) {
-                self.fake_borrows.insert(resolved_place);
+            if let Some(place) = match_pair.place {
+                self.fake_borrows.insert(place);
             }
 
             for subpair in &match_pair.subpairs {
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_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index bff59aa6023..8ad7bc394c5 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -14,11 +14,7 @@ pub struct UnreachablePropagation;
 impl MirPass<'_> for UnreachablePropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable.
-
-        // FIXME(#116171) Coverage gets confused by MIR passes that can remove all
-        // coverage statements from an instrumented function. This pass can be
-        // re-enabled when coverage codegen is robust against that happening.
-        sess.mir_opt_level() >= 2 && !sess.instrument_coverage()
+        sess.mir_opt_level() >= 2
     }
 
     fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
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/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 7e317c3df14..18fb858c84c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2768,7 +2768,7 @@ impl<'a> Parser<'a> {
                 };
                 return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) {
                     // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the
-                    // parser state and emit a targetted suggestion.
+                    // parser state and emit a targeted suggestion.
                     let span = vec![start_span, self.token.span];
                     let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
                     self.bump(); // )
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..869cbebbc0d 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;
@@ -19,9 +24,10 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt};
 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 +60,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 +110,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 +139,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,
             },
@@ -141,16 +163,6 @@ impl<'tcx> ReachableContext<'tcx> {
         if !self.any_library {
             // If we are building an executable, only explicitly extern
             // types need to be exported.
-            let reachable =
-                if let Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })
-                | Node::ImplItem(hir::ImplItem {
-                    kind: hir::ImplItemKind::Fn(sig, ..), ..
-                }) = *node
-                {
-                    sig.header.abi != Abi::Rust
-                } else {
-                    false
-                };
             let codegen_attrs = if self.tcx.def_kind(search_item).has_codegen_attrs() {
                 self.tcx.codegen_fn_attrs(search_item)
             } else {
@@ -159,7 +171,7 @@ impl<'tcx> ReachableContext<'tcx> {
             let is_extern = codegen_attrs.contains_extern_indicator();
             let std_internal =
                 codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
-            if reachable || is_extern || std_internal {
+            if is_extern || std_internal {
                 self.reachable_symbols.insert(search_item);
             }
         } else {
@@ -174,7 +186,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 +240,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 +328,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 +406,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 +440,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/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 476b31f44ae..4057bc9ffbd 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2730,7 +2730,7 @@ pub(crate) fn import_candidates(
     );
 }
 
-type PathString<'a> = (String, &'a str, Option<DefId>, &'a Option<String>, bool);
+type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
 
 /// When an entity with a given name is not available in scope, we search for
 /// entities with that name in all crates. This method allows outputting the
@@ -2762,7 +2762,7 @@ fn show_candidates(
                 accessible_path_strings.push((
                     pprust::path_to_string(&c.path),
                     c.descr,
-                    c.did,
+                    c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
                     &c.note,
                     c.via_import,
                 ))
@@ -2771,7 +2771,7 @@ fn show_candidates(
             inaccessible_path_strings.push((
                 pprust::path_to_string(&c.path),
                 c.descr,
-                c.did,
+                c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
                 &c.note,
                 c.via_import,
             ))
@@ -2889,15 +2889,14 @@ fn show_candidates(
     } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagMode::Import { .. })) {
         let prefix =
             if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
-        if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] {
+        if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
             let msg = format!(
                 "{prefix}{descr} `{name}`{} exists but is inaccessible",
                 if let DiagMode::Pattern = mode { ", which" } else { "" }
             );
 
-            if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
-                let span = tcx.source_span(local_def_id);
-                let span = tcx.sess.source_map().guess_head_span(span);
+            if let Some(source_span) = source_span {
+                let span = tcx.sess.source_map().guess_head_span(*source_span);
                 let mut multi_span = MultiSpan::from_span(span);
                 multi_span.push_span_label(span, "not accessible");
                 err.span_note(multi_span, msg);
@@ -2925,10 +2924,9 @@ fn show_candidates(
             let mut has_colon = false;
 
             let mut spans = Vec::new();
-            for (name, _, def_id, _, _) in &inaccessible_path_strings {
-                if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
-                    let span = tcx.source_span(local_def_id);
-                    let span = tcx.sess.source_map().guess_head_span(span);
+            for (name, _, source_span, _, _) in &inaccessible_path_strings {
+                if let Some(source_span) = source_span {
+                    let span = tcx.sess.source_map().guess_head_span(*source_span);
                     spans.push((name, span));
                 } else {
                     if !has_colon {
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..39ccf6d3714 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,
@@ -1605,7 +1618,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 .into_items()
                 .map(|(k, f)| (k, f.key()))
                 .collect(),
-            def_id_to_node_id: self.def_id_to_node_id,
             trait_map: self.trait_map,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
             lint_buffer: Steal::new(self.lint_buffer),
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c06fe29c567..f612e8b5b1a 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2795,11 +2795,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
     let debuginfo = select_debuginfo(matches, &cg);
     let debuginfo_compression = unstable_opts.debuginfo_compression;
 
-    let mut search_paths = vec![];
-    for s in &matches.opt_strs("L") {
-        search_paths.push(SearchPath::from_cli_opt(early_dcx, s));
-    }
-
     let libs = parse_libs(early_dcx, matches);
 
     let test = matches.opt_present("test");
@@ -2848,6 +2843,11 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
     };
 
+    let mut search_paths = vec![];
+    for s in &matches.opt_strs("L") {
+        search_paths.push(SearchPath::from_cli_opt(&sysroot, &target_triple, early_dcx, s));
+    }
+
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
         early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
     });
diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs
index 32d5e430717..16dd40acef0 100644
--- a/compiler/rustc_session/src/search_paths.rs
+++ b/compiler/rustc_session/src/search_paths.rs
@@ -1,5 +1,6 @@
 use crate::filesearch::make_target_lib_path;
 use crate::EarlyDiagCtxt;
+use rustc_target::spec::TargetTriple;
 use std::path::{Path, PathBuf};
 
 #[derive(Clone, Debug)]
@@ -46,7 +47,12 @@ impl PathKind {
 }
 
 impl SearchPath {
-    pub fn from_cli_opt(early_dcx: &EarlyDiagCtxt, path: &str) -> Self {
+    pub fn from_cli_opt(
+        sysroot: &Path,
+        triple: &TargetTriple,
+        early_dcx: &EarlyDiagCtxt,
+        path: &str,
+    ) -> Self {
         let (kind, path) = if let Some(stripped) = path.strip_prefix("native=") {
             (PathKind::Native, stripped)
         } else if let Some(stripped) = path.strip_prefix("crate=") {
@@ -60,12 +66,17 @@ impl SearchPath {
         } else {
             (PathKind::All, path)
         };
-        if path.is_empty() {
+        let dir = match path.strip_prefix("@RUSTC_BUILTIN") {
+            Some(stripped) => {
+                make_target_lib_path(sysroot, triple.triple()).join("builtin").join(stripped)
+            }
+            None => PathBuf::from(path),
+        };
+        if dir.as_os_str().is_empty() {
             #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
             early_dcx.early_fatal("empty search path given via `-L`");
         }
 
-        let dir = PathBuf::from(path);
         Self::new(kind, dir)
     }
 
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 0c811d7dff1..8f721bac951 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -218,8 +218,6 @@ rustc_index::newtype_index! {
 ///
 /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`.
 #[derive(Clone, PartialEq, Eq, Copy)]
-// Don't derive order on 64-bit big-endian, so we can be consistent regardless of field order.
-#[cfg_attr(not(all(target_pointer_width = "64", target_endian = "big")), derive(PartialOrd, Ord))]
 // On below-64 bit systems we can simply use the derived `Hash` impl
 #[cfg_attr(not(target_pointer_width = "64"), derive(Hash))]
 #[repr(C)]
@@ -236,6 +234,12 @@ pub struct DefId {
     pub index: DefIndex,
 }
 
+// To ensure correctness of incremental compilation,
+// `DefId` must not implement `Ord` or `PartialOrd`.
+// See https://github.com/rust-lang/rust/issues/90317.
+impl !Ord for DefId {}
+impl !PartialOrd for DefId {}
+
 // On 64-bit systems, we can hash the whole `DefId` as one `u64` instead of two `u32`s. This
 // improves performance without impairing `FxHash` quality. So the below code gets compiled to a
 // noop on little endian systems because the memory layout of `DefId` is as follows:
@@ -261,22 +265,6 @@ impl Hash for DefId {
     }
 }
 
-// Implement the same comparison as derived with the other field order.
-#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
-impl Ord for DefId {
-    #[inline]
-    fn cmp(&self, other: &DefId) -> std::cmp::Ordering {
-        Ord::cmp(&(self.index, self.krate), &(other.index, other.krate))
-    }
-}
-#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
-impl PartialOrd for DefId {
-    #[inline]
-    fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
 impl DefId {
     /// Makes a local `DefId` from the given `DefIndex`.
     #[inline]
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 616a7ccc7c6..0c974ef4ca3 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -427,6 +427,17 @@ impl FileName {
         src.hash(&mut hasher);
         FileName::InlineAsm(hasher.finish())
     }
+
+    /// Returns the path suitable for reading from the file system on the local host,
+    /// if this information exists.
+    /// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
+    pub fn into_local_path(self) -> Option<PathBuf> {
+        match self {
+            FileName::Real(path) => path.into_local_path(),
+            FileName::DocTest(path, _) => Some(path),
+            _ => None,
+        }
+    }
 }
 
 /// Represents a span.
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..04b92fbd33b 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
@@ -1112,8 +1112,36 @@ pub fn typeid_for_instance<'tcx>(
     mut instance: Instance<'tcx>,
     options: TypeIdOptions,
 ) -> String {
-    if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
-        instance.args = strip_receiver_auto(tcx, instance.args)
+    if (matches!(instance.def, ty::InstanceDef::Virtual(..))
+        && Some(instance.def_id()) == tcx.lang_items().drop_in_place_fn())
+        || matches!(instance.def, ty::InstanceDef::DropGlue(..))
+    {
+        // Adjust the type ids of DropGlues
+        //
+        // DropGlues may have indirect calls to one or more given types drop function. Rust allows
+        // for types to be erased to any trait object and retains the drop function for the original
+        // type, which means at the indirect call sites in DropGlues, when typeid_for_fnabi is
+        // called a second time, it only has information after type erasure and it could be a call
+        // on any arbitrary trait object. Normalize them to a synthesized Drop trait object, both on
+        // declaration/definition, and during code generation at call sites so they have the same
+        // type id and match.
+        //
+        // FIXME(rcvalle): This allows a drop call on any trait object to call the drop function of
+        //   any other type.
+        //
+        let def_id = tcx
+            .lang_items()
+            .drop_trait()
+            .unwrap_or_else(|| bug!("typeid_for_instance: couldn't get drop_trait lang item"));
+        let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef {
+            def_id: def_id,
+            args: List::empty(),
+        });
+        let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]);
+        let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn);
+        instance.args = tcx.mk_args_trait(self_ty, List::empty());
+    } else if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
+        instance.args = strip_receiver_auto(tcx, instance.args);
     }
 
     if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
@@ -1124,7 +1152,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 +1183,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 +1213,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 +1231,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_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index 2169e2971d8..703a3206af2 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -19,6 +19,7 @@ pub fn target() -> Target {
             stack_probes: StackProbeType::Inline,
             supported_sanitizers: SanitizerSet::ADDRESS
                 | SanitizerSet::CFI
+                | SanitizerSet::KCFI
                 | SanitizerSet::LEAK
                 | SanitizerSet::MEMORY
                 | SanitizerSet::MEMTAG
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
index 98374023dc5..11fb28a9aed 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
     base.static_position_independent_executables = true;
     base.supported_sanitizers = SanitizerSet::ADDRESS
         | SanitizerSet::CFI
+        | SanitizerSet::KCFI
         | SanitizerSet::DATAFLOW
         | SanitizerSet::LEAK
         | SanitizerSet::MEMORY
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 3cc46b5c638..7a62030353d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -21,6 +21,7 @@ use crate::traits::{
 };
 use core::ops::ControlFlow;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::unord::UnordSet;
 use rustc_errors::codes::*;
 use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan, StringPart};
 use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, FatalError, StashKey};
@@ -2117,7 +2118,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 })
                 .collect();
 
-            impl_candidates.sort();
+            impl_candidates.sort_by_key(|tr| tr.to_string());
             impl_candidates.dedup();
             return report(impl_candidates, err);
         }
@@ -2143,7 +2144,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 cand
             })
             .collect();
-        impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
+        impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref.to_string()));
         let mut impl_candidates: Vec<_> =
             impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
         impl_candidates.dedup();
@@ -2243,14 +2244,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         };
 
         let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let traits_with_same_path: std::collections::BTreeSet<_> = self
+        let traits_with_same_path: UnordSet<_> = self
             .tcx
             .all_traits()
             .filter(|trait_def_id| *trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path)
+            .map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id))
+            .filter(|(p, _)| *p == required_trait_path)
             .collect();
+
+        let traits_with_same_path =
+            traits_with_same_path.into_items().into_sorted_stable_ord_by_key(|(p, _)| p);
         let mut suggested = false;
-        for trait_with_same_path in traits_with_same_path {
+        for (_, trait_with_same_path) in traits_with_same_path {
             let trait_impls = get_trait_impls(trait_with_same_path);
             if trait_impls.is_empty() {
                 continue;
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 3f433a9e919..29d063321a7 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
 
 use super::NormalizeExt;
 use super::{ObligationCause, PredicateObligation, SelectionContext};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Diag;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{InferCtxt, InferOk};
@@ -431,8 +431,8 @@ pub struct BoundVarReplacer<'me, 'tcx> {
     // These three maps track the bound variable that were replaced by placeholders. It might be
     // nice to remove these since we already have the `kind` in the placeholder; we really just need
     // the `var` (but we *could* bring that into scope if we were to track them as we pass them).
-    mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
-    mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+    mapped_regions: FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion>,
+    mapped_types: FxIndexMap<ty::PlaceholderType, ty::BoundTy>,
     mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
     // The current depth relative to *this* folding, *not* the entire normalization. In other words,
     // the depth of binders we've passed here.
@@ -451,12 +451,13 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
         value: T,
     ) -> (
         T,
-        BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
-        BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+        FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion>,
+        FxIndexMap<ty::PlaceholderType, ty::BoundTy>,
         BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
     ) {
-        let mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion> = BTreeMap::new();
-        let mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy> = BTreeMap::new();
+        let mapped_regions: FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion> =
+            FxIndexMap::default();
+        let mapped_types: FxIndexMap<ty::PlaceholderType, ty::BoundTy> = FxIndexMap::default();
         let mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar> = BTreeMap::new();
 
         let mut replacer = BoundVarReplacer {
@@ -574,8 +575,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
 /// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
 pub struct PlaceholderReplacer<'me, 'tcx> {
     infcx: &'me InferCtxt<'tcx>,
-    mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
-    mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+    mapped_regions: FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion>,
+    mapped_types: FxIndexMap<ty::PlaceholderType, ty::BoundTy>,
     mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
     universe_indices: &'me [Option<ty::UniverseIndex>],
     current_index: ty::DebruijnIndex,
@@ -584,8 +585,8 @@ pub struct PlaceholderReplacer<'me, 'tcx> {
 impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
     pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
         infcx: &'me InferCtxt<'tcx>,
-        mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
-        mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
+        mapped_regions: FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion>,
+        mapped_types: FxIndexMap<ty::PlaceholderType, ty::BoundTy>,
         mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
         universe_indices: &'me [Option<ty::UniverseIndex>],
         value: T,
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index a7c60c3b490..0377ed5d4c5 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -65,7 +65,7 @@ pub mod rustc {
     use std::fmt::{self, Write};
 
     /// A reference in the layout.
-    #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)]
+    #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
     pub struct Ref<'tcx> {
         pub lifetime: ty::Region<'tcx>,
         pub ty: Ty<'tcx>,
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/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 9c3d39307b2..331970ac362 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -745,7 +745,7 @@ fn coroutine_layout<'tcx>(
     let tcx = cx.tcx;
     let instantiate_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).instantiate(tcx, args);
 
-    let Some(info) = tcx.coroutine_layout(def_id) else {
+    let Some(info) = tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()) else {
         return Err(error(cx, LayoutError::Unknown(ty)));
     };
     let (ineligible_locals, assignments) = coroutine_saved_local_eligibility(info);
@@ -1072,7 +1072,7 @@ fn variant_info_for_coroutine<'tcx>(
         return (vec![], None);
     };
 
-    let coroutine = cx.tcx.optimized_mir(def_id).coroutine_layout().unwrap();
+    let coroutine = cx.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()).unwrap();
     let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
 
     let mut upvars_size = Size::ZERO;
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 0aaaad5af05..5b08140db3a 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -8,15 +8,7 @@ use self::ConstKind::*;
 
 /// Represents a constant in Rust.
 #[derive(derivative::Derivative)]
-#[derivative(
-    Clone(bound = ""),
-    Copy(bound = ""),
-    PartialOrd(bound = ""),
-    PartialOrd = "feature_allow_slow_enum",
-    Ord(bound = ""),
-    Ord = "feature_allow_slow_enum",
-    Hash(bound = "")
-)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum ConstKind<I: Interner> {
     /// A const generic parameter.
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 373540de05e..ae1e1902f14 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -9,16 +9,16 @@ use crate::{
 };
 
 pub trait Interner: Sized {
-    type DefId: Copy + Debug + Hash + Ord;
-    type AdtDef: Copy + Debug + Hash + Ord;
+    type DefId: Copy + Debug + Hash + Eq;
+    type AdtDef: Copy + Debug + Hash + Eq;
 
     type GenericArgs: Copy
         + DebugWithInfcx<Self>
         + Hash
-        + Ord
+        + Eq
         + IntoIterator<Item = Self::GenericArg>;
-    type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Ord;
-    type Term: Copy + Debug + Hash + Ord;
+    type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type Term: Copy + Debug + Hash + Eq;
 
     type Binder<T: TypeVisitable<Self>>: BoundVars<Self> + TypeSuperVisitable<Self>;
     type BoundVars: IntoIterator<Item = Self::BoundVar>;
@@ -30,56 +30,56 @@ pub trait Interner: Sized {
     type Ty: Copy
         + DebugWithInfcx<Self>
         + Hash
-        + Ord
+        + Eq
         + Into<Self::GenericArg>
         + IntoKind<Kind = TyKind<Self>>
         + TypeSuperVisitable<Self>
         + Flags
         + new::Ty<Self>;
-    type Tys: Copy + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
-    type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Ord;
-    type ParamTy: Copy + Debug + Hash + Ord;
-    type BoundTy: Copy + Debug + Hash + Ord;
-    type PlaceholderTy: Copy + Debug + Hash + Ord + PlaceholderLike;
+    type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
+    type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type ParamTy: Copy + Debug + Hash + Eq;
+    type BoundTy: Copy + Debug + Hash + Eq;
+    type PlaceholderTy: Copy + Debug + Hash + Eq + PlaceholderLike;
 
     // Things stored inside of tys
-    type ErrorGuaranteed: Copy + Debug + Hash + Ord;
-    type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Ord;
-    type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Ord;
-    type AllocId: Copy + Debug + Hash + Ord;
+    type ErrorGuaranteed: Copy + Debug + Hash + Eq;
+    type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type AllocId: Copy + Debug + Hash + Eq;
 
     // Kinds of consts
     type Const: Copy
         + DebugWithInfcx<Self>
         + Hash
-        + Ord
+        + Eq
         + Into<Self::GenericArg>
         + IntoKind<Kind = ConstKind<Self>>
         + ConstTy<Self>
         + TypeSuperVisitable<Self>
         + Flags
         + new::Const<Self>;
-    type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
-    type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike;
-    type ParamConst: Copy + Debug + Hash + Ord;
-    type BoundConst: Copy + Debug + Hash + Ord;
-    type ValueConst: Copy + Debug + Hash + Ord;
-    type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type PlaceholderConst: Copy + Debug + Hash + Eq + PlaceholderLike;
+    type ParamConst: Copy + Debug + Hash + Eq;
+    type BoundConst: Copy + Debug + Hash + Eq;
+    type ValueConst: Copy + Debug + Hash + Eq;
+    type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
 
     // Kinds of regions
     type Region: Copy
         + DebugWithInfcx<Self>
         + Hash
-        + Ord
+        + Eq
         + Into<Self::GenericArg>
         + IntoKind<Kind = RegionKind<Self>>
         + Flags
         + new::Region<Self>;
-    type EarlyParamRegion: Copy + Debug + Hash + Ord;
-    type LateParamRegion: Copy + Debug + Hash + Ord;
-    type BoundRegion: Copy + Debug + Hash + Ord;
-    type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Ord;
-    type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike;
+    type EarlyParamRegion: Copy + Debug + Hash + Eq;
+    type LateParamRegion: Copy + Debug + Hash + Eq;
+    type BoundRegion: Copy + Debug + Hash + Eq;
+    type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type PlaceholderRegion: Copy + Debug + Hash + Eq + PlaceholderLike;
 
     // Predicates
     type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 2e8481df56d..e1247e2661a 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -113,15 +113,7 @@ use self::RegionKind::*;
 /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
 #[derive(derivative::Derivative)]
-#[derivative(
-    Clone(bound = ""),
-    Copy(bound = ""),
-    PartialOrd(bound = ""),
-    PartialOrd = "feature_allow_slow_enum",
-    Ord(bound = ""),
-    Ord = "feature_allow_slow_enum",
-    Hash(bound = "")
-)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum RegionKind<I: Interner> {
     /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 5ed73cd94f4..fad67fe3cbb 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -63,15 +63,7 @@ impl AliasKind {
 /// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
 #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
 #[derive(derivative::Derivative)]
-#[derivative(
-    Clone(bound = ""),
-    Copy(bound = ""),
-    PartialOrd(bound = ""),
-    PartialOrd = "feature_allow_slow_enum",
-    Ord(bound = ""),
-    Ord = "feature_allow_slow_enum",
-    Hash(bound = "")
-)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum TyKind<I: Interner> {
     /// The primitive boolean type. Written as `bool`.
@@ -803,8 +795,6 @@ impl<I: Interner> DebugWithInfcx<I> for InferTy {
 #[derivative(
     Clone(bound = ""),
     Copy(bound = ""),
-    PartialOrd(bound = ""),
-    Ord(bound = ""),
     PartialEq(bound = ""),
     Eq(bound = ""),
     Hash(bound = ""),
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/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 0a894258f46..66eb991c6d4 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -354,7 +354,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
                 // SAFETY: There is no tree yet so no reference to it exists.
                 let map = unsafe { self.dormant_map.awaken() };
                 let mut root = NodeRef::new_leaf(self.alloc.clone());
-                let val_ptr = root.borrow_mut().push(self.key, value) as *mut V;
+                let val_ptr = root.borrow_mut().push(self.key, value);
                 map.root = Some(root.forget_type());
                 map.length = 1;
                 val_ptr
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index 0c7f94ccceb..6a64eaf576b 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -408,7 +408,7 @@ impl CString {
                 fn strlen(s: *const c_char) -> usize;
             }
             let len = strlen(ptr) + 1; // Including the NUL byte
-            let slice = slice::from_raw_parts_mut(ptr, len as usize);
+            let slice = slice::from_raw_parts_mut(ptr, len);
             CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
         }
     }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 02d155aaf12..20b7d0afa87 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)]
@@ -169,6 +170,7 @@
 #![feature(unicode_internals)]
 #![feature(unsize)]
 #![feature(utf8_chunks)]
+#![feature(vec_pop_if)]
 // tidy-alphabetical-end
 //
 // Language features:
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 0ee293db73a..175e23b543c 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -114,7 +114,10 @@ impl<T> RawVec<T, Global> {
     #[must_use]
     #[inline]
     pub fn with_capacity(capacity: usize) -> Self {
-        handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global))
+        match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global) {
+            Ok(res) => res,
+            Err(err) => handle_error(err),
+        }
     }
 
     /// Like `with_capacity`, but guarantees the buffer is zeroed.
@@ -152,7 +155,10 @@ impl<T, A: Allocator> RawVec<T, A> {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
-        handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc))
+        match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc) {
+            Ok(res) => res,
+            Err(err) => handle_error(err),
+        }
     }
 
     /// Like `try_with_capacity`, but parameterized over the choice of
@@ -167,7 +173,10 @@ impl<T, A: Allocator> RawVec<T, A> {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
-        handle_reserve(Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc))
+        match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc) {
+            Ok(res) => res,
+            Err(err) => handle_error(err),
+        }
     }
 
     /// Converts the entire buffer into `Box<[MaybeUninit<T>]>` with the specified `len`.
@@ -326,7 +335,9 @@ impl<T, A: Allocator> RawVec<T, A> {
             len: usize,
             additional: usize,
         ) {
-            handle_reserve(slf.grow_amortized(len, additional));
+            if let Err(err) = slf.grow_amortized(len, additional) {
+                handle_error(err);
+            }
         }
 
         if self.needs_to_grow(len, additional) {
@@ -339,7 +350,9 @@ impl<T, A: Allocator> RawVec<T, A> {
     #[cfg(not(no_global_oom_handling))]
     #[inline(never)]
     pub fn reserve_for_push(&mut self, len: usize) {
-        handle_reserve(self.grow_amortized(len, 1));
+        if let Err(err) = self.grow_amortized(len, 1) {
+            handle_error(err);
+        }
     }
 
     /// The same as `reserve`, but returns on errors instead of panicking or aborting.
@@ -373,7 +386,9 @@ impl<T, A: Allocator> RawVec<T, A> {
     /// Aborts on OOM.
     #[cfg(not(no_global_oom_handling))]
     pub fn reserve_exact(&mut self, len: usize, additional: usize) {
-        handle_reserve(self.try_reserve_exact(len, additional));
+        if let Err(err) = self.try_reserve_exact(len, additional) {
+            handle_error(err);
+        }
     }
 
     /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
@@ -404,7 +419,9 @@ impl<T, A: Allocator> RawVec<T, A> {
     /// Aborts on OOM.
     #[cfg(not(no_global_oom_handling))]
     pub fn shrink_to_fit(&mut self, cap: usize) {
-        handle_reserve(self.shrink(cap));
+        if let Err(err) = self.shrink(cap) {
+            handle_error(err);
+        }
     }
 }
 
@@ -559,12 +576,11 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
 
 // Central function for reserve error handling.
 #[cfg(not(no_global_oom_handling))]
-#[inline]
-fn handle_reserve<T>(result: Result<T, TryReserveError>) -> T {
-    match result.map_err(|e| e.kind()) {
-        Ok(res) => res,
-        Err(CapacityOverflow) => capacity_overflow(),
-        Err(AllocError { layout, .. }) => handle_alloc_error(layout),
+#[cold]
+fn handle_error(e: TryReserveError) -> ! {
+    match e.kind() {
+        CapacityOverflow => capacity_overflow(),
+        AllocError { layout, .. } => handle_alloc_error(layout),
     }
 }
 
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/slice.rs b/library/alloc/src/slice.rs
index 21d5dce04a0..ebe6f7e7caa 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -511,9 +511,9 @@ impl<T> [T] {
             while m > 0 {
                 // `buf.extend(buf)`:
                 unsafe {
-                    ptr::copy_nonoverlapping(
+                    ptr::copy_nonoverlapping::<T>(
                         buf.as_ptr(),
-                        (buf.as_mut_ptr() as *mut T).add(buf.len()),
+                        (buf.as_mut_ptr()).add(buf.len()),
                         buf.len(),
                     );
                     // `buf` has capacity of `self.len() * n`.
@@ -532,9 +532,9 @@ impl<T> [T] {
             // `buf.extend(buf[0 .. rem_len])`:
             unsafe {
                 // This is non-overlapping since `2^expn > rem`.
-                ptr::copy_nonoverlapping(
+                ptr::copy_nonoverlapping::<T>(
                     buf.as_ptr(),
-                    (buf.as_mut_ptr() as *mut T).add(buf.len()),
+                    (buf.as_mut_ptr()).add(buf.len()),
                     rem_len,
                 );
                 // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
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/task.rs b/library/alloc/src/task.rs
index b40768a52b6..a3fa6585a37 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -148,7 +148,7 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
     unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
         unsafe { Arc::increment_strong_count(waker as *const W) };
         RawWaker::new(
-            waker as *const (),
+            waker,
             &RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
         )
     }
@@ -320,7 +320,7 @@ fn local_raw_waker<W: LocalWake + 'static>(waker: Rc<W>) -> RawWaker {
     unsafe fn clone_waker<W: LocalWake + 'static>(waker: *const ()) -> RawWaker {
         unsafe { Rc::increment_strong_count(waker as *const W) };
         RawWaker::new(
-            waker as *const (),
+            waker,
             &RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
         )
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 94bed825bb2..8ca8046dac5 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2058,6 +2058,31 @@ impl<T, A: Allocator> Vec<T, A> {
         }
     }
 
+    /// Removes and returns the last element in a vector if the predicate
+    /// returns `true`, or [`None`] if the predicate returns false or the vector
+    /// is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_pop_if)]
+    ///
+    /// let mut vec = vec![1, 2, 3, 4];
+    /// let pred = |x: &mut i32| *x % 2 == 0;
+    ///
+    /// assert_eq!(vec.pop_if(pred), Some(4));
+    /// assert_eq!(vec, [1, 2, 3]);
+    /// assert_eq!(vec.pop_if(pred), None);
+    /// ```
+    #[unstable(feature = "vec_pop_if", issue = "122741")]
+    pub fn pop_if<F>(&mut self, f: F) -> Option<T>
+    where
+        F: FnOnce(&mut T) -> bool,
+    {
+        let last = self.last_mut()?;
+        if f(last) { self.pop() } else { None }
+    }
+
     /// Moves all the elements of `other` into `self`, leaving `other` empty.
     ///
     /// # Panics
@@ -2772,6 +2797,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/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index f58998fbd79..04709af5c0a 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -43,6 +43,7 @@
 #![feature(strict_provenance)]
 #![feature(drain_keep_rest)]
 #![feature(local_waker)]
+#![feature(vec_pop_if)]
 #![allow(internal_features)]
 #![deny(fuzzy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index f1f841fe190..71d79893e01 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -2644,6 +2644,36 @@ fn test_vec_from_array_mut_ref() {
     assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
 }
 
+#[test]
+fn test_pop_if() {
+    let mut v = vec![1, 2, 3, 4];
+    let pred = |x: &mut i32| *x % 2 == 0;
+
+    assert_eq!(v.pop_if(pred), Some(4));
+    assert_eq!(v, [1, 2, 3]);
+
+    assert_eq!(v.pop_if(pred), None);
+    assert_eq!(v, [1, 2, 3]);
+}
+
+#[test]
+fn test_pop_if_empty() {
+    let mut v = Vec::<i32>::new();
+    assert_eq!(v.pop_if(|_| true), None);
+    assert!(v.is_empty());
+}
+
+#[test]
+fn test_pop_if_mutates() {
+    let mut v = vec![1];
+    let pred = |x: &mut i32| {
+        *x += 1;
+        false
+    };
+    assert_eq!(v.pop_if(pred), None);
+    assert_eq!(v, [2]);
+}
+
 /// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments
 /// in the stdlib. Draining and extending the allocation are fairly well-tested earlier, but
 /// `vec.insert(usize::MAX, val)` once slipped by!
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/macros/mod.rs b/library/core/src/macros/mod.rs
index a78842c8f8d..574a357b44a 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1726,20 +1726,28 @@ pub(crate) mod builtin {
         builtin # deref($pat)
     }
 
-    /// Unstable implementation detail of the `rustc` compiler, do not use.
+    /// Derive macro for `rustc-serialize`. Should not be used in new code.
     #[rustc_builtin_macro]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[allow_internal_unstable(core_intrinsics, libstd_sys_internals, rt)]
+    #[unstable(
+        feature = "rustc_encodable_decodable",
+        issue = "none",
+        soft,
+        reason = "derive macro for `rustc-serialize`; should not be used in new code"
+    )]
     #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")]
     #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it.
     pub macro RustcDecodable($item:item) {
         /* compiler built-in */
     }
 
-    /// Unstable implementation detail of the `rustc` compiler, do not use.
+    /// Derive macro for `rustc-serialize`. Should not be used in new code.
     #[rustc_builtin_macro]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[allow_internal_unstable(core_intrinsics, rt)]
+    #[unstable(
+        feature = "rustc_encodable_decodable",
+        issue = "none",
+        soft,
+        reason = "derive macro for `rustc-serialize`; should not be used in new code"
+    )]
     #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")]
     #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it.
     pub macro RustcEncodable($item:item) {
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/num/nonzero.rs b/library/core/src/num/nonzero.rs
index c65ffbb98f2..1171407c07a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -20,7 +20,15 @@ use super::{IntErrorKind, ParseIntError};
 ///
 /// # Safety
 ///
-/// Types implementing this trait must be primitves that are valid when zeroed.
+/// Types implementing this trait must be primitives that are valid when zeroed.
+///
+/// The associated `Self::NonZeroInner` type must have the same size+align as `Self`,
+/// but with a niche and bit validity making it so the following `transmutes` are sound:
+///
+/// - `Self::NonZeroInner` to `Option<Self::NonZeroInner>`
+/// - `Option<Self::NonZeroInner>` to `Self`
+///
+/// (And, consequently, `Self::NonZeroInner` to `Self`.)
 #[unstable(
     feature = "nonzero_internals",
     reason = "implementation detail which may disappear or be replaced at any time",
@@ -434,17 +442,11 @@ where
         // of some not-inlined function, LLVM don't have range metadata
         // to understand that the value cannot be zero.
         //
-        // SAFETY: `Self` is guaranteed to have the same layout as `Option<Self>`.
-        match unsafe { intrinsics::transmute_unchecked(self) } {
-            None => {
-                // SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
-                unsafe { intrinsics::unreachable() }
-            }
-            Some(Self(inner)) => {
-                // SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
-                unsafe { intrinsics::transmute_unchecked(inner) }
-            }
-        }
+        // For now, using the transmute `assume`s the range at runtime.
+        //
+        // SAFETY: `ZeroablePrimitive` guarantees that the size and bit validity
+        // of `.0` is such that this transmute is sound.
+        unsafe { intrinsics::transmute_unchecked(self) }
     }
 }
 
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/pin.rs b/library/core/src/pin.rs
index d14cac9afb5..e843a5d5790 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -806,7 +806,7 @@
 //!
 //!     As a consequence, the struct *must not* be [`#[repr(packed)]`][packed].
 //!
-//! 3.  *Structural Notice of Destruction.* You must uphold the the
+//! 3.  *Structural Notice of Destruction.* You must uphold the
 //!     [`Drop` guarantee][drop-guarantee]: once your struct is pinned, the struct's storage cannot
 //!     be re-used without calling the structurally-pinned fields' destructors, as well.
 //!
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/common.rs
index 29f73bb4942..b98f3a4659b 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/common.rs
@@ -1,9 +1,7 @@
-//! The first version of the core prelude.
+//! Items common to the prelude of all editions.
 //!
 //! See the [module-level documentation](super) for more.
 
-#![stable(feature = "core_prelude", since = "1.4.0")]
-
 // Re-exported core operators
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
@@ -68,11 +66,6 @@ pub use crate::{
 #[doc(no_inline)]
 pub use crate::concat_bytes;
 
-// Do not `doc(inline)` these `doc(hidden)` items.
-#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow(deprecated)]
-pub use crate::macros::builtin::{RustcDecodable, RustcEncodable};
-
 // Do not `doc(no_inline)` so that they become doc items on their own
 // (no public module for them to be re-exported from).
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs
index b4791c2c022..ca33ef160e8 100644
--- a/library/core/src/prelude/mod.rs
+++ b/library/core/src/prelude/mod.rs
@@ -6,7 +6,26 @@
 
 #![stable(feature = "core_prelude", since = "1.4.0")]
 
-pub mod v1;
+mod common;
+
+/// The first version of the prelude of The Rust Standard Library.
+///
+/// See the [module-level documentation](self) for more.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod v1 {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::common::*;
+
+    // Do not `doc(inline)` these `doc(hidden)` items.
+    #[unstable(
+        feature = "rustc_encodable_decodable",
+        issue = "none",
+        soft,
+        reason = "derive macro for `rustc-serialize`; should not be used in new code"
+    )]
+    #[allow(deprecated)]
+    pub use crate::macros::builtin::{RustcDecodable, RustcEncodable};
+}
 
 /// The 2015 version of the core prelude.
 ///
@@ -46,14 +65,21 @@ pub mod rust_2021 {
     pub use crate::convert::{TryFrom, TryInto};
 }
 
-/// The 2024 edition of the core prelude.
+/// The 2024 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
 #[unstable(feature = "prelude_2024", issue = "121042")]
 pub mod rust_2024 {
-    #[unstable(feature = "prelude_2024", issue = "121042")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::common::*;
+
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
+    #[doc(no_inline)]
+    pub use crate::iter::FromIterator;
+
+    #[stable(feature = "prelude_2021", since = "1.55.0")]
     #[doc(no_inline)]
-    pub use super::rust_2021::*;
+    pub use crate::convert::{TryFrom, TryInto};
 
     #[unstable(feature = "prelude_2024", issue = "121042")]
     #[doc(no_inline)]
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/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 00e75ec9a25..77002ef87aa 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -243,7 +243,7 @@ const EMULATE_ATOMIC_BOOL: bool =
 
 /// A boolean type which can be safely shared between threads.
 ///
-/// This type has the same in-memory representation as a [`bool`].
+/// This type has the same size, alignment, and bit validity as a [`bool`].
 ///
 /// **Note**: This type is only available on platforms that support atomic
 /// loads and stores of `u8`.
@@ -272,7 +272,7 @@ unsafe impl Sync for AtomicBool {}
 
 /// A raw pointer type which can be safely shared between threads.
 ///
-/// This type has the same in-memory representation as a `*mut T`.
+/// This type has the same size and bit validity as a `*mut T`.
 ///
 /// **Note**: This type is only available on platforms that support atomic
 /// loads and stores of pointers. Its size depends on the target pointer's size.
@@ -2121,7 +2121,7 @@ macro_rules! atomic_int {
      $int_type:ident $atomic_type:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
-        /// This type has the same in-memory representation as the underlying
+        /// This type has the same size and bit validity as the underlying
         /// integer type, [`
         #[doc = $s_int_type]
         /// `].
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..9017ba79714 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
@@ -385,7 +385,7 @@ impl File {
     /// See the [`OpenOptions::open`] function for more details.
     ///
     /// See also [`std::fs::write()`][self::write] for a simple function to
-    /// create a file with a given data.
+    /// create a file with some given data.
     ///
     /// # Examples
     ///
@@ -1036,7 +1036,7 @@ impl OpenOptions {
     /// [`OpenOptions::append`] access must be used.
     ///
     /// See also [`std::fs::write()`][self::write] for a simple function to
-    /// create a file with a given data.
+    /// create a file with some given data.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index d67493aaf4d..9b01d232611 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -580,6 +580,10 @@ impl io::Read for UnixStream {
         io::Read::read(&mut &*self, buf)
     }
 
+    fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+        io::Read::read_buf(&mut &*self, buf)
+    }
+
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         io::Read::read_vectored(&mut &*self, bufs)
     }
@@ -596,6 +600,10 @@ impl<'a> io::Read for &'a UnixStream {
         self.0.read(buf)
     }
 
+    fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+        self.0.read_buf(buf)
+    }
+
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.0.read_vectored(bufs)
     }
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/common.rs
index 36fa4e88b5b..f61e04e02b6 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/common.rs
@@ -1,9 +1,7 @@
-//! The first version of the prelude of The Rust Standard Library.
+//! Items common to the prelude of all editions.
 //!
 //! See the [module-level documentation](super) for more.
 
-#![stable(feature = "rust1", since = "1.0.0")]
-
 // Re-exported core operators
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
@@ -52,11 +50,6 @@ pub use core::prelude::v1::{
 #[doc(no_inline)]
 pub use core::prelude::v1::concat_bytes;
 
-// Do not `doc(inline)` these `doc(hidden)` items.
-#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow(deprecated)]
-pub use core::prelude::v1::{RustcDecodable, RustcEncodable};
-
 // Do not `doc(no_inline)` so that they become doc items on their own
 // (no public module for them to be re-exported from).
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs
index 7d44d2e4b5d..0bdbab716ad 100644
--- a/library/std/src/prelude/mod.rs
+++ b/library/std/src/prelude/mod.rs
@@ -93,7 +93,26 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-pub mod v1;
+mod common;
+
+/// The first version of the prelude of The Rust Standard Library.
+///
+/// See the [module-level documentation](self) for more.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod v1 {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::common::*;
+
+    // Do not `doc(inline)` these `doc(hidden)` items.
+    #[unstable(
+        feature = "rustc_encodable_decodable",
+        issue = "none",
+        soft,
+        reason = "derive macro for `rustc-serialize`; should not be used in new code"
+    )]
+    #[allow(deprecated)]
+    pub use core::prelude::v1::{RustcDecodable, RustcEncodable};
+}
 
 /// The 2015 version of the prelude of The Rust Standard Library.
 ///
@@ -134,9 +153,8 @@ pub mod rust_2021 {
 /// See the [module-level documentation](self) for more.
 #[unstable(feature = "prelude_2024", issue = "121042")]
 pub mod rust_2024 {
-    #[unstable(feature = "prelude_2024", issue = "121042")]
-    #[doc(no_inline)]
-    pub use super::v1::*;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::common::*;
 
     #[unstable(feature = "prelude_2024", issue = "121042")]
     #[doc(no_inline)]
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index d648cd08994..e0a8a7603d7 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -31,13 +31,14 @@ use crate::sys::sync as sys;
 /// <details><summary>Potential deadlock example</summary>
 ///
 /// ```text
-/// // Thread 1             |  // Thread 2
-/// let _rg = lock.read();  |
-///                         |  // will block
-///                         |  let _wg = lock.write();
-/// // may deadlock         |
-/// let _rg = lock.read();  |
+/// // Thread 1              |  // Thread 2
+/// let _rg1 = lock.read();  |
+///                          |  // will block
+///                          |  let _wg = lock.write();
+/// // may deadlock          |
+/// let _rg2 = lock.read();  |
 /// ```
+///
 /// </details>
 ///
 /// The type parameter `T` represents the data that this lock protects. It is
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index a1c0321876f..9d8cc18b838 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -167,6 +167,8 @@ impl FileDesc {
     }
 
     #[cfg(any(
+        target_os = "aix",
+        target_os = "dragonfly", // DragonFly 1.5
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -174,6 +176,7 @@ impl FileDesc {
         target_os = "illumos",
         target_os = "linux",
         target_os = "netbsd",
+        target_os = "openbsd", // OpenBSD 2.7
     ))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         let ret = cvt(unsafe {
@@ -188,7 +191,9 @@ impl FileDesc {
     }
 
     #[cfg(not(any(
+        target_os = "aix",
         target_os = "android",
+        target_os = "dragonfly",
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -199,6 +204,8 @@ impl FileDesc {
         target_os = "linux",
         target_os = "macos",
         target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "watchos",
     )))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         io::default_read_vectored(|b| self.read_at(b, offset), bufs)
@@ -236,9 +243,10 @@ impl FileDesc {
     // no `syscall` possible in these platform.
     #[cfg(any(
         all(target_os = "android", target_pointer_width = "32"),
-        target_os = "ios",
-        target_os = "tvos",
-        target_os = "macos",
+        target_os = "ios", // ios 14.0
+        target_os = "tvos", // tvos 14.0
+        target_os = "macos", // macos 11.0
+        target_os = "watchos", // watchos 7.0
     ))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
@@ -318,6 +326,8 @@ impl FileDesc {
     }
 
     #[cfg(any(
+        target_os = "aix",
+        target_os = "dragonfly", // DragonFly 1.5
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -325,6 +335,7 @@ impl FileDesc {
         target_os = "illumos",
         target_os = "linux",
         target_os = "netbsd",
+        target_os = "openbsd", // OpenBSD 2.7
     ))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         let ret = cvt(unsafe {
@@ -339,7 +350,9 @@ impl FileDesc {
     }
 
     #[cfg(not(any(
+        target_os = "aix",
         target_os = "android",
+        target_os = "dragonfly",
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -350,6 +363,8 @@ impl FileDesc {
         target_os = "linux",
         target_os = "macos",
         target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "watchos",
     )))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         io::default_write_vectored(|b| self.write_at(b, offset), bufs)
@@ -387,9 +402,10 @@ impl FileDesc {
     // no `syscall` possible in these platform.
     #[cfg(any(
         all(target_os = "android", target_pointer_width = "32"),
-        target_os = "ios",
-        target_os = "tvos",
-        target_os = "macos",
+        target_os = "ios", // ios 14.0
+        target_os = "tvos", // tvos 14.0
+        target_os = "macos", // macos 11.0
+        target_os = "watchos", // watchos 7.0
     ))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
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/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index a3e1b6782e8..4cd7c0e3059 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -424,7 +424,7 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
                     if !set.is_null() {
                         let mut count: usize = 0;
                         if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
-                            for i in 0..u64::MAX {
+                            for i in 0..libc::cpuid_t::MAX {
                                 match libc::_cpuset_isset(i, set) {
                                     -1 => break,
                                     0 => continue,
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 581c46af0ea..2d785064245 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -107,13 +107,13 @@ where
 pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
     match storage.ss_family as c_int {
         c::AF_INET => {
-            assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
+            assert!(len >= mem::size_of::<c::sockaddr_in>());
             Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
                 *(storage as *const _ as *const c::sockaddr_in)
             })))
         }
         c::AF_INET6 => {
-            assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
+            assert!(len >= mem::size_of::<c::sockaddr_in6>());
             Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
                 *(storage as *const _ as *const c::sockaddr_in6)
             })))
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..48596af7ca0 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);
@@ -2601,8 +2605,12 @@ impl Step for Crate {
         let mode = self.mode;
 
         // See [field@compile::Std::force_recompile].
-        builder.ensure(compile::Std::force_recompile(compiler, target));
-        builder.ensure(RemoteCopyLibs { compiler, target });
+        builder.ensure(compile::Std::force_recompile(compiler, compiler.host));
+
+        if builder.config.build != target {
+            builder.ensure(compile::Std::force_recompile(compiler, target));
+            builder.ensure(RemoteCopyLibs { compiler, target });
+        }
 
         // If we're not doing a full bootstrap but we're testing a stage2
         // version of libstd, then what we're actually testing is the libstd
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/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index ef707d179ea..0cdf52bfb00 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -41,7 +41,7 @@ use std::hash::Hash;
 use std::mem;
 use thin_vec::ThinVec;
 
-use crate::core::{self, DocContext, ImplTraitParam};
+use crate::core::{self, DocContext};
 use crate::formats::item_type::ItemType;
 use crate::visit_ast::Module as DocModule;
 
@@ -761,7 +761,7 @@ fn clean_ty_generics<'tcx>(
 ) -> Generics {
     // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
     // since `Clean for ty::Predicate` would consume them.
-    let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
+    let mut impl_trait = BTreeMap::<u32, Vec<GenericBound>>::default();
 
     // Bounds in the type_params and lifetimes fields are repeated in the
     // predicates field (see rustc_hir_analysis::collect::ty_generics), so remove
@@ -778,7 +778,7 @@ fn clean_ty_generics<'tcx>(
                     return None;
                 }
                 if synthetic {
-                    impl_trait.insert(param.index.into(), vec![]);
+                    impl_trait.insert(param.index, vec![]);
                     return None;
                 }
                 Some(clean_generic_param_def(param, cx))
@@ -823,7 +823,7 @@ fn clean_ty_generics<'tcx>(
             })();
 
             if let Some(param_idx) = param_idx
-                && let Some(bounds) = impl_trait.get_mut(&param_idx.into())
+                && let Some(bounds) = impl_trait.get_mut(&param_idx)
             {
                 let pred = clean_predicate(*pred, cx)?;
 
@@ -847,7 +847,7 @@ fn clean_ty_generics<'tcx>(
         })
         .collect::<Vec<_>>();
 
-    for (param, mut bounds) in impl_trait {
+    for (idx, mut bounds) in impl_trait {
         let mut has_sized = false;
         bounds.retain(|b| {
             if b.is_sized_bound(cx) {
@@ -870,7 +870,6 @@ fn clean_ty_generics<'tcx>(
             bounds.insert(0, GenericBound::sized(cx));
         }
 
-        let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
         if let Some(proj) = impl_trait_proj.remove(&idx) {
             for (trait_did, name, rhs) in proj {
                 let rhs = clean_middle_term(rhs, cx);
@@ -878,7 +877,7 @@ fn clean_ty_generics<'tcx>(
             }
         }
 
-        cx.impl_trait_bounds.insert(param, bounds);
+        cx.impl_trait_bounds.insert(idx.into(), bounds);
     }
 
     // Now that `cx.impl_trait_bounds` is populated, we can process
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index be7e319bc79..f078ad2fb53 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -460,8 +460,6 @@ impl Options {
             &matches.free[0]
         });
 
-        let libs =
-            matches.opt_strs("L").iter().map(|s| SearchPath::from_cli_opt(early_dcx, s)).collect();
         let externs = parse_externs(early_dcx, matches, &unstable_opts);
         let extern_html_root_urls = match parse_extern_html_roots(matches) {
             Ok(ex) => ex,
@@ -625,6 +623,20 @@ impl Options {
         }
 
         let target = parse_target_triple(early_dcx, matches);
+        let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
+
+        let sysroot = match &maybe_sysroot {
+            Some(s) => s.clone(),
+            None => {
+                rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
+            }
+        };
+
+        let libs = matches
+            .opt_strs("L")
+            .iter()
+            .map(|s| SearchPath::from_cli_opt(&sysroot, &target, early_dcx, s))
+            .collect();
 
         let show_coverage = matches.opt_present("show-coverage");
 
@@ -653,7 +665,6 @@ impl Options {
         let bin_crate = crate_types.contains(&CrateType::Executable);
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
-        let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
         let module_sorting = if matches.opt_present("sort-modules-by-appearance") {
             ModuleSorting::DeclarationOrder
         } else {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 80a30ac2727..25b78d9598d 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -509,7 +509,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
 
 /// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
 /// for `impl Trait` in argument position.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub(crate) enum ImplTraitParam {
     DefId(DefId),
     ParamIndex(u32),
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 5d4f1acc4b1..fbb521a6188 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1728,6 +1728,8 @@ fn item_variants(
         }
         w.write_str("</h3></section>");
 
+        write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4));
+
         let heading_and_fields = match &variant_data.kind {
             clean::VariantKind::Struct(s) => {
                 // If there is no field to display, no need to add the heading.
@@ -1789,8 +1791,6 @@ fn item_variants(
             }
             w.write_str("</div>");
         }
-
-        write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4));
     }
     write!(w, "</div>");
 }
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index f153a908329..be2786c99ec 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -65,8 +65,9 @@ pub(crate) fn build_index<'tcx>(
     // Sort search index items. This improves the compressibility of the search index.
     cache.search_index.sort_unstable_by(|k1, k2| {
         // `sort_unstable_by_key` produces lifetime errors
-        let k1 = (&k1.path, k1.name.as_str(), &k1.ty, &k1.parent);
-        let k2 = (&k2.path, k2.name.as_str(), &k2.ty, &k2.parent);
+        // HACK(rustdoc): should not be sorting `CrateNum` or `DefIndex`, this will soon go away, too
+        let k1 = (&k1.path, k1.name.as_str(), &k1.ty, k1.parent.map(|id| (id.index, id.krate)));
+        let k2 = (&k2.path, k2.name.as_str(), &k2.ty, k2.parent.map(|id| (id.index, id.krate)));
         Ord::cmp(&k1, &k2)
     });
 
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..e414bc384f1 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -691,9 +691,9 @@ pub fn line_directive<'line>(
     }
 }
 
-/// This is generated by collecting directives from ui tests and then extracting their directive
-/// names. This is **not** an exhaustive list of all possible directives. Instead, this is a
-/// best-effort approximation for diagnostics.
+/// This was originally generated by collecting directives from ui tests and then extracting their
+/// directive names. This is **not** an exhaustive list of all possible directives. Instead, this is
+/// a best-effort approximation for diagnostics. Add new headers to this list when needed.
 const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     // tidy-alphabetical-start
     "assembly-output",
@@ -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",
@@ -826,6 +827,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-cfi",
     "needs-sanitizer-dataflow",
     "needs-sanitizer-hwaddress",
+    "needs-sanitizer-kcfi",
     "needs-sanitizer-leak",
     "needs-sanitizer-memory",
     "needs-sanitizer-memtag",
@@ -835,6 +837,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-thread",
     "needs-threads",
     "needs-unwind",
+    "needs-wasmtime",
     "needs-xray",
     "no-prefer-dynamic",
     "normalize-stderr-32bit",
@@ -870,6 +873,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "only-unix",
     "only-wasm32",
     "only-wasm32-bare",
+    "only-wasm32-wasip1",
     "only-windows",
     "only-x86",
     "only-x86_64",
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index d7c74038aea..db154932d5b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -149,6 +149,11 @@ pub(super) fn handle_needs(
             condition: config.target_cfg().relocation_model == "pic",
             ignore_reason: "ignored on targets without PIC relocation model",
         },
+        Need {
+            name: "needs-wasmtime",
+            condition: config.runner.as_ref().is_some_and(|r| r.contains("wasmtime")),
+            ignore_reason: "ignored when wasmtime runner is not available",
+        },
     ];
 
     let (name, comment) = match ln.split_once([':', ' ']) {
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/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index e547599d954..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";
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 4904a489eae..8fffb91542f 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -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/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/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 419b04231b5..7975677286d 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -1,19 +1,21 @@
+pub mod run;
+pub mod rustc;
+pub mod rustdoc;
+
 use std::env;
-use std::path::{Path, PathBuf};
-use std::process::{Command, Output};
+use std::path::PathBuf;
+use std::process::Output;
 
 pub use object;
 pub use wasmparser;
 
-pub fn out_dir() -> PathBuf {
-    env::var_os("TMPDIR").unwrap().into()
-}
+pub use run::{run, run_fail};
+pub use rustc::{aux_build, rustc, Rustc};
+pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
 
-fn setup_common_build_cmd(command: &str) -> Command {
-    let rustc = env::var(command).unwrap();
-    let mut cmd = Command::new(rustc);
-    cmd.arg("--out-dir").arg(out_dir()).arg("-L").arg(out_dir());
-    cmd
+/// Path of `TMPDIR` (a temporary build directory, not under `/tmp`).
+pub fn tmp_dir() -> PathBuf {
+    env::var_os("TMPDIR").unwrap().into()
 }
 
 fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> ! {
@@ -24,170 +26,3 @@ fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> !
     eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
     std::process::exit(1)
 }
-
-pub fn rustc() -> RustcInvocationBuilder {
-    RustcInvocationBuilder::new()
-}
-
-pub fn aux_build() -> AuxBuildInvocationBuilder {
-    AuxBuildInvocationBuilder::new()
-}
-
-pub fn rustdoc() -> Rustdoc {
-    Rustdoc::new()
-}
-
-#[derive(Debug)]
-pub struct RustcInvocationBuilder {
-    cmd: Command,
-}
-
-impl RustcInvocationBuilder {
-    fn new() -> Self {
-        let cmd = setup_common_build_cmd("RUSTC");
-        Self { cmd }
-    }
-
-    pub fn arg(&mut self, arg: &str) -> &mut RustcInvocationBuilder {
-        self.cmd.arg(arg);
-        self
-    }
-
-    pub fn args(&mut self, args: &[&str]) -> &mut RustcInvocationBuilder {
-        self.cmd.args(args);
-        self
-    }
-
-    #[track_caller]
-    pub fn run(&mut self) -> Output {
-        let caller_location = std::panic::Location::caller();
-        let caller_line_number = caller_location.line();
-
-        let output = self.cmd.output().unwrap();
-        if !output.status.success() {
-            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
-        }
-        output
-    }
-}
-
-#[derive(Debug)]
-pub struct AuxBuildInvocationBuilder {
-    cmd: Command,
-}
-
-impl AuxBuildInvocationBuilder {
-    fn new() -> Self {
-        let mut cmd = setup_common_build_cmd("RUSTC");
-        cmd.arg("--crate-type=lib");
-        Self { cmd }
-    }
-
-    pub fn arg(&mut self, arg: &str) -> &mut AuxBuildInvocationBuilder {
-        self.cmd.arg(arg);
-        self
-    }
-
-    #[track_caller]
-    pub fn run(&mut self) -> Output {
-        let caller_location = std::panic::Location::caller();
-        let caller_line_number = caller_location.line();
-
-        let output = self.cmd.output().unwrap();
-        if !output.status.success() {
-            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
-        }
-        output
-    }
-}
-
-#[derive(Debug)]
-pub struct Rustdoc {
-    cmd: Command,
-}
-
-impl Rustdoc {
-    fn new() -> Self {
-        let cmd = setup_common_build_cmd("RUSTDOC");
-        Self { cmd }
-    }
-
-    pub fn arg(&mut self, arg: &str) -> &mut Self {
-        self.cmd.arg(arg);
-        self
-    }
-
-    #[track_caller]
-    pub fn run(&mut self) -> Output {
-        let caller_location = std::panic::Location::caller();
-        let caller_line_number = caller_location.line();
-
-        let output = self.cmd.output().unwrap();
-        if !output.status.success() {
-            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
-        }
-        output
-    }
-}
-
-fn run_common(bin_name: &str) -> (Command, Output) {
-    let target = env::var("TARGET").unwrap();
-
-    let bin_name =
-        if target.contains("windows") { format!("{}.exe", bin_name) } else { bin_name.to_owned() };
-
-    let mut bin_path = PathBuf::new();
-    bin_path.push(env::var("TMPDIR").unwrap());
-    bin_path.push(&bin_name);
-    let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
-    let mut cmd = Command::new(bin_path);
-    cmd.env(&ld_lib_path_envvar, {
-        let mut paths = vec![];
-        paths.push(PathBuf::from(env::var("TMPDIR").unwrap()));
-        for p in env::split_paths(&env::var("TARGET_RPATH_ENV").unwrap()) {
-            paths.push(p.to_path_buf());
-        }
-        for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) {
-            paths.push(p.to_path_buf());
-        }
-        env::join_paths(paths.iter()).unwrap()
-    });
-
-    if target.contains("windows") {
-        let mut paths = vec![];
-        for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
-            paths.push(p.to_path_buf());
-        }
-        paths.push(Path::new(&std::env::var("TARGET_RPATH_DIR").unwrap()).to_path_buf());
-        cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
-    }
-
-    let output = cmd.output().unwrap();
-    (cmd, output)
-}
-
-/// Run a built binary and make sure it succeeds.
-#[track_caller]
-pub fn run(bin_name: &str) -> Output {
-    let caller_location = std::panic::Location::caller();
-    let caller_line_number = caller_location.line();
-
-    let (cmd, output) = run_common(bin_name);
-    if !output.status.success() {
-        handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
-    }
-    output
-}
-
-/// Run a built binary and make sure it fails.
-#[track_caller]
-pub fn run_fail(bin_name: &str) -> Output {
-    let caller_location = std::panic::Location::caller();
-    let caller_line_number = caller_location.line();
-
-    let (cmd, output) = run_common(bin_name);
-    if output.status.success() {
-        handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
-    }
-    output
-}
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
new file mode 100644
index 00000000000..42dcf54da22
--- /dev/null
+++ b/src/tools/run-make-support/src/run.rs
@@ -0,0 +1,67 @@
+use std::env;
+use std::path::{Path, PathBuf};
+use std::process::{Command, Output};
+
+use super::handle_failed_output;
+
+fn run_common(bin_name: &str) -> (Command, Output) {
+    let target = env::var("TARGET").unwrap();
+
+    let bin_name =
+        if target.contains("windows") { format!("{}.exe", bin_name) } else { bin_name.to_owned() };
+
+    let mut bin_path = PathBuf::new();
+    bin_path.push(env::var("TMPDIR").unwrap());
+    bin_path.push(&bin_name);
+    let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
+    let mut cmd = Command::new(bin_path);
+    cmd.env(&ld_lib_path_envvar, {
+        let mut paths = vec![];
+        paths.push(PathBuf::from(env::var("TMPDIR").unwrap()));
+        for p in env::split_paths(&env::var("TARGET_RPATH_ENV").unwrap()) {
+            paths.push(p.to_path_buf());
+        }
+        for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) {
+            paths.push(p.to_path_buf());
+        }
+        env::join_paths(paths.iter()).unwrap()
+    });
+
+    if target.contains("windows") {
+        let mut paths = vec![];
+        for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
+            paths.push(p.to_path_buf());
+        }
+        paths.push(Path::new(&std::env::var("TARGET_RPATH_DIR").unwrap()).to_path_buf());
+        cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
+    }
+
+    let output = cmd.output().unwrap();
+    (cmd, output)
+}
+
+/// Run a built binary and make sure it succeeds.
+#[track_caller]
+pub fn run(bin_name: &str) -> Output {
+    let caller_location = std::panic::Location::caller();
+    let caller_line_number = caller_location.line();
+
+    let (cmd, output) = run_common(bin_name);
+    if !output.status.success() {
+        handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
+    }
+    output
+}
+
+/// Run a built binary and make sure it fails.
+#[track_caller]
+pub fn run_fail(bin_name: &str) -> Output {
+    let caller_location = std::panic::Location::caller();
+    let caller_line_number = caller_location.line();
+
+    let (cmd, output) = run_common(bin_name);
+    if output.status.success() {
+        handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
+    }
+    output
+}
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
new file mode 100644
index 00000000000..d0ab8df42d2
--- /dev/null
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -0,0 +1,147 @@
+use std::env;
+use std::path::Path;
+use std::process::{Command, Output};
+
+use crate::{handle_failed_output, tmp_dir};
+
+/// Construct a new `rustc` invocation.
+pub fn rustc() -> Rustc {
+    Rustc::new()
+}
+
+/// Construct a new `rustc` aux-build invocation.
+pub fn aux_build() -> Rustc {
+    Rustc::new_aux_build()
+}
+
+/// A `rustc` invocation builder.
+#[derive(Debug)]
+pub struct Rustc {
+    cmd: Command,
+}
+
+fn setup_common() -> Command {
+    let rustc = env::var("RUSTC").unwrap();
+    let mut cmd = Command::new(rustc);
+    cmd.arg("--out-dir").arg(tmp_dir()).arg("-L").arg(tmp_dir());
+    cmd
+}
+
+impl Rustc {
+    // `rustc` invocation constructor methods
+
+    /// Construct a new `rustc` invocation.
+    pub fn new() -> Self {
+        let cmd = setup_common();
+        Self { cmd }
+    }
+
+    /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
+    pub fn new_aux_build() -> Self {
+        let mut cmd = setup_common();
+        cmd.arg("--crate-type=lib");
+        Self { cmd }
+    }
+
+    // Argument provider methods
+
+    /// Configure the compilation environment.
+    pub fn cfg(&mut self, s: &str) -> &mut Self {
+        self.cmd.arg("--cfg");
+        self.cmd.arg(s);
+        self
+    }
+
+    /// Specify default optimization level `-O` (alias for `-C opt-level=2`).
+    pub fn opt(&mut self) -> &mut Self {
+        self.cmd.arg("-O");
+        self
+    }
+
+    /// Specify type(s) of output files to generate.
+    pub fn emit(&mut self, kinds: &str) -> &mut Self {
+        self.cmd.arg(format!("--emit={kinds}"));
+        self
+    }
+
+    /// Specify where an external library is located.
+    pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
+        assert!(
+            !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
+            "crate name cannot contain whitespace or path separators"
+        );
+
+        let path = path.as_ref().to_string_lossy();
+
+        self.cmd.arg("--extern");
+        self.cmd.arg(format!("{crate_name}={path}"));
+
+        self
+    }
+
+    /// Specify path to the input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Specify target triple.
+    pub fn target(&mut self, target: &str) -> &mut Self {
+        assert!(!target.contains(char::is_whitespace), "target triple cannot contain spaces");
+        self.cmd.arg(format!("--target={target}"));
+        self
+    }
+
+    /// Generic command argument provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`.
+    /// This method will panic if a plain `-Z` or `-C` is passed, or if `-Z <name>` or `-C <name>`
+    /// is passed (note the space).
+    pub fn arg(&mut self, arg: &str) -> &mut Self {
+        assert!(
+            !(["-Z", "-C"].contains(&arg) || arg.starts_with("-Z ") || arg.starts_with("-C ")),
+            "use `-Zarg` or `-Carg` over split `-Z` `arg` or `-C` `arg`"
+        );
+        self.cmd.arg(arg);
+        self
+    }
+
+    /// Generic command arguments provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`.
+    /// This method will panic if a plain `-Z` or `-C` is passed, or if `-Z <name>` or `-C <name>`
+    /// is passed (note the space).
+    pub fn args(&mut self, args: &[&str]) -> &mut Self {
+        for arg in args {
+            assert!(
+                !(["-Z", "-C"].contains(&arg) || arg.starts_with("-Z ") || arg.starts_with("-C ")),
+                "use `-Zarg` or `-Carg` over split `-Z` `arg` or `-C` `arg`"
+            );
+        }
+
+        self.cmd.args(args);
+        self
+    }
+
+    // Command inspection, output and running helper methods
+
+    /// Get the [`Output`][std::process::Output] of the finished `rustc` process.
+    pub fn output(&mut self) -> Output {
+        self.cmd.output().unwrap()
+    }
+
+    /// Run the constructed `rustc` command and assert that it is successfully run.
+    #[track_caller]
+    pub fn run(&mut self) -> Output {
+        let caller_location = std::panic::Location::caller();
+        let caller_line_number = caller_location.line();
+
+        let output = self.cmd.output().unwrap();
+        if !output.status.success() {
+            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
+        }
+        output
+    }
+
+    /// Inspect what the underlying [`Command`] is up to the current construction.
+    pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
+        f(&self.cmd);
+        self
+    }
+}
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
new file mode 100644
index 00000000000..9607ff02f96
--- /dev/null
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -0,0 +1,80 @@
+use std::env;
+use std::path::Path;
+use std::process::{Command, Output};
+
+use crate::handle_failed_output;
+
+/// Construct a plain `rustdoc` invocation with no flags set.
+pub fn bare_rustdoc() -> Rustdoc {
+    Rustdoc::bare()
+}
+
+/// Construct a new `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
+pub fn rustdoc() -> Rustdoc {
+    Rustdoc::new()
+}
+
+#[derive(Debug)]
+pub struct Rustdoc {
+    cmd: Command,
+}
+
+fn setup_common() -> Command {
+    let rustdoc = env::var("RUSTDOC").unwrap();
+    Command::new(rustdoc)
+}
+
+impl Rustdoc {
+    /// Construct a bare `rustdoc` invocation.
+    pub fn bare() -> Self {
+        let cmd = setup_common();
+        Self { cmd }
+    }
+
+    /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
+    pub fn new() -> Self {
+        let mut cmd = setup_common();
+        let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
+        cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
+        Self { cmd }
+    }
+
+    /// Specify path to the input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Specify output directory.
+    pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("--out-dir").arg(path.as_ref());
+        self
+    }
+
+    /// Given a `path`, pass `@{path}` to `rustdoc` as an
+    /// [arg file](https://doc.rust-lang.org/rustdoc/command-line-arguments.html#path-load-command-line-flags-from-a-path).
+    pub fn arg_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(format!("@{}", path.as_ref().display()));
+        self
+    }
+
+    /// Fallback argument provider. Consider adding meaningfully named methods instead of using
+    /// this method.
+    pub fn arg(&mut self, arg: &str) -> &mut Self {
+        self.cmd.arg(arg);
+        self
+    }
+
+    /// Run the build `rustdoc` command and assert that the run is successful.
+    #[track_caller]
+    pub fn run(&mut self) -> Output {
+        let caller_location = std::panic::Location::caller();
+        let caller_line_number = caller_location.line();
+
+        let output = self.cmd.output().unwrap();
+        if !output.status.success() {
+            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
+        }
+        output
+    }
+}
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
new file mode 100644
index 00000000000..bdee3afa6b7
--- /dev/null
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -0,0 +1,337 @@
+run-make/alloc-no-oom-handling/Makefile
+run-make/alloc-no-rc/Makefile
+run-make/alloc-no-sync/Makefile
+run-make/allocator-shim-circular-deps/Makefile
+run-make/allow-non-lint-warnings-cmdline/Makefile
+run-make/allow-warnings-cmdline-stability/Makefile
+run-make/archive-duplicate-names/Makefile
+run-make/arguments-non-c-like-enum/Makefile
+run-make/atomic-lock-free/Makefile
+run-make/bare-outfile/Makefile
+run-make/branch-protection-check-IBT/Makefile
+run-make/c-dynamic-dylib/Makefile
+run-make/c-dynamic-rlib/Makefile
+run-make/c-link-to-rust-dylib/Makefile
+run-make/c-link-to-rust-staticlib/Makefile
+run-make/c-link-to-rust-va-list-fn/Makefile
+run-make/c-static-dylib/Makefile
+run-make/c-static-rlib/Makefile
+run-make/c-unwind-abi-catch-lib-panic/Makefile
+run-make/c-unwind-abi-catch-panic/Makefile
+run-make/cat-and-grep-sanity-check/Makefile
+run-make/cdylib-dylib-linkage/Makefile
+run-make/cdylib-fewer-symbols/Makefile
+run-make/cdylib/Makefile
+run-make/codegen-options-parsing/Makefile
+run-make/comment-section/Makefile
+run-make/compile-stdin/Makefile
+run-make/compiler-lookup-paths-2/Makefile
+run-make/compiler-lookup-paths/Makefile
+run-make/compiler-rt-works-on-mingw/Makefile
+run-make/compressed-debuginfo/Makefile
+run-make/const-prop-lint/Makefile
+run-make/const_fn_mir/Makefile
+run-make/core-no-fp-fmt-parse/Makefile
+run-make/core-no-oom-handling/Makefile
+run-make/crate-data-smoke/Makefile
+run-make/crate-hash-rustc-version/Makefile
+run-make/crate-name-priority/Makefile
+run-make/cross-lang-lto-clang/Makefile
+run-make/cross-lang-lto-pgo-smoketest/Makefile
+run-make/cross-lang-lto-upstream-rlibs/Makefile
+run-make/cross-lang-lto/Makefile
+run-make/debug-assertions/Makefile
+run-make/debugger-visualizer-dep-info/Makefile
+run-make/dep-graph/Makefile
+run-make/dep-info-doesnt-run-much/Makefile
+run-make/dep-info-spaces/Makefile
+run-make/dep-info/Makefile
+run-make/doctests-keep-binaries/Makefile
+run-make/doctests-runtool/Makefile
+run-make/dump-ice-to-disk/Makefile
+run-make/dump-mono-stats/Makefile
+run-make/duplicate-output-flavors/Makefile
+run-make/dylib-chain/Makefile
+run-make/emit-named-files/Makefile
+run-make/emit-path-unhashed/Makefile
+run-make/emit-shared-files/Makefile
+run-make/emit-stack-sizes/Makefile
+run-make/emit-to-stdout/Makefile
+run-make/emit/Makefile
+run-make/env-dep-info/Makefile
+run-make/error-found-staticlib-instead-crate/Makefile
+run-make/error-writing-dependencies/Makefile
+run-make/exit-code/Makefile
+run-make/export-executable-symbols/Makefile
+run-make/extern-diff-internal-name/Makefile
+run-make/extern-flag-disambiguates/Makefile
+run-make/extern-flag-fun/Makefile
+run-make/extern-flag-pathless/Makefile
+run-make/extern-flag-rename-transitive/Makefile
+run-make/extern-fn-explicit-align/Makefile
+run-make/extern-fn-generic/Makefile
+run-make/extern-fn-mangle/Makefile
+run-make/extern-fn-reachable/Makefile
+run-make/extern-fn-struct-passing-abi/Makefile
+run-make/extern-fn-with-extern-types/Makefile
+run-make/extern-fn-with-packed-struct/Makefile
+run-make/extern-fn-with-union/Makefile
+run-make/extern-multiple-copies/Makefile
+run-make/extern-multiple-copies2/Makefile
+run-make/extern-overrides-distribution/Makefile
+run-make/extra-filename-with-temp-outputs/Makefile
+run-make/fmt-write-bloat/Makefile
+run-make/forced-unwind-terminate-pof/Makefile
+run-make/foreign-double-unwind/Makefile
+run-make/foreign-exceptions/Makefile
+run-make/foreign-rust-exceptions/Makefile
+run-make/fpic/Makefile
+run-make/glibc-staticlib-args/Makefile
+run-make/hir-tree/Makefile
+run-make/inaccessible-temp-dir/Makefile
+run-make/include_bytes_deps/Makefile
+run-make/incr-add-rust-src-component/Makefile
+run-make/incr-foreign-head-span/Makefile
+run-make/incr-prev-body-beyond-eof/Makefile
+run-make/incremental-debugger-visualizer/Makefile
+run-make/incremental-session-fail/Makefile
+run-make/inline-always-many-cgu/Makefile
+run-make/interdependent-c-libraries/Makefile
+run-make/intrinsic-unreachable/Makefile
+run-make/invalid-library/Makefile
+run-make/invalid-so/Makefile
+run-make/invalid-staticlib/Makefile
+run-make/issue-107094/Makefile
+run-make/issue-10971-temps-dir/Makefile
+run-make/issue-109934-lto-debuginfo/Makefile
+run-make/issue-11908/Makefile
+run-make/issue-14500/Makefile
+run-make/issue-14698/Makefile
+run-make/issue-15460/Makefile
+run-make/issue-18943/Makefile
+run-make/issue-20626/Makefile
+run-make/issue-22131/Makefile
+run-make/issue-24445/Makefile
+run-make/issue-25581/Makefile
+run-make/issue-26006/Makefile
+run-make/issue-26092/Makefile
+run-make/issue-28595/Makefile
+run-make/issue-28766/Makefile
+run-make/issue-30063/Makefile
+run-make/issue-33329/Makefile
+run-make/issue-35164/Makefile
+run-make/issue-36710/Makefile
+run-make/issue-37839/Makefile
+run-make/issue-37893/Makefile
+run-make/issue-38237/Makefile
+run-make/issue-40535/Makefile
+run-make/issue-46239/Makefile
+run-make/issue-47384/Makefile
+run-make/issue-47551/Makefile
+run-make/issue-51671/Makefile
+run-make/issue-53964/Makefile
+run-make/issue-64153/Makefile
+run-make/issue-68794-textrel-on-minimal-lib/Makefile
+run-make/issue-69368/Makefile
+run-make/issue-7349/Makefile
+run-make/issue-83045/Makefile
+run-make/issue-83112-incr-test-moved-file/Makefile
+run-make/issue-84395-lto-embed-bitcode/Makefile
+run-make/issue-85019-moved-src-dir/Makefile
+run-make/issue-85401-static-mir/Makefile
+run-make/issue-85441/Makefile
+run-make/issue-88756-default-output/Makefile
+run-make/issue-97463-abi-param-passing/Makefile
+run-make/issue64319/Makefile
+run-make/jobserver-error/Makefile
+run-make/libs-through-symlinks/Makefile
+run-make/libtest-json/Makefile
+run-make/libtest-junit/Makefile
+run-make/libtest-padding/Makefile
+run-make/libtest-thread-limit/Makefile
+run-make/link-arg/Makefile
+run-make/link-args-order/Makefile
+run-make/link-cfg/Makefile
+run-make/link-dedup/Makefile
+run-make/link-framework/Makefile
+run-make/link-path-order/Makefile
+run-make/linkage-attr-on-static/Makefile
+run-make/llvm-ident/Makefile
+run-make/llvm-outputs/Makefile
+run-make/long-linker-command-lines-cmd-exe/Makefile
+run-make/long-linker-command-lines/Makefile
+run-make/longjmp-across-rust/Makefile
+run-make/ls-metadata/Makefile
+run-make/lto-dylib-dep/Makefile
+run-make/lto-empty/Makefile
+run-make/lto-linkage-used-attr/Makefile
+run-make/lto-no-link-whole-rlib/Makefile
+run-make/lto-readonly-lib/Makefile
+run-make/lto-smoke-c/Makefile
+run-make/lto-smoke/Makefile
+run-make/macos-deployment-target/Makefile
+run-make/macos-fat-archive/Makefile
+run-make/manual-crate-name/Makefile
+run-make/manual-link/Makefile
+run-make/many-crates-but-no-match/Makefile
+run-make/metadata-dep-info/Makefile
+run-make/metadata-flag-frobs-symbols/Makefile
+run-make/min-global-align/Makefile
+run-make/mingw-export-call-convention/Makefile
+run-make/mismatching-target-triples/Makefile
+run-make/missing-crate-dependency/Makefile
+run-make/mixing-deps/Makefile
+run-make/mixing-formats/Makefile
+run-make/mixing-libs/Makefile
+run-make/msvc-opt-minsize/Makefile
+run-make/multiple-emits/Makefile
+run-make/native-link-modifier-bundle/Makefile
+run-make/native-link-modifier-verbatim-linker/Makefile
+run-make/native-link-modifier-verbatim-rustc/Makefile
+run-make/native-link-modifier-whole-archive/Makefile
+run-make/no-alloc-shim/Makefile
+run-make/no-builtins-attribute/Makefile
+run-make/no-builtins-lto/Makefile
+run-make/no-cdylib-as-rdylib/Makefile
+run-make/no-duplicate-libs/Makefile
+run-make/no-input-file/Makefile
+run-make/no-intermediate-extras/Makefile
+run-make/obey-crate-type-flag/Makefile
+run-make/optimization-remarks-dir-pgo/Makefile
+run-make/optimization-remarks-dir/Makefile
+run-make/output-filename-conflicts-with-directory/Makefile
+run-make/output-filename-overwrites-input/Makefile
+run-make/output-type-permutations/Makefile
+run-make/output-with-hyphens/Makefile
+run-make/override-aliased-flags/Makefile
+run-make/overwrite-input/Makefile
+run-make/panic-abort-eh_frame/Makefile
+run-make/panic-impl-transitive/Makefile
+run-make/pass-linker-flags-flavor/Makefile
+run-make/pass-linker-flags-from-dep/Makefile
+run-make/pass-linker-flags/Makefile
+run-make/pass-non-c-like-enum-to-c/Makefile
+run-make/pdb-alt-path/Makefile
+run-make/pdb-buildinfo-cl-cmd/Makefile
+run-make/pgo-branch-weights/Makefile
+run-make/pgo-gen-lto/Makefile
+run-make/pgo-gen-no-imp-symbols/Makefile
+run-make/pgo-gen/Makefile
+run-make/pgo-indirect-call-promotion/Makefile
+run-make/pgo-use/Makefile
+run-make/pointer-auth-link-with-c/Makefile
+run-make/prefer-dylib/Makefile
+run-make/prefer-rlib/Makefile
+run-make/pretty-print-to-file/Makefile
+run-make/pretty-print-with-dep-file/Makefile
+run-make/print-calling-conventions/Makefile
+run-make/print-cfg/Makefile
+run-make/print-native-static-libs/Makefile
+run-make/print-target-list/Makefile
+run-make/profile/Makefile
+run-make/prune-link-args/Makefile
+run-make/raw-dylib-alt-calling-convention/Makefile
+run-make/raw-dylib-c/Makefile
+run-make/raw-dylib-cross-compilation/Makefile
+run-make/raw-dylib-custom-dlltool/Makefile
+run-make/raw-dylib-import-name-type/Makefile
+run-make/raw-dylib-inline-cross-dylib/Makefile
+run-make/raw-dylib-link-ordinal/Makefile
+run-make/raw-dylib-stdcall-ordinal/Makefile
+run-make/redundant-libs/Makefile
+run-make/relocation-model/Makefile
+run-make/relro-levels/Makefile
+run-make/remap-path-prefix-dwarf/Makefile
+run-make/remap-path-prefix/Makefile
+run-make/repr128-dwarf/Makefile
+run-make/reproducible-build-2/Makefile
+run-make/reproducible-build/Makefile
+run-make/resolve-rename/Makefile
+run-make/return-non-c-like-enum-from-c/Makefile
+run-make/return-non-c-like-enum/Makefile
+run-make/rlib-chain/Makefile
+run-make/rlib-format-packed-bundled-libs-2/Makefile
+run-make/rlib-format-packed-bundled-libs-3/Makefile
+run-make/rlib-format-packed-bundled-libs/Makefile
+run-make/rmeta-preferred/Makefile
+run-make/rust-lld-custom-target/Makefile
+run-make/rust-lld/Makefile
+run-make/rustc-macro-dep-files/Makefile
+run-make/rustdoc-determinism/Makefile
+run-make/rustdoc-error-lines/Makefile
+run-make/rustdoc-io-error/Makefile
+run-make/rustdoc-map-file/Makefile
+run-make/rustdoc-output-path/Makefile
+run-make/rustdoc-scrape-examples-invalid-expr/Makefile
+run-make/rustdoc-scrape-examples-macros/Makefile
+run-make/rustdoc-scrape-examples-multiple/Makefile
+run-make/rustdoc-scrape-examples-ordering/Makefile
+run-make/rustdoc-scrape-examples-remap/Makefile
+run-make/rustdoc-scrape-examples-test/Makefile
+run-make/rustdoc-scrape-examples-whitespace/Makefile
+run-make/rustdoc-shared-flags/Makefile
+run-make/rustdoc-target-spec-json-path/Makefile
+run-make/rustdoc-themes/Makefile
+run-make/rustdoc-verify-output-files/Makefile
+run-make/rustdoc-with-out-dir-option/Makefile
+run-make/rustdoc-with-output-option/Makefile
+run-make/rustdoc-with-short-out-dir-option/Makefile
+run-make/sanitizer-cdylib-link/Makefile
+run-make/sanitizer-dylib-link/Makefile
+run-make/sanitizer-staticlib-link/Makefile
+run-make/separate-link-fail/Makefile
+run-make/separate-link/Makefile
+run-make/sepcomp-cci-copies/Makefile
+run-make/sepcomp-inlining/Makefile
+run-make/sepcomp-separate/Makefile
+run-make/share-generics-dylib/Makefile
+run-make/short-ice/Makefile
+run-make/silly-file-names/Makefile
+run-make/simd-ffi/Makefile
+run-make/simple-dylib/Makefile
+run-make/simple-rlib/Makefile
+run-make/split-debuginfo/Makefile
+run-make/stable-symbol-names/Makefile
+run-make/static-dylib-by-default/Makefile
+run-make/static-extern-type/Makefile
+run-make/static-pie/Makefile
+run-make/static-unwinding/Makefile
+run-make/staticlib-blank-lib/Makefile
+run-make/staticlib-dylib-linkage/Makefile
+run-make/std-core-cycle/Makefile
+run-make/stdin-non-utf8/Makefile
+run-make/suspicious-library/Makefile
+run-make/symbol-mangling-hashed/Makefile
+run-make/symbol-visibility/Makefile
+run-make/symbols-include-type-name/Makefile
+run-make/symlinked-extern/Makefile
+run-make/symlinked-libraries/Makefile
+run-make/symlinked-rlib/Makefile
+run-make/sysroot-crates-are-unstable/Makefile
+run-make/target-cpu-native/Makefile
+run-make/target-specs/Makefile
+run-make/target-without-atomic-cas/Makefile
+run-make/test-benches/Makefile
+run-make/test-harness/Makefile
+run-make/thumb-none-cortex-m/Makefile
+run-make/thumb-none-qemu/Makefile
+run-make/track-path-dep-info/Makefile
+run-make/track-pgo-dep-info/Makefile
+run-make/translation/Makefile
+run-make/type-mismatch-same-crate-name/Makefile
+run-make/unknown-mod-stdin/Makefile
+run-make/unstable-flag-required/Makefile
+run-make/use-suggestions-rust-2018/Makefile
+run-make/used-cdylib-macos/Makefile
+run-make/used/Makefile
+run-make/valid-print-requests/Makefile
+run-make/version/Makefile
+run-make/volatile-intrinsics/Makefile
+run-make/wasm-exceptions-nostd/Makefile
+run-make/wasm-override-linker/Makefile
+run-make/weird-output-filenames/Makefile
+run-make/windows-binary-no-external-deps/Makefile
+run-make/windows-safeseh/Makefile
+run-make/windows-spawn/Makefile
+run-make/windows-subsystem/Makefile
+run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
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/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 670b7eb2be9..57436e8d7fe 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -69,6 +69,7 @@ mod fluent_used;
 pub(crate) mod iter_header;
 pub mod mir_opt_tests;
 pub mod pal;
+pub mod run_make_tests;
 pub mod rustdoc_css_themes;
 pub mod rustdoc_gui_tests;
 pub mod style;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 2bce246c308..93be4d61a9a 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -103,6 +103,8 @@ fn main() {
         check!(tests_revision_unpaired_stdout_stderr, &tests_path);
         check!(debug_artifacts, &tests_path);
         check!(ui_tests, &root_path, bless);
+        // FIXME(jieyouxu): remove this check once all run-make tests are ported over to rmake.rs.
+        check!(run_make_tests, &tests_path, &src_path, bless);
         check!(mir_opt_tests, &tests_path, bless);
         check!(rustdoc_gui_tests, &tests_path);
         check!(rustdoc_css_themes, &librustdoc_path);
diff --git a/src/tools/tidy/src/run_make_tests.rs b/src/tools/tidy/src/run_make_tests.rs
new file mode 100644
index 00000000000..98021cec130
--- /dev/null
+++ b/src/tools/tidy/src/run_make_tests.rs
@@ -0,0 +1,89 @@
+//! Tidy check to ensure that no new Makefiles are added under `tests/run-make/`.
+
+use std::collections::BTreeSet;
+use std::fs::File;
+use std::io::Write;
+use std::path::{Path, PathBuf};
+
+pub fn check(tests_path: &Path, src_path: &Path, bless: bool, bad: &mut bool) {
+    let allowed_makefiles = {
+        let allowed_makefiles = include_str!("allowed_run_make_makefiles.txt");
+        let allowed_makefiles = allowed_makefiles.lines().collect::<Vec<_>>();
+        let is_sorted = allowed_makefiles.windows(2).all(|w| w[0] < w[1]);
+        if !is_sorted && !bless {
+            tidy_error!(
+                bad,
+                "`src/tools/tidy/src/allowed_run_make_makefiles.txt` is not in order, likely \
+                because you modified it manually, please only update it with command \
+                `x test tidy --bless`"
+            );
+        }
+        let allowed_makefiles_unique =
+            allowed_makefiles.iter().map(ToString::to_string).collect::<BTreeSet<String>>();
+        if allowed_makefiles_unique.len() != allowed_makefiles.len() {
+            tidy_error!(
+                bad,
+                "`src/tools/tidy/src/allowed_run_make_makefiles.txt` contains duplicate entries, \
+                likely because you modified it manually, please only update it with command \
+                `x test tidy --bless`"
+            );
+        }
+        allowed_makefiles_unique
+    };
+
+    let mut remaining_makefiles = allowed_makefiles.clone();
+
+    crate::walk::walk_no_read(
+        &[tests_path.join("run-make").as_ref()],
+        |_, _| false,
+        &mut |entry| {
+            if entry.file_type().map_or(true, |t| t.is_dir()) {
+                return;
+            }
+
+            if entry.file_name().to_str().map_or(true, |f| f != "Makefile") {
+                return;
+            }
+
+            let makefile_path = entry.path().strip_prefix(&tests_path).unwrap();
+            let makefile_path = makefile_path.to_str().unwrap().replace('\\', "/");
+
+            if !remaining_makefiles.remove(&makefile_path) {
+                tidy_error!(
+                    bad,
+                    "found run-make Makefile not permitted in \
+                `src/tools/tidy/src/allowed_run_make_makefiles.txt`, please write new run-make \
+                tests with `rmake.rs` instead: {}",
+                    entry.path().display()
+                );
+            }
+        },
+    );
+
+    // If there are any expected Makefiles remaining, they were moved or deleted.
+    // Our data must remain up to date, so they must be removed from
+    // `src/tools/tidy/src/allowed_run_make_makefiles.txt`.
+    // This can be done automatically on --bless, or else a tidy error will be issued.
+    if bless && !remaining_makefiles.is_empty() {
+        let tidy_src = src_path.join("tools").join("tidy").join("src");
+        let org_file_path = tidy_src.join("allowed_run_make_makefiles.txt");
+        let temp_file_path = tidy_src.join("blessed_allowed_run_make_makefiles.txt");
+        let mut temp_file = t!(File::create_new(&temp_file_path));
+        for file in allowed_makefiles.difference(&remaining_makefiles) {
+            t!(writeln!(temp_file, "{file}"));
+        }
+        t!(std::fs::rename(&temp_file_path, &org_file_path));
+    } else {
+        for file in remaining_makefiles {
+            let mut p = PathBuf::from(tests_path);
+            p.push(file);
+            tidy_error!(
+                bad,
+                "Makefile `{}` no longer exists and should be removed from the exclusions in \
+                `src/tools/tidy/src/allowed_run_make_makefiles.txt`, you can run --bless to update \
+                the allow list",
+                p.display()
+            );
+        }
+    }
+}
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/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs
new file mode 100644
index 00000000000..3ec1988edd6
--- /dev/null
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs
@@ -0,0 +1,27 @@
+// Verifies that type metadata identifiers for drop functions are emitted correctly.
+//
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
+
+#![crate_type="lib"]
+
+// CHECK-LABEL: define{{.*}}4core3ptr47drop_in_place$LT$dyn$u20$core..marker..Send$GT$
+// CHECK-SAME:  {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+// CHECK:       call i1 @llvm.type.test(ptr {{%.+}}, metadata !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE")
+
+struct EmptyDrop;
+// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+
+struct NonEmptyDrop;
+
+impl Drop for NonEmptyDrop {
+    fn drop(&mut self) {}
+    // CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}NonEmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+}
+
+pub fn foo() {
+    let _ = Box::new(EmptyDrop) as Box<dyn Send>;
+    let _ = Box::new(NonEmptyDrop) as Box<dyn Send>;
+}
+
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE"}
diff --git a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs
index f08c9e6702e..f9c7cca3989 100644
--- a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs
@@ -29,6 +29,8 @@ impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b
 trait Freeze { }
 #[lang="drop_in_place"]
 fn drop_in_place_fn<T>() { }
+#[lang="drop"]
+trait Drop { fn drop(&mut self); }
 
 pub trait Trait1 {
     fn foo(&self);
diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map
index 55d124a16f5..9d4698527d0 100644
--- a/tests/coverage/unreachable.cov-map
+++ b/tests/coverage/unreachable.cov-map
@@ -14,11 +14,11 @@ Number of expressions: 0
 Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 17, 1) to (start + 1, 37)
 
-Function name: unreachable::unreachable_intrinsic
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 01, 2c]
+Function name: unreachable::unreachable_intrinsic (unused)
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 2c]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 22, 1) to (start + 1, 44)
+- Code(Zero) at (prev + 22, 1) to (start + 1, 44)
 
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-fulldeps/pretty-expanded/input.rs b/tests/run-make-fulldeps/pretty-expanded/input.rs
index af3d75b3bf2..02b235068a1 100644
--- a/tests/run-make-fulldeps/pretty-expanded/input.rs
+++ b/tests/run-make-fulldeps/pretty-expanded/input.rs
@@ -1,12 +1,8 @@
-#[crate_type="lib"]
-
 // #13544
 
-extern crate rustc_serialize;
-
-#[derive(RustcEncodable)] pub struct A;
-#[derive(RustcEncodable)] pub struct B(isize);
-#[derive(RustcEncodable)] pub struct C { x: isize }
-#[derive(RustcEncodable)] pub enum D {}
-#[derive(RustcEncodable)] pub enum E { y }
-#[derive(RustcEncodable)] pub enum F { z(isize) }
+#[derive(Debug)] pub struct A;
+#[derive(Debug)] pub struct B(isize);
+#[derive(Debug)] pub struct C { x: isize }
+#[derive(Debug)] pub enum D {}
+#[derive(Debug)] pub enum E { y }
+#[derive(Debug)] pub enum F { z(isize) }
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
index 586f4e4095f..1204260a2f4 100644
--- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
@@ -1,24 +1,25 @@
 // ignore-tidy-linelength
 
+// Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current
+// `rustc` version and the `since` property in feature stability gating is properly respected.
+
 extern crate run_make_support;
 
 use std::path::PathBuf;
 
-use run_make_support::{aux_build, rustc};
+use run_make_support::{rustc, aux_build};
 
 fn main() {
-    aux_build()
-        .arg("--emit=metadata")
-        .arg("stable.rs")
-        .run();
+    aux_build().input("stable.rs").emit("metadata").run();
+
     let mut stable_path = PathBuf::from(env!("TMPDIR"));
     stable_path.push("libstable.rmeta");
+
     let output = rustc()
-        .arg("--emit=metadata")
-        .arg("--extern")
-        .arg(&format!("stable={}", &stable_path.to_string_lossy()))
-        .arg("main.rs")
-        .run();
+        .input("main.rs")
+        .emit("metadata")
+        .extern_("stable", &stable_path)
+        .output();
 
     let stderr = String::from_utf8_lossy(&output.stderr);
     let version = include_str!(concat!(env!("S"), "/src/version"));
diff --git a/tests/run-make/a-b-a-linker-guard/rmake.rs b/tests/run-make/a-b-a-linker-guard/rmake.rs
index ef4813e1214..ffc1b2000b9 100644
--- a/tests/run-make/a-b-a-linker-guard/rmake.rs
+++ b/tests/run-make/a-b-a-linker-guard/rmake.rs
@@ -1,44 +1,36 @@
 // ignore-tidy-linelength
 
+// Test that if we build `b` against a version of `a` that has one set of types, it will not run
+// with a dylib that has a different set of types.
+
 extern crate run_make_support;
 
 use run_make_support::{run, run_fail, rustc};
 
 fn main() {
     rustc()
-        .arg("a.rs")
-        .arg("--cfg")
-        .arg("x")
-        .arg("-C")
-        .arg("prefer-dynamic")
-        .arg("-Z")
-        .arg("unstable-options")
-        .arg("-C")
-        .arg("symbol-mangling-version=legacy")
+        .input("a.rs")
+        .cfg("x")
+        .arg("-Zunstable-options")
+        .arg("-Cprefer-dynamic")
+        .arg("-Csymbol-mangling-version=legacy")
         .run();
 
     rustc()
-       .arg("b.rs")
-       .arg("-C")
-       .arg("prefer-dynamic")
-       .arg("-Z")
-       .arg("unstable-options")
-       .arg("-C")
-       .arg("symbol-mangling-version=legacy")
-       .run();
+        .input("b.rs")
+        .arg("-Zunstable-options")
+        .arg("-Cprefer-dynamic")
+        .arg("-Csymbol-mangling-version=legacy")
+        .run();
 
     run("b");
 
     rustc()
-        .arg("a.rs")
-        .arg("--cfg")
-        .arg("y")
-        .arg("-C")
-        .arg("prefer-dynamic")
-        .arg("-Z")
-        .arg("unstable-options")
-        .arg("-C")
-        .arg("symbol-mangling-version=legacy")
+        .input("a.rs")
+        .cfg("y")
+        .arg("-Zunstable-options")
+        .arg("-Cprefer-dynamic")
+        .arg("-Csymbol-mangling-version=legacy")
         .run();
 
     run_fail("b");
diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs
index e7a5e8addbe..e5939470b46 100644
--- a/tests/run-make/compiler-builtins/rmake.rs
+++ b/tests/run-make/compiler-builtins/rmake.rs
@@ -8,6 +8,10 @@
 //! settings. Turning off optimizations and enabling debug assertions tends to produce the most
 //! dependence on core that is possible, so that is the configuration we test here.
 
+// wasm and nvptx targets don't produce rlib files that object can parse.
+//@ ignore-wasm
+//@ ignore-nvptx64
+
 #![deny(warnings)]
 
 extern crate run_make_support;
@@ -18,7 +22,7 @@ use run_make_support::object::read::Object;
 use run_make_support::object::ObjectSection;
 use run_make_support::object::ObjectSymbol;
 use run_make_support::object::RelocationTarget;
-use run_make_support::out_dir;
+use run_make_support::tmp_dir;
 use std::collections::HashSet;
 
 const MANIFEST: &str = r#"
@@ -31,19 +35,15 @@ edition = "2021"
 path = "lib.rs""#;
 
 fn main() {
-    let target_dir = out_dir().join("target");
+    let target_dir = tmp_dir().join("target");
     let target = std::env::var("TARGET").unwrap();
-    if target.starts_with("wasm") || target.starts_with("nvptx") {
-        // wasm and nvptx targets don't produce rlib files that object can parse.
-        return;
-    }
 
     println!("Testing compiler_builtins for {}", target);
 
     // Set up the tiniest Cargo project: An empty no_std library. Just enough to run -Zbuild-std.
-    let manifest_path = out_dir().join("Cargo.toml");
+    let manifest_path = tmp_dir().join("Cargo.toml");
     std::fs::write(&manifest_path, MANIFEST.as_bytes()).unwrap();
-    std::fs::write(out_dir().join("lib.rs"), b"#![no_std]").unwrap();
+    std::fs::write(tmp_dir().join("lib.rs"), b"#![no_std]").unwrap();
 
     let path = std::env::var("PATH").unwrap();
     let rustc = std::env::var("RUSTC").unwrap();
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-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs
index 808d13928eb..c8edfb6370e 100644
--- a/tests/run-make/rustdoc-test-args/rmake.rs
+++ b/tests/run-make/rustdoc-test-args/rmake.rs
@@ -1,8 +1,8 @@
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustdoc};
-use std::{fs, iter};
+use run_make_support::{rustdoc, tmp_dir};
 use std::path::Path;
+use std::{fs, iter};
 
 fn generate_a_lot_of_cfgs(path: &Path) {
     let content = iter::repeat("--cfg=a\n").take(100_000).collect::<String>();
@@ -10,9 +10,8 @@ fn generate_a_lot_of_cfgs(path: &Path) {
 }
 
 fn main() {
-    let arg_file = out_dir().join("args");
+    let arg_file = tmp_dir().join("args");
     generate_a_lot_of_cfgs(&arg_file);
 
-    let arg_file = format!("@{}", arg_file.display());
-    rustdoc().arg("--test").arg(&arg_file).arg("foo.rs").run();
+    rustdoc().out_dir(tmp_dir()).input("foo.rs").arg_file(&arg_file).arg("--test").run();
 }
diff --git a/tests/run-make/wasm-abi/rmake.rs b/tests/run-make/wasm-abi/rmake.rs
index 07b826ae6fe..d83332f6e03 100644
--- a/tests/run-make/wasm-abi/rmake.rs
+++ b/tests/run-make/wasm-abi/rmake.rs
@@ -1,25 +1,16 @@
+//@ only-wasm32-wasip1
+//@ needs-wasmtime
+
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc};
+use run_make_support::{rustc, tmp_dir};
 use std::path::Path;
 use std::process::Command;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
-    let file = out_dir().join("foo.wasm");
+    rustc().input("foo.rs").target("wasm32-wasip1").run();
 
-    let has_wasmtime = match Command::new("wasmtime").arg("--version").output() {
-        Ok(s) => s.status.success(),
-        _ => false,
-    };
-    if !has_wasmtime {
-        println!("skipping test, wasmtime isn't available");
-        return;
-    }
+    let file = tmp_dir().join("foo.wasm");
 
     run(&file, "return_two_i32", "1\n2\n");
     run(&file, "return_two_i64", "3\n4\n");
diff --git a/tests/run-make/wasm-custom-section/rmake.rs b/tests/run-make/wasm-custom-section/rmake.rs
index 9ad152695ec..825fcf71514 100644
--- a/tests/run-make/wasm-custom-section/rmake.rs
+++ b/tests/run-make/wasm-custom-section/rmake.rs
@@ -1,17 +1,14 @@
+//@ only-wasm32-wasip1
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{rustc, tmp_dir, wasmparser};
 use std::collections::HashMap;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
-    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
+    rustc().input("foo.rs").target("wasm32-wasip1").run();
+    rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let file = std::fs::read(&out_dir().join("bar.wasm")).unwrap();
+    let file = std::fs::read(&tmp_dir().join("bar.wasm")).unwrap();
 
     let mut custom = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs
index db31d6b7163..634683adc22 100644
--- a/tests/run-make/wasm-custom-sections-opt/rmake.rs
+++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs
@@ -1,16 +1,14 @@
+//@ only-wasm32-wasip1
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{tmp_dir, wasmparser, rustc};
 use std::collections::HashMap;
 use std::path::Path;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
+    rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
 
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-O").run();
-    verify(&out_dir().join("foo.wasm"));
+    verify(&tmp_dir().join("foo.wasm"));
 }
 
 fn verify(path: &Path) {
diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs
index e3b118279b7..400d6db5651 100644
--- a/tests/run-make/wasm-export-all-symbols/rmake.rs
+++ b/tests/run-make/wasm-export-all-symbols/rmake.rs
@@ -1,15 +1,13 @@
+//@ only-wasm32-wasip1
+
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{tmp_dir, wasmparser, rustc};
 use std::collections::HashMap;
 use std::path::Path;
 use wasmparser::ExternalKind::*;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
     test(&[]);
     test(&["-O"]);
     test(&["-Clto"]);
@@ -17,16 +15,17 @@ fn main() {
 
 fn test(args: &[&str]) {
     eprintln!("running with {args:?}");
-    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").args(args).run();
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").args(args).run();
-    rustc().arg("main.rs").arg("--target=wasm32-wasip1").args(args).run();
+
+    rustc().input("bar.rs").target("wasm32-wasip1").args(args).run();
+    rustc().input("foo.rs").target("wasm32-wasip1").args(args).run();
+    rustc().input("main.rs").target("wasm32-wasip1").args(args).run();
 
     verify_exports(
-        &out_dir().join("foo.wasm"),
+        &tmp_dir().join("foo.wasm"),
         &[("foo", Func), ("FOO", Global), ("memory", Memory)],
     );
     verify_exports(
-        &out_dir().join("main.wasm"),
+        &tmp_dir().join("main.wasm"),
         &[
             ("foo", Func),
             ("FOO", Global),
diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs
index e521b5b0983..1b814e9ccce 100644
--- a/tests/run-make/wasm-import-module/rmake.rs
+++ b/tests/run-make/wasm-import-module/rmake.rs
@@ -1,18 +1,21 @@
+//@ only-wasm32-wasip1
+
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{tmp_dir, wasmparser, rustc};
 use std::collections::HashMap;
 use wasmparser::TypeRef::Func;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
-    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
+    rustc().input("foo.rs").target("wasm32-wasip1").run();
+    rustc()
+        .input("bar.rs")
+        .target("wasm32-wasip1")
+        .arg("-Clto")
+        .opt()
+        .run();
 
-    let file = std::fs::read(&out_dir().join("bar.wasm")).unwrap();
+    let file = std::fs::read(&tmp_dir().join("bar.wasm")).unwrap();
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-panic-small/rmake.rs b/tests/run-make/wasm-panic-small/rmake.rs
index 0260485f744..bffa311d93a 100644
--- a/tests/run-make/wasm-panic-small/rmake.rs
+++ b/tests/run-make/wasm-panic-small/rmake.rs
@@ -1,14 +1,11 @@
+//@ only-wasm32-wasip1
 #![deny(warnings)]
 
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc};
+use run_make_support::{rustc, tmp_dir};
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
     test("a");
     test("b");
     test("c");
@@ -17,16 +14,10 @@ fn main() {
 
 fn test(cfg: &str) {
     eprintln!("running cfg {cfg:?}");
-    rustc()
-        .arg("foo.rs")
-        .arg("--target=wasm32-wasip1")
-        .arg("-Clto")
-        .arg("-O")
-        .arg("--cfg")
-        .arg(cfg)
-        .run();
 
-    let bytes = std::fs::read(&out_dir().join("foo.wasm")).unwrap();
+    rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().cfg(cfg).run();
+
+    let bytes = std::fs::read(&tmp_dir().join("foo.wasm")).unwrap();
     println!("{}", bytes.len());
     assert!(bytes.len() < 40_000);
 }
diff --git a/tests/run-make/wasm-spurious-import/rmake.rs b/tests/run-make/wasm-spurious-import/rmake.rs
index 0ac9104bfb4..8f716061d28 100644
--- a/tests/run-make/wasm-spurious-import/rmake.rs
+++ b/tests/run-make/wasm-spurious-import/rmake.rs
@@ -1,24 +1,21 @@
+//@ only-wasm32-wasip1
+
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{rustc, tmp_dir, wasmparser};
 use std::collections::HashMap;
-use wasmparser::TypeRef::Func;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
     rustc()
-        .arg("main.rs")
-        .arg("--target=wasm32-wasip1")
-        .arg("-Coverflow-checks=yes")
+        .input("main.rs")
+        .target("wasm32-wasip1")
+        .arg("-Coverflow-checks")
         .arg("-Cpanic=abort")
         .arg("-Clto")
         .arg("-Copt-level=z")
         .run();
 
-    let file = std::fs::read(&out_dir().join("main.wasm")).unwrap();
+    let file = std::fs::read(&tmp_dir().join("main.wasm")).unwrap();
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-stringify-ints-small/rmake.rs b/tests/run-make/wasm-stringify-ints-small/rmake.rs
index 80cff7acdf4..5efbfee8d38 100644
--- a/tests/run-make/wasm-stringify-ints-small/rmake.rs
+++ b/tests/run-make/wasm-stringify-ints-small/rmake.rs
@@ -1,17 +1,14 @@
+//@ only-wasm32-wasip1
 #![deny(warnings)]
 
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc};
+use run_make_support::{rustc, tmp_dir};
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
+    rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
-
-    let bytes = std::fs::read(&out_dir().join("foo.wasm")).unwrap();
+    let bytes = std::fs::read(&tmp_dir().join("foo.wasm")).unwrap();
     println!("{}", bytes.len());
     assert!(bytes.len() < 50_000);
 }
diff --git a/tests/run-make/wasm-symbols-different-module/rmake.rs b/tests/run-make/wasm-symbols-different-module/rmake.rs
index c3cc1e0c32b..88bd16a404c 100644
--- a/tests/run-make/wasm-symbols-different-module/rmake.rs
+++ b/tests/run-make/wasm-symbols-different-module/rmake.rs
@@ -1,13 +1,10 @@
+//@ only-wasm32-wasip1
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{rustc, tmp_dir, wasmparser};
 use std::collections::{HashMap, HashSet};
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
     test_file("foo.rs", &[("a", &["foo"]), ("b", &["foo"])]);
     test_file("bar.rs", &[("m1", &["f", "g"]), ("m2", &["f"])]);
     test_file("baz.rs", &[("sqlite", &["allocate", "deallocate"])]);
@@ -24,9 +21,9 @@ fn test_file(file: &str, expected_imports: &[(&str, &[&str])]) {
 fn test(file: &str, args: &[&str], expected_imports: &[(&str, &[&str])]) {
     println!("test {file:?} {args:?} for {expected_imports:?}");
 
-    rustc().arg(file).arg("--target=wasm32-wasip1").args(args).run();
+    rustc().input(file).target("wasm32-wasip1").args(args).run();
 
-    let file = std::fs::read(&out_dir().join(file).with_extension("wasm")).unwrap();
+    let file = std::fs::read(&tmp_dir().join(file).with_extension("wasm")).unwrap();
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs
index 5ff0dc578b3..c9207f70ae5 100644
--- a/tests/run-make/wasm-symbols-not-exported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs
@@ -1,22 +1,19 @@
+//@ only-wasm32-wasip1
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{rustc, tmp_dir, wasmparser};
 use std::path::Path;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
-    verify_symbols(&out_dir().join("foo.wasm"));
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-O").run();
-    verify_symbols(&out_dir().join("foo.wasm"));
+    rustc().input("foo.rs").target("wasm32-wasip1").run();
+    verify_symbols(&tmp_dir().join("foo.wasm"));
+    rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
+    verify_symbols(&tmp_dir().join("foo.wasm"));
 
-    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").run();
-    verify_symbols(&out_dir().join("bar.wasm"));
-    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").arg("-O").run();
-    verify_symbols(&out_dir().join("bar.wasm"));
+    rustc().input("bar.rs").target("wasm32-wasip1").run();
+    verify_symbols(&tmp_dir().join("bar.wasm"));
+    rustc().input("bar.rs").target("wasm32-wasip1").opt().run();
+    verify_symbols(&tmp_dir().join("bar.wasm"));
 }
 
 fn verify_symbols(path: &Path) {
diff --git a/tests/run-make/wasm-symbols-not-imported/rmake.rs b/tests/run-make/wasm-symbols-not-imported/rmake.rs
index 974f415166b..4d41dc7c0aa 100644
--- a/tests/run-make/wasm-symbols-not-imported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-imported/rmake.rs
@@ -1,21 +1,18 @@
+//@ only-wasm32-wasip1
 extern crate run_make_support;
 
-use run_make_support::{out_dir, rustc, wasmparser};
+use run_make_support::{rustc, tmp_dir, wasmparser};
 use std::path::Path;
 
 fn main() {
-    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
-        return;
-    }
-
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
-    verify_symbols(&out_dir().join("foo.wasm"));
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-Clto").run();
-    verify_symbols(&out_dir().join("foo.wasm"));
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-O").run();
-    verify_symbols(&out_dir().join("foo.wasm"));
-    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
-    verify_symbols(&out_dir().join("foo.wasm"));
+    rustc().input("foo.rs").target("wasm32-wasip1").run();
+    verify_symbols(&tmp_dir().join("foo.wasm"));
+    rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").run();
+    verify_symbols(&tmp_dir().join("foo.wasm"));
+    rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
+    verify_symbols(&tmp_dir().join("foo.wasm"));
+    rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
+    verify_symbols(&tmp_dir().join("foo.wasm"));
 }
 
 fn verify_symbols(path: &Path) {
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/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml
index c5e7f813dd1..26071df8d04 100644
--- a/tests/rustdoc-gui/target.goml
+++ b/tests/rustdoc-gui/target.goml
@@ -1,4 +1,4 @@
-// Check that the targetted element has the expected styles.
+// Check that the targeted element has the expected styles.
 go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html#method.a_method"
 show-text: true
 
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/anonymous-higher-ranked-lifetime.stderr
index cc27a0fcf95..c28d856ad55 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/tests/ui/anonymous-higher-ranked-lifetime.stderr
@@ -70,7 +70,7 @@ LL |     f4(|_: (), _: ()| {});
    |     |  found signature defined here
    |     expected due to this
    |
-   = note: expected closure signature `for<'r, 'a> fn(&'a (), &'r ()) -> _`
+   = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f4`
   --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25
@@ -217,7 +217,7 @@ LL |     h2(|_: (), _: (), _: (), _: ()| {});
    |     |  found signature defined here
    |     expected due to this
    |
-   = note: expected closure signature `for<'t0, 'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
+   = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
               found closure signature `fn((), (), (), ()) -> _`
 note: required by a bound in `h2`
   --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25
diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr
index 42d722291c3..35ee95d1215 100644
--- a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr
+++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr
@@ -4,16 +4,16 @@ error[E0034]: multiple applicable items in scope
 LL | const X: i32 = <i32>::ID;
    |                       ^^ multiple `ID` found
    |
-note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32`
-  --> $DIR/associated-const-ambiguity-report.rs:10:5
-   |
-LL |     const ID: i32 = 1;
-   |     ^^^^^^^^^^^^^
-note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32`
+note: candidate #1 is defined in an impl of the trait `Bar` for the type `i32`
   --> $DIR/associated-const-ambiguity-report.rs:14:5
    |
 LL |     const ID: i32 = 3;
    |     ^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Foo` for the type `i32`
+  --> $DIR/associated-const-ambiguity-report.rs:10:5
+   |
+LL |     const ID: i32 = 1;
+   |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
 LL | const X: i32 = <i32 as Bar>::ID;
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/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr
index 8a226d712ff..32bd2554abb 100644
--- a/tests/ui/binop/binary-op-suggest-deref.stderr
+++ b/tests/ui/binop/binary-op-suggest-deref.stderr
@@ -247,14 +247,14 @@ LL |     _ = &&0 == Foo;
    |
    = help: the trait `PartialEq<Foo>` is not implemented for `&&{integer}`
    = help: the following other types implement trait `PartialEq<Rhs>`:
-             isize
-             i8
+             f32
+             f64
+             i128
              i16
              i32
              i64
-             i128
-             usize
-             u8
+             i8
+             isize
            and 6 others
 
 error[E0369]: binary operation `==` cannot be applied to type `Foo`
@@ -303,10 +303,10 @@ LL |     let _ = FOO & (*"Sized".to_string().into_boxed_str());
    |
    = help: the trait `BitAnd<str>` is not implemented for `i32`
    = help: the following other types implement trait `BitAnd<Rhs>`:
-             <i32 as BitAnd>
-             <i32 as BitAnd<&i32>>
              <&'a i32 as BitAnd<i32>>
              <&i32 as BitAnd<&i32>>
+             <i32 as BitAnd<&i32>>
+             <i32 as BitAnd>
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/binary-op-suggest-deref.rs:78:17
diff --git a/tests/ui/binop/binop-mul-i32-f32.stderr b/tests/ui/binop/binop-mul-i32-f32.stderr
index 6ed3e7b4447..29e1ff91834 100644
--- a/tests/ui/binop/binop-mul-i32-f32.stderr
+++ b/tests/ui/binop/binop-mul-i32-f32.stderr
@@ -6,10 +6,10 @@ LL |     x * y
    |
    = help: the trait `Mul<f32>` is not implemented for `i32`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <i32 as Mul>
-             <i32 as Mul<&i32>>
              <&'a i32 as Mul<i32>>
              <&i32 as Mul<&i32>>
+             <i32 as Mul<&i32>>
+             <i32 as Mul>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/binop/shift-various-bad-types.stderr b/tests/ui/binop/shift-various-bad-types.stderr
index b43672ef3b5..38db66f86b4 100644
--- a/tests/ui/binop/shift-various-bad-types.stderr
+++ b/tests/ui/binop/shift-various-bad-types.stderr
@@ -6,14 +6,14 @@ LL |     22 >> p.char;
    |
    = help: the trait `Shr<char>` is not implemented for `{integer}`
    = help: the following other types implement trait `Shr<Rhs>`:
-             <isize as Shr>
-             <isize as Shr<i8>>
-             <isize as Shr<i16>>
-             <isize as Shr<i32>>
-             <isize as Shr<i64>>
-             <isize as Shr<i128>>
-             <isize as Shr<usize>>
-             <isize as Shr<u8>>
+             <&'a i128 as Shr<i128>>
+             <&'a i128 as Shr<i16>>
+             <&'a i128 as Shr<i32>>
+             <&'a i128 as Shr<i64>>
+             <&'a i128 as Shr<i8>>
+             <&'a i128 as Shr<isize>>
+             <&'a i128 as Shr<u128>>
+             <&'a i128 as Shr<u16>>
            and 568 others
 
 error[E0277]: no implementation for `{integer} >> &str`
@@ -24,14 +24,14 @@ LL |     22 >> p.str;
    |
    = help: the trait `Shr<&str>` is not implemented for `{integer}`
    = help: the following other types implement trait `Shr<Rhs>`:
-             <isize as Shr>
-             <isize as Shr<i8>>
-             <isize as Shr<i16>>
-             <isize as Shr<i32>>
-             <isize as Shr<i64>>
-             <isize as Shr<i128>>
-             <isize as Shr<usize>>
-             <isize as Shr<u8>>
+             <&'a i128 as Shr<i128>>
+             <&'a i128 as Shr<i16>>
+             <&'a i128 as Shr<i32>>
+             <&'a i128 as Shr<i64>>
+             <&'a i128 as Shr<i8>>
+             <&'a i128 as Shr<isize>>
+             <&'a i128 as Shr<u128>>
+             <&'a i128 as Shr<u16>>
            and 568 others
 
 error[E0277]: no implementation for `{integer} >> &Panolpy`
@@ -42,14 +42,14 @@ LL |     22 >> p;
    |
    = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}`
    = help: the following other types implement trait `Shr<Rhs>`:
-             <isize as Shr>
-             <isize as Shr<i8>>
-             <isize as Shr<i16>>
-             <isize as Shr<i32>>
-             <isize as Shr<i64>>
-             <isize as Shr<i128>>
-             <isize as Shr<usize>>
-             <isize as Shr<u8>>
+             <&'a i128 as Shr<i128>>
+             <&'a i128 as Shr<i16>>
+             <&'a i128 as Shr<i32>>
+             <&'a i128 as Shr<i64>>
+             <&'a i128 as Shr<i8>>
+             <&'a i128 as Shr<isize>>
+             <&'a i128 as Shr<u128>>
+             <&'a i128 as Shr<u16>>
            and 568 others
 
 error[E0308]: mismatched types
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/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr
index 42814c1fb70..acaa0cf1a50 100644
--- a/tests/ui/const-generics/exhaustive-value.stderr
+++ b/tests/ui/const-generics/exhaustive-value.stderr
@@ -6,13 +6,13 @@ LL |     <() as Foo<N>>::test()
    |
    = help: the following other types implement trait `Foo<N>`:
              <() as Foo<0>>
-             <() as Foo<1>>
-             <() as Foo<2>>
-             <() as Foo<3>>
-             <() as Foo<4>>
-             <() as Foo<5>>
-             <() as Foo<6>>
-             <() as Foo<7>>
+             <() as Foo<100>>
+             <() as Foo<101>>
+             <() as Foo<102>>
+             <() as Foo<103>>
+             <() as Foo<104>>
+             <() as Foo<105>>
+             <() as Foo<106>>
            and 248 others
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
index 6d3b0b8508c..5b296a14869 100644
--- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
+++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
@@ -6,11 +6,11 @@ LL |     let y = Mask::<_, _>::splat(false);
    |
    = note: cannot satisfy `_: MaskElement`
    = help: the following types implement trait `MaskElement`:
-             isize
-             i8
              i16
              i32
              i64
+             i8
+             isize
 note: required by a bound in `Mask::<T, N>::splat`
   --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
 help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr
index e39d43205c1..5cc3bb673bc 100644
--- a/tests/ui/const-generics/issues/issue-67185-2.stderr
+++ b/tests/ui/const-generics/issues/issue-67185-2.stderr
@@ -5,8 +5,8 @@ LL |     <u8 as Baz>::Quaks: Bar,
    |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]`
    |
    = help: the following other types implement trait `Bar`:
-             [u16; 4]
              [[u16; 3]; 3]
+             [u16; 4]
    = help: see issue #48214
 help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
    |
@@ -20,8 +20,8 @@ LL |     [<u8 as Baz>::Quaks; 2]: Bar,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
    |
    = help: the following other types implement trait `Bar`:
-             [u16; 4]
              [[u16; 3]; 3]
+             [u16; 4]
    = help: see issue #48214
 help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
    |
@@ -35,8 +35,8 @@ LL | impl Foo for FooImpl {}
    |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`, which is required by `<u8 as Baz>::Quaks: Bar`
    |
    = help: the following other types implement trait `Bar`:
-             [u16; 4]
              [[u16; 3]; 3]
+             [u16; 4]
 note: required by a bound in `Foo`
   --> $DIR/issue-67185-2.rs:15:25
    |
@@ -53,8 +53,8 @@ LL | impl Foo for FooImpl {}
    |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`, which is required by `[<u8 as Baz>::Quaks; 2]: Bar`
    |
    = help: the following other types implement trait `Bar`:
-             [u16; 4]
              [[u16; 3]; 3]
+             [u16; 4]
 note: required by a bound in `Foo`
   --> $DIR/issue-67185-2.rs:14:30
    |
@@ -71,8 +71,8 @@ LL | fn f(_: impl Foo) {}
    |              ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
    |
    = help: the following other types implement trait `Bar`:
-             [u16; 4]
              [[u16; 3]; 3]
+             [u16; 4]
 note: required by a bound in `Foo`
   --> $DIR/issue-67185-2.rs:14:30
    |
@@ -89,8 +89,8 @@ LL | fn f(_: impl Foo) {}
    |              ^^^ the trait `Bar` is not implemented for `[u16; 3]`
    |
    = help: the following other types implement trait `Bar`:
-             [u16; 4]
              [[u16; 3]; 3]
+             [u16; 4]
 note: required by a bound in `Foo`
   --> $DIR/issue-67185-2.rs:15:25
    |
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/const-eval/const-eval-overflow-3b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr
index 06e398edca9..05f33c33946 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr
+++ b/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr
@@ -12,10 +12,10 @@ LL |     = [0; (i8::MAX + 1u8) as usize];
    |
    = help: the trait `Add<u8>` is not implemented for `i8`
    = help: the following other types implement trait `Add<Rhs>`:
-             <i8 as Add>
-             <i8 as Add<&i8>>
              <&'a i8 as Add<i8>>
              <&i8 as Add<&i8>>
+             <i8 as Add<&i8>>
+             <i8 as Add>
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
index 07ef2ac090f..d019f5920b5 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
+++ b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -12,10 +12,10 @@ LL |     : [u32; (i8::MAX as i8 + 1u8) as usize]
    |
    = help: the trait `Add<u8>` is not implemented for `i8`
    = help: the following other types implement trait `Add<Rhs>`:
-             <i8 as Add>
-             <i8 as Add<&i8>>
              <&'a i8 as Add<i8>>
              <&i8 as Add<&i8>>
+             <i8 as Add<&i8>>
+             <i8 as Add>
 
 error[E0604]: only `u8` can be cast as `char`, not `i8`
   --> $DIR/const-eval-overflow-4b.rs:22:13
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/consts/missing-larger-array-impl.stderr b/tests/ui/consts/missing-larger-array-impl.stderr
index acf38d00ec6..ff4fa36d684 100644
--- a/tests/ui/consts/missing-larger-array-impl.stderr
+++ b/tests/ui/consts/missing-larger-array-impl.stderr
@@ -5,14 +5,14 @@ LL |     <[X; 35] as Default>::default();
    |      ^^^^^^^ the trait `Default` is not implemented for `[X; 35]`
    |
    = help: the following other types implement trait `Default`:
+             &[T]
+             &mut [T]
              [T; 0]
-             [T; 1]
-             [T; 2]
-             [T; 3]
-             [T; 4]
-             [T; 5]
-             [T; 6]
-             [T; 7]
+             [T; 10]
+             [T; 11]
+             [T; 12]
+             [T; 13]
+             [T; 14]
            and 27 others
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs
new file mode 100644
index 00000000000..8d95e3dca63
--- /dev/null
+++ b/tests/ui/consts/missing_assoc_const_type.rs
@@ -0,0 +1,28 @@
+//! Test that we compute the right type for associated constants
+//! of impls, even if the type is missing. We know it from the trait
+//! declaration after all.
+
+trait Range {
+    const FIRST: u8;
+    const LAST: u8;
+}
+
+struct TwoDigits;
+impl Range for TwoDigits {
+    const FIRST:  = 10;
+    //~^ ERROR: missing type for `const` item
+    const LAST: u8 = 99;
+}
+
+const fn digits(x: u8) -> usize {
+    match x {
+        TwoDigits::FIRST..=TwoDigits::LAST => 0,
+        0..=9 | 100..=255 => panic!(),
+    }
+}
+
+const FOOMP: [(); {
+    digits(42)
+}] = [];
+
+fn main() {}
diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr
new file mode 100644
index 00000000000..28af1f0f321
--- /dev/null
+++ b/tests/ui/consts/missing_assoc_const_type.stderr
@@ -0,0 +1,8 @@
+error: missing type for `const` item
+  --> $DIR/missing_assoc_const_type.rs:12:17
+   |
+LL |     const FIRST:  = 10;
+   |                 ^ help: provide a type for the associated constant: `u8`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/consts/missing_assoc_const_type2.rs b/tests/ui/consts/missing_assoc_const_type2.rs
new file mode 100644
index 00000000000..baf236700a3
--- /dev/null
+++ b/tests/ui/consts/missing_assoc_const_type2.rs
@@ -0,0 +1,21 @@
+//! Test that we compute the right type for associated constants
+//! of impls, even if the type is missing. We know it from the trait
+//! declaration after all.
+
+trait Range {
+    const FIRST: u8;
+    const LAST: u8;
+}
+
+struct TwoDigits;
+impl Range for TwoDigits {
+    const FIRST:  = 10;
+    //~^ ERROR: missing type
+    const LAST: u8 = 99;
+}
+
+const FOOMP: [(); {
+    TwoDigits::FIRST as usize
+}] = [(); 10];
+
+fn main() {}
diff --git a/tests/ui/consts/missing_assoc_const_type2.stderr b/tests/ui/consts/missing_assoc_const_type2.stderr
new file mode 100644
index 00000000000..1255ca2d102
--- /dev/null
+++ b/tests/ui/consts/missing_assoc_const_type2.stderr
@@ -0,0 +1,8 @@
+error: missing type for `const` item
+  --> $DIR/missing_assoc_const_type2.rs:12:17
+   |
+LL |     const FIRST:  = 10;
+   |                 ^ help: provide a type for the associated constant: `u8`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr
index 4089c850c80..54dffa3befc 100644
--- a/tests/ui/consts/too_generic_eval_ice.stderr
+++ b/tests/ui/consts/too_generic_eval_ice.stderr
@@ -22,14 +22,14 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    |
    = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]`
    = help: the following other types implement trait `PartialEq<Rhs>`:
-             <[T; N] as PartialEq<[U; N]>>
-             <[T; N] as PartialEq<[U]>>
+             <&[T] as PartialEq<Vec<U, A>>>
+             <&[T] as PartialEq<[U; N]>>
+             <&mut [T] as PartialEq<Vec<U, A>>>
+             <&mut [T] as PartialEq<[U; N]>>
              <[T; N] as PartialEq<&[U]>>
              <[T; N] as PartialEq<&mut [U]>>
-             <[T] as PartialEq<Vec<U, A>>>
-             <[T] as PartialEq<[U; N]>>
-             <[T] as PartialEq<[U]>>
-             <&[T] as PartialEq<Vec<U, A>>>
+             <[T; N] as PartialEq<[U; N]>>
+             <[T; N] as PartialEq<[U]>>
            and 3 others
 
 error: aborting due to 3 previous errors
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/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs
index df456f94507..d2723dc32e0 100644
--- a/tests/ui/delegation/bad-resolve.rs
+++ b/tests/ui/delegation/bad-resolve.rs
@@ -1,5 +1,5 @@
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 trait Trait {
     const C: u32 = 0;
@@ -34,14 +34,6 @@ impl Trait for S {
 
     reuse foo { &self.0 }
     //~^ ERROR cannot find function `foo` in this scope
-    reuse F::foo { &self.0 }
-    //~^ ERROR cannot find function `foo` in `F`
-    //~| ERROR duplicate definitions with name `foo`
-}
-
-impl S {
-    reuse F::foo { &self.0 }
-    //~^ ERROR cannot find function `foo` in `F`
 }
 
 fn main() {}
diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr
index d5206637310..f669ac3730e 100644
--- a/tests/ui/delegation/bad-resolve.stderr
+++ b/tests/ui/delegation/bad-resolve.stderr
@@ -25,18 +25,6 @@ LL |     reuse <F as Trait>::baz;
    |     |                   help: there is an associated function with a similar name: `bar`
    |     not a member of trait `Trait`
 
-error[E0201]: duplicate definitions with name `foo`:
-  --> $DIR/bad-resolve.rs:37:5
-   |
-LL |     fn foo(&self, x: i32) -> i32 { x }
-   |     ---------------------------------- item in trait
-...
-LL |     reuse foo { &self.0 }
-   |     --------------------- previous definition here
-LL |
-LL |     reuse F::foo { &self.0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
-
 error[E0423]: expected function, found associated constant `Trait::C`
   --> $DIR/bad-resolve.rs:24:11
    |
@@ -66,27 +54,6 @@ error[E0425]: cannot find function `foo` in this scope
 LL |     reuse foo { &self.0 }
    |           ^^^ not found in this scope
 
-error[E0425]: cannot find function `foo` in `F`
-  --> $DIR/bad-resolve.rs:37:14
-   |
-LL |     reuse F::foo { &self.0 }
-   |              ^^^ not found in `F`
-
-error[E0425]: cannot find function `foo` in `F`
-  --> $DIR/bad-resolve.rs:43:14
-   |
-LL |     reuse F::foo { &self.0 }
-   |              ^^^ not found in `F`
-
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-resolve.rs:1:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0046]: not all trait items implemented, missing: `Type`
   --> $DIR/bad-resolve.rs:22:1
    |
@@ -96,7 +63,7 @@ LL |     type Type;
 LL | impl Trait for S {
    | ^^^^^^^^^^^^^^^^ missing `Type` in implementation
 
-error: aborting due to 11 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0046, E0201, E0324, E0407, E0423, E0425, E0575, E0576.
+Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0575, E0576.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs
index bd685b40b2f..9c7afcef3ec 100644
--- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs
+++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs
@@ -1,5 +1,5 @@
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 trait Trait {
     fn foo(&self) -> u32 { 0 }
diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr
index a5f9e6ad0bf..a0f157800cb 100644
--- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr
+++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr
@@ -9,15 +9,6 @@ LL |     reuse to_reuse::foo { self }
 LL |     reuse Trait::foo;
    |     ^^^^^^^^^^^^^^^^^ duplicate definition
 
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/duplicate-definition-inside-trait-impl.rs:1:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0201`.
diff --git a/tests/ui/delegation/explicit-paths-in-traits-pass.rs b/tests/ui/delegation/explicit-paths-in-traits-pass.rs
index 4abcc18b9b2..7d281ad150a 100644
--- a/tests/ui/delegation/explicit-paths-in-traits-pass.rs
+++ b/tests/ui/delegation/explicit-paths-in-traits-pass.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 trait ToReuse {
     fn foo(&self, x: i32) -> i32 { x }
diff --git a/tests/ui/delegation/explicit-paths-in-traits-pass.stderr b/tests/ui/delegation/explicit-paths-in-traits-pass.stderr
deleted file mode 100644
index 8a320b44e63..00000000000
--- a/tests/ui/delegation/explicit-paths-in-traits-pass.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/explicit-paths-in-traits-pass.rs:3:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs
index 140605a2bc5..fada793bd11 100644
--- a/tests/ui/delegation/explicit-paths-pass.rs
+++ b/tests/ui/delegation/explicit-paths-pass.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 trait Trait {
     fn bar(&self, x: i32) -> i32 { x }
@@ -10,7 +10,6 @@ trait Trait {
     }
     fn static_method(x: i32) -> i32 { x }
     fn static_method2(x: i32, y: i32) -> i32 { x + y }
-    fn baz<'a>(&self, x: &'a i32) -> &'a i32 { x }
 }
 
 struct F;
@@ -29,11 +28,9 @@ impl Trait for S {
     reuse Trait::description { &self.0 }
     reuse <F as Trait>::static_method;
     reuse <F as Trait>::static_method2 { S::static_method(self) }
-    reuse Trait::baz { &self.0 }
 }
 
 impl S {
-    reuse Trait::baz { &self.0 }
     reuse <F as Trait>::static_method { to_reuse::foo(self) }
 }
 
@@ -49,16 +46,8 @@ fn main() {
     assert_eq!(42, <S as Trait>::static_method(42));
     assert_eq!(21, S::static_method2(10, 10));
 
-    reuse <S as Trait>::static_method;
-    reuse <S as Trait>::static_method2 { static_method(self) }
     #[inline]
     reuse to_reuse::foo;
-    assert_eq!(42, static_method(42));
-    assert_eq!(21, static_method2(10, 10));
     assert_eq!(43, foo(42));
     assert_eq!(15, zero_args());
-
-    let x: i32 = 15;
-    assert_eq!(&x, <S as Trait>::baz(&s, &x));
-    assert_eq!(&x, S::baz(&s, &x));
 }
diff --git a/tests/ui/delegation/explicit-paths-pass.stderr b/tests/ui/delegation/explicit-paths-pass.stderr
deleted file mode 100644
index 6d25fb4a5a5..00000000000
--- a/tests/ui/delegation/explicit-paths-pass.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/explicit-paths-pass.rs:3:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/delegation/explicit-paths-signature-pass.rs b/tests/ui/delegation/explicit-paths-signature-pass.rs
index b53e5779924..8c16ad92393 100644
--- a/tests/ui/delegation/explicit-paths-signature-pass.rs
+++ b/tests/ui/delegation/explicit-paths-signature-pass.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 mod to_reuse {
     use crate::S;
diff --git a/tests/ui/delegation/explicit-paths-signature-pass.stderr b/tests/ui/delegation/explicit-paths-signature-pass.stderr
deleted file mode 100644
index 6c81a2ea0af..00000000000
--- a/tests/ui/delegation/explicit-paths-signature-pass.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/explicit-paths-signature-pass.rs:3:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/delegation/explicit-paths.rs b/tests/ui/delegation/explicit-paths.rs
index 1feaaa73f79..a91ca4cb931 100644
--- a/tests/ui/delegation/explicit-paths.rs
+++ b/tests/ui/delegation/explicit-paths.rs
@@ -1,25 +1,84 @@
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 trait Trait {
-    fn bar(&self) -> i32 { 42 }
+    fn foo1(&self, x: i32) -> i32 { x }
+    fn foo2(x: i32) -> i32 { x }
 }
 
 struct F;
 impl Trait for F {}
-
 struct S(F);
 
-impl Trait for S {
-    reuse <F as Trait>::bar;
-    //~^ ERROR mismatched types
+pub mod to_reuse {
+    pub fn foo3() {}
+}
+
+impl F {
+    fn foo4(&self) {}
+}
+
+mod fn_to_other {
+    use super::*;
+
+    reuse Trait::foo1;
+    //~^ ERROR delegation to a trait method from a free function is not supported yet
+    reuse <S as Trait>::foo2;
+    //~^ ERROR delegation to a trait method from a free function is not supported yet
+    reuse to_reuse::foo3;
+    reuse S::foo4;
+    //~^ ERROR cannot find function `foo4` in `S`
+}
+
+mod inherent_impl_assoc_fn_to_other {
+    use crate::*;
+
+    impl S {
+        reuse Trait::foo1 { &self.0 }
+        reuse <S as Trait>::foo2;
+        reuse to_reuse::foo3;
+        reuse F::foo4 { &self.0 }
+        //~^ ERROR cannot find function `foo4` in `F`
+    }
+}
+
+mod trait_impl_assoc_fn_to_other {
+    use crate::*;
+
+    impl Trait for S {
+        reuse Trait::foo1 { &self.0 }
+        reuse <F as Trait>::foo2;
+        reuse to_reuse::foo3;
+        //~^ ERROR method `foo3` is not a member of trait `Trait`
+        reuse F::foo4 { &self.0 }
+        //~^ ERROR method `foo4` is not a member of trait `Trait`
+        //~| ERROR cannot find function `foo4` in `F`
+    }
+}
+
+mod trait_assoc_fn_to_other {
+    use crate::*;
+
+    trait Trait2 : Trait {
+        reuse <F as Trait>::foo1 { self }
+        //~^ ERROR mismatched types
+        reuse <F as Trait>::foo2;
+        reuse to_reuse::foo3;
+        reuse F::foo4 { &F }
+        //~^ ERROR cannot find function `foo4` in `F`
+    }
 }
 
-struct S2(F);
+mod type_mismatch {
+    use crate::*;
 
-impl Trait for S2 {
-    reuse <S2 as Trait>::bar { &self.0 }
-    //~^ ERROR mismatched types
+    struct S2;
+    impl Trait for S {
+    //~^ ERROR conflicting implementations of trait `Trait` for type `S`
+        reuse <S2 as Trait>::foo1;
+        //~^ ERROR mismatched types
+        //~| ERROR the trait bound `S2: Trait` is not satisfied
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr
index 2994b2390de..30891c94c0e 100644
--- a/tests/ui/delegation/explicit-paths.stderr
+++ b/tests/ui/delegation/explicit-paths.stderr
@@ -1,38 +1,129 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/explicit-paths.rs:1:12
+error[E0407]: method `foo3` is not a member of trait `Trait`
+  --> $DIR/explicit-paths.rs:51:9
    |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
+LL |         reuse to_reuse::foo3;
+   |         ^^^^^^^^^^^^^^^^----^
+   |         |               |
+   |         |               help: there is an associated function with a similar name: `foo1`
+   |         not a member of trait `Trait`
+
+error[E0407]: method `foo4` is not a member of trait `Trait`
+  --> $DIR/explicit-paths.rs:53:9
+   |
+LL |         reuse F::foo4 { &self.0 }
+   |         ^^^^^^^^^----^^^^^^^^^^^^
+   |         |        |
+   |         |        help: there is an associated function with a similar name: `foo1`
+   |         not a member of trait `Trait`
+
+error[E0425]: cannot find function `foo4` in `S`
+  --> $DIR/explicit-paths.rs:29:14
+   |
+LL |     reuse S::foo4;
+   |              ^^^^ not found in `S`
+
+error[E0425]: cannot find function `foo4` in `F`
+  --> $DIR/explicit-paths.rs:40:18
+   |
+LL |         reuse F::foo4 { &self.0 }
+   |                  ^^^^ not found in `F`
+   |
+note: function `fn_to_other::foo4` exists but is inaccessible
+  --> $DIR/explicit-paths.rs:29:5
+   |
+LL |     reuse S::foo4;
+   |     ^^^^^^^^^^^^^^ not accessible
+
+error[E0425]: cannot find function `foo4` in `F`
+  --> $DIR/explicit-paths.rs:53:18
+   |
+LL |         reuse F::foo4 { &self.0 }
+   |                  ^^^^ not found in `F`
+   |
+note: function `fn_to_other::foo4` exists but is inaccessible
+  --> $DIR/explicit-paths.rs:29:5
+   |
+LL |     reuse S::foo4;
+   |     ^^^^^^^^^^^^^^ not accessible
+
+error[E0425]: cannot find function `foo4` in `F`
+  --> $DIR/explicit-paths.rs:67:18
+   |
+LL |         reuse F::foo4 { &F }
+   |                  ^^^^ not found in `F`
+   |
+note: function `fn_to_other::foo4` exists but is inaccessible
+  --> $DIR/explicit-paths.rs:29:5
    |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
+LL |     reuse S::foo4;
+   |     ^^^^^^^^^^^^^^ not accessible
+
+error[E0119]: conflicting implementations of trait `Trait` for type `S`
+  --> $DIR/explicit-paths.rs:76:5
+   |
+LL |     impl Trait for S {
+   |     ---------------- first implementation here
+...
+LL |     impl Trait for S {
+   |     ^^^^^^^^^^^^^^^^ conflicting implementation for `S`
+
+error: delegation to a trait method from a free function is not supported yet
+  --> $DIR/explicit-paths.rs:24:18
+   |
+LL |     fn foo1(&self, x: i32) -> i32 { x }
+   |     ----------------------------- callee defined here
+...
+LL |     reuse Trait::foo1;
+   |                  ^^^^
+
+error: delegation to a trait method from a free function is not supported yet
+  --> $DIR/explicit-paths.rs:26:25
+   |
+LL |     fn foo2(x: i32) -> i32 { x }
+   |     ---------------------- callee defined here
+...
+LL |     reuse <S as Trait>::foo2;
+   |                         ^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/explicit-paths.rs:14:25
+  --> $DIR/explicit-paths.rs:63:36
    |
-LL |     reuse <F as Trait>::bar;
-   |           --------------^^^
-   |           |             |
-   |           |             expected `&F`, found `&S`
-   |           arguments to this function are incorrect
+LL |     trait Trait2 : Trait {
+   |     -------------------- found this type parameter
+LL |         reuse <F as Trait>::foo1 { self }
+   |                                    ^^^^ expected `&F`, found `&Self`
    |
    = note: expected reference `&F`
-              found reference `&S`
-note: method defined here
-  --> $DIR/explicit-paths.rs:5:8
+              found reference `&Self`
+
+error[E0277]: the trait bound `S2: Trait` is not satisfied
+  --> $DIR/explicit-paths.rs:78:16
    |
-LL |     fn bar(&self) -> i32 { 42 }
-   |        ^^^ -----
+LL |         reuse <S2 as Trait>::foo1;
+   |                ^^ the trait `Trait` is not implemented for `S2`
+   |
+   = help: the following other types implement trait `Trait`:
+             F
+             S
 
 error[E0308]: mismatched types
-  --> $DIR/explicit-paths.rs:21:32
+  --> $DIR/explicit-paths.rs:78:30
    |
-LL |     reuse <S2 as Trait>::bar { &self.0 }
-   |                                ^^^^^^^ expected `&S2`, found `&F`
+LL |         reuse <S2 as Trait>::foo1;
+   |               ---------------^^^^
+   |               |              |
+   |               |              expected `&S2`, found `&S`
+   |               arguments to this function are incorrect
    |
    = note: expected reference `&S2`
-              found reference `&F`
+              found reference `&S`
+note: method defined here
+  --> $DIR/explicit-paths.rs:5:8
+   |
+LL |     fn foo1(&self, x: i32) -> i32 { x }
+   |        ^^^^ -----
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0119, E0277, E0308, E0407, E0425.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
index 23081b1e1fc..9dccb12b57a 100644
--- a/tests/ui/delegation/not-supported.rs
+++ b/tests/ui/delegation/not-supported.rs
@@ -1,6 +1,6 @@
 #![feature(c_variadic)]
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 mod generics {
     trait GenericTrait<T> {
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index 324b79f3c53..f6c49366899 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -1,12 +1,3 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/not-supported.rs:2:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: delegation with early bound generics is not supported yet
   --> $DIR/not-supported.rs:16:29
    |
@@ -178,7 +169,7 @@ LL |         pub reuse to_reuse2::foo;
 LL |     reuse to_reuse1::foo;
    |                      ^^^
 
-error: aborting due to 19 previous errors; 1 warning emitted
+error: aborting due to 19 previous errors
 
 Some errors have detailed explanations: E0049, E0195.
 For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/parse.rs b/tests/ui/delegation/parse.rs
index 5e8026c5532..72b00bf6e0d 100644
--- a/tests/ui/delegation/parse.rs
+++ b/tests/ui/delegation/parse.rs
@@ -2,7 +2,7 @@
 
 #![feature(decl_macro)]
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 macro_rules! reuse { {} => {} }
 
diff --git a/tests/ui/delegation/parse.stderr b/tests/ui/delegation/parse.stderr
deleted file mode 100644
index 1e420ceeec7..00000000000
--- a/tests/ui/delegation/parse.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/parse.rs:4:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs
index 1f2edf0dc13..9e326a19b8f 100644
--- a/tests/ui/delegation/target-expr-pass.rs
+++ b/tests/ui/delegation/target-expr-pass.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![feature(fn_delegation)]
-//~^ WARN the feature `fn_delegation` is incomplete
+#![allow(incomplete_features)]
 
 mod to_reuse {
     pub fn foo(x: i32) -> i32 { x }
diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr
index dd1f3a14e0b..c8d73ec6e5a 100644
--- a/tests/ui/delegation/target-expr-pass.stderr
+++ b/tests/ui/delegation/target-expr-pass.stderr
@@ -1,12 +1,3 @@
-warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/target-expr-pass.rs:3:12
-   |
-LL | #![feature(fn_delegation)]
-   |            ^^^^^^^^^^^^^
-   |
-   = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 warning: trait `Trait` is never used
   --> $DIR/target-expr-pass.rs:17:7
    |
@@ -27,5 +18,5 @@ warning: struct `S` is never constructed
 LL | struct S(F);
    |        ^
 
-warning: 4 warnings emitted
+warning: 3 warnings emitted
 
diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs
new file mode 100644
index 00000000000..fd7ea943b9d
--- /dev/null
+++ b/tests/ui/delegation/target-expr.rs
@@ -0,0 +1,40 @@
+#![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 to a trait method from a free function is not supported yet
+    //~| 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 {
+    //~^ ERROR delegation to a trait method from a free function is not supported yet
+        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..b30f0c474c6
--- /dev/null
+++ b/tests/ui/delegation/target-expr.stderr
@@ -0,0 +1,84 @@
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/target-expr.rs:20: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:29:17
+   |
+LL |         let x = y;
+   |                 ^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/target-expr.rs:36: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:38:13
+   |
+LL |     let z = x;
+   |             ^
+   |
+help: the binding `x` is available in a different scope in the same function
+  --> $DIR/target-expr.rs:29: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: delegation to a trait method from a free function 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: delegation to a trait method from a free function is not supported yet
+  --> $DIR/target-expr.rs:27:25
+   |
+LL |     fn static_method(x: i32) -> i32 { x }
+   |     ------------------------------- callee defined here
+...
+LL |     reuse <S as Trait>::static_method {
+   |                         ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/target-expr.rs:16:32
+   |
+LL |       reuse Trait::static_method {
+   |  ________________________________^
+LL | |
+LL | |
+LL | |
+LL | |         let _ = T::Default();
+LL | |
+LL | |     }
+   | |_____^ expected `i32`, found `()`
+
+error: aborting due to 8 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/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr
index f76701860ef..612a7aff225 100644
--- a/tests/ui/deriving/issue-103157.stderr
+++ b/tests/ui/deriving/issue-103157.stderr
@@ -8,14 +8,14 @@ LL |     Float(Option<f64>),
    |           ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64`, which is required by `Option<f64>: Eq`
    |
    = help: the following other types implement trait `Eq`:
-             isize
-             i8
+             i128
              i16
              i32
              i64
-             i128
-             usize
-             u8
+             i8
+             isize
+             u128
+             u16
            and 4 others
    = note: required for `Option<f64>` to implement `Eq`
 note: required by a bound in `AssertParamIsEq`
diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
index 6ac0bf21e4a..a2b7d804cb8 100644
--- a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
+++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -7,12 +7,12 @@ LL |     f1.foo(1usize);
    |        required by a bound introduced by this call
    |
    = help: the following other types implement trait `Foo<A>`:
-             <Bar as Foo<i8>>
              <Bar as Foo<i16>>
              <Bar as Foo<i32>>
-             <Bar as Foo<u8>>
+             <Bar as Foo<i8>>
              <Bar as Foo<u16>>
              <Bar as Foo<u32>>
+             <Bar as Foo<u8>>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index ae15e054f62..7229b9ac986 100644
--- a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -8,10 +8,10 @@ LL |     Foo::<i32>::bar(&1i8);
    |
    = help: the following other types implement trait `Foo<B>`:
              <i8 as Foo<bool>>
-             <i8 as Foo<u8>>
              <i8 as Foo<u16>>
              <i8 as Foo<u32>>
              <i8 as Foo<u64>>
+             <i8 as Foo<u8>>
 
 error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:21
@@ -38,10 +38,10 @@ LL |     Foo::<i32>::bar(&true);
    = help: the following other types implement trait `Foo<B>`:
              <bool as Foo<bool>>
              <bool as Foo<i8>>
-             <bool as Foo<u8>>
              <bool as Foo<u16>>
              <bool as Foo<u32>>
              <bool as Foo<u64>>
+             <bool as Foo<u8>>
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs
new file mode 100644
index 00000000000..13f8fd5fe22
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs
@@ -0,0 +1,16 @@
+#![crate_type = "lib"]
+
+// This isn't intended to compile, so it's easiest to just ignore this error.
+extern crate rustc_serialize; //~ERROR can't find crate for `rustc_serialize`
+
+#[derive(
+    RustcEncodable,
+    //~^   ERROR   use of unstable library feature 'rustc_encodable_decodable'
+    //~^^  WARNING this was previously accepted by the compiler
+    //~^^^ WARNING use of deprecated macro `RustcEncodable`
+    RustcDecodable,
+    //~^   ERROR   use of unstable library feature 'rustc_encodable_decodable'
+    //~^^  WARNING this was previously accepted by the compiler
+    //~^^^ WARNING use of deprecated macro `RustcDecodable`
+)]
+struct S;
diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr
new file mode 100644
index 00000000000..02b74dacf4d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr
@@ -0,0 +1,66 @@
+error[E0463]: can't find crate for `rustc_serialize`
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:4:1
+   |
+LL | extern crate rustc_serialize;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+   |
+   = help: maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5
+   |
+LL |     RustcEncodable,
+   |     ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+   = note: `#[deny(soft_unstable)]` on by default
+
+warning: use of deprecated macro `RustcEncodable`: rustc-serialize is deprecated and no longer supported
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5
+   |
+LL |     RustcEncodable,
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated)]` on by default
+
+error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5
+   |
+LL |     RustcDecodable,
+   |     ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+warning: use of deprecated macro `RustcDecodable`: rustc-serialize is deprecated and no longer supported
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5
+   |
+LL |     RustcDecodable,
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0463`.
+Future incompatibility report: Future breakage diagnostic:
+error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5
+   |
+LL |     RustcEncodable,
+   |     ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+   = note: `#[deny(soft_unstable)]` on by default
+
+Future breakage diagnostic:
+error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+  --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5
+   |
+LL |     RustcDecodable,
+   |     ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+   = note: `#[deny(soft_unstable)]` on by default
+
diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr
index 3c5428e59fb..a22bba07c02 100644
--- a/tests/ui/fmt/ifmt-unimpl.stderr
+++ b/tests/ui/fmt/ifmt-unimpl.stderr
@@ -7,14 +7,14 @@ LL |     format!("{:X}", "3");
    |              required by a bound introduced by this call
    |
    = help: the following other types implement trait `UpperHex`:
-             isize
-             i8
+             &T
+             &mut T
+             NonZero<T>
+             Saturating<T>
+             Wrapping<T>
+             i128
              i16
              i32
-             i64
-             i128
-             usize
-             u8
            and 9 others
    = note: required for `&str` to implement `UpperHex`
 note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex`
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/impl-trait/defining-use-captured-non-universal-region.infer.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
new file mode 100644
index 00000000000..ded9a92d8e8
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/defining-use-captured-non-universal-region.rs:13:18
+   |
+LL | fn foo<'a>() -> impl Sized + 'a {
+   |                              -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     let i: i32 = foo::<'_>();
+   |                  ^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
new file mode 100644
index 00000000000..e18302dc061
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
@@ -0,0 +1,22 @@
+// This was an ICE. See #110726.
+
+//@ revisions: statik infer fixed
+//@ [fixed] check-pass
+#![allow(unconditional_recursion)]
+
+fn foo<'a>() -> impl Sized + 'a {
+    #[cfg(statik)]
+    let i: i32 = foo::<'static>();
+    //[statik]~^ ERROR expected generic lifetime parameter, found `'static`
+
+    #[cfg(infer)]
+    let i: i32 = foo::<'_>();
+    //[infer]~^ ERROR expected generic lifetime parameter, found `'_`
+
+    #[cfg(fixed)]
+    let i: i32 = foo::<'a>();
+
+    i
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
new file mode 100644
index 00000000000..43beb29f9ec
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/defining-use-captured-non-universal-region.rs:9:18
+   |
+LL | fn foo<'a>() -> impl Sized + 'a {
+   |                              -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |     #[cfg(statik)]
+LL |     let i: i32 = foo::<'static>();
+   |                  ^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs
new file mode 100644
index 00000000000..56e099c28d2
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs
@@ -0,0 +1,74 @@
+// issue: #110623
+//@ check-pass
+
+use std::{collections::BTreeMap, num::ParseIntError, str::FromStr};
+
+enum FileSystem {
+    File(usize),
+    Directory(BTreeMap<String, FileSystem>),
+}
+
+impl FromStr for FileSystem {
+    type Err = ParseIntError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        if s.starts_with("dir") {
+            Ok(Self::new_dir())
+        } else {
+            Ok(Self::File(s.split_whitespace().next().unwrap().parse()?))
+        }
+    }
+}
+
+impl FileSystem {
+    fn new_dir() -> FileSystem {
+        FileSystem::Directory(BTreeMap::new())
+    }
+
+    fn insert(&mut self, name: String, other: FileSystem) -> Option<FileSystem> {
+        match self {
+            FileSystem::File(_) => panic!("can only insert into directory!"),
+            FileSystem::Directory(tree) => tree.insert(name, other),
+        }
+    }
+
+    // Recursively build a tree from commands. This uses (abuses?)
+    // the fact that `cd /` only appears at the start and that
+    // subsequent `cd`s can only move ONE level to use the recursion
+    // stack as the filesystem stack
+    fn build<'a>(
+        &mut self,
+        mut commands: impl Iterator<Item = &'a str> + 'a,
+    ) -> Option<impl Iterator<Item = &'a str> + 'a> {
+        let cmd = commands.next()?;
+        let mut elements = cmd.lines();
+        match elements.next().map(str::trim) {
+            Some("cd /") | None => self.build(commands),
+            Some("cd ..") => {
+                // return to higher scope
+                Some(commands)
+            }
+            Some("ls") => {
+                for item in elements {
+                    let name = item.split_whitespace().last().unwrap();
+                    let prior = self.insert(name.to_string(), item.parse().unwrap());
+                    debug_assert!(prior.is_none());
+                }
+                // continue on
+                self.build(commands)
+            }
+            Some(other_cd) => {
+                let name = other_cd
+                    .trim()
+                    .strip_prefix("cd ")
+                    .expect("expected a cd command");
+                let mut directory = FileSystem::new_dir();
+                let further_commands = directory.build(commands);
+                self.insert(name.to_string(), directory);
+                self.build(further_commands?) // THIS LINE FAILS TO COMPILE
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
new file mode 100644
index 00000000000..a6dcad3face
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+trait Bar<const FOO: &'static str> {}
+impl Bar<"asdf"> for () {}
+
+fn foo<const FOO: &'static str>() -> impl Bar<"asdf"> {
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs
new file mode 100644
index 00000000000..f90ff51c651
--- /dev/null
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs
@@ -0,0 +1,16 @@
+// issue: #111906
+//@ check-pass
+
+#![allow(unconditional_recursion)]
+
+fn foo<'a: 'a>() -> impl Sized {
+    let _: () = foo::<'a>();
+    loop {}
+}
+
+fn bar<'a: 'a>() -> impl Sized + 'a {
+    let _: *mut &'a () = bar::<'a>();
+    loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr
index 9b8bff215e0..69f4cbbbf42 100644
--- a/tests/ui/impl-trait/equality.stderr
+++ b/tests/ui/impl-trait/equality.stderr
@@ -30,10 +30,10 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `Add<impl Foo>` is not implemented for `u32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <u32 as Add>
-             <u32 as Add<&u32>>
              <&'a u32 as Add<u32>>
              <&u32 as Add<&u32>>
+             <u32 as Add<&u32>>
+             <u32 as Add>
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
index 1d648162113..78ef8ec404c 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
@@ -1,4 +1,4 @@
-error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
+error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
   --> $DIR/erased-regions-in-hidden-ty.rs:12:36
    |
 LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
index 1d648162113..78ef8ec404c 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
@@ -1,4 +1,4 @@
-error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
+error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
   --> $DIR/erased-regions-in-hidden-ty.rs:12:36
    |
 LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
index 9d71685f179..e60f1badcae 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
@@ -10,7 +10,7 @@
 // Make sure that the compiler can handle `ReErased` in the hidden type of an opaque.
 
 fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
-    //~^ ERROR 'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
+    //~^ ERROR '{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
     // Can't write whole type because of lack of path sanitization
     || ()
 }
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
index 15778662375..199cbbf4fcc 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
@@ -2,10 +2,8 @@
 use std::fmt::Debug;
 
 fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
-    //~^ ERROR cannot resolve opaque type
-
     |x| x
-    //~^ ERROR concrete type differs from previous defining opaque type use
+    //~^ ERROR expected generic lifetime parameter, found `'_`
 }
 
 fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
index c19420bbb0c..6064b09ef09 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
@@ -1,21 +1,11 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/impl-fn-predefined-lifetimes.rs:7:9
-   |
-LL |     |x| x
-   |         ^ expected `impl Debug + '_`, got `&u8`
-   |
-note: previous use here
-  --> $DIR/impl-fn-predefined-lifetimes.rs:7:5
-   |
-LL |     |x| x
-   |     ^^^^^
-
-error[E0720]: cannot resolve opaque type
-  --> $DIR/impl-fn-predefined-lifetimes.rs:4:35
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/impl-fn-predefined-lifetimes.rs:5:9
    |
 LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
-   |                                   ^^^^^^^^^^^^^^^ cannot resolve opaque type
+   |                                                -- this generic parameter must be used with a generic lifetime parameter
+LL |     |x| x
+   |         ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr
index 421afc96eed..d62e3ac4183 100644
--- a/tests/ui/impl-trait/impl_trait_projections.stderr
+++ b/tests/ui/impl-trait/impl_trait_projections.stderr
@@ -35,14 +35,14 @@ LL |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range<impl Debug>: Iterator`
    |
    = help: the following other types implement trait `Step`:
+             Char
+             Ipv4Addr
+             Ipv6Addr
              char
-             isize
-             i8
+             i128
              i16
              i32
              i64
-             i128
-             usize
            and 8 others
    = note: required for `std::ops::Range<impl Debug>` to implement `Iterator`
 
@@ -56,14 +56,14 @@ LL | | }
    | |_^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range<impl Debug>: Iterator`
    |
    = help: the following other types implement trait `Step`:
+             Char
+             Ipv4Addr
+             Ipv6Addr
              char
-             isize
-             i8
+             i128
              i16
              i32
              i64
-             i128
-             usize
            and 8 others
    = note: required for `std::ops::Range<impl Debug>` to implement `Iterator`
 
diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
index 41d5f0f6449..5b3a4eb53ff 100644
--- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
+++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
@@ -5,6 +5,7 @@ trait Foo {
     fn bar<'other: 'a>() -> impl Sized + 'a {}
     //~^ ERROR use of undeclared lifetime name `'a`
     //~| ERROR use of undeclared lifetime name `'a`
+    //~| ERROR expected generic lifetime parameter, found `'static`
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
index b0832eb33ca..8975578dabd 100644
--- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
+++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
@@ -28,6 +28,15 @@ help: consider introducing lifetime `'a` here
 LL | trait Foo<'a> {
    |          ++++
 
-error: aborting due to 2 previous errors
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/bad-item-bound-within-rpitit-2.rs:5:45
+   |
+LL |     fn bar<'other: 'a>() -> impl Sized + 'a {}
+   |            ------                           ^^
+   |            |
+   |            cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0261, E0792.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/impl-trait/no-method-suggested-traits.stderr b/tests/ui/impl-trait/no-method-suggested-traits.stderr
index 7a4dc366618..676247d1a42 100644
--- a/tests/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/tests/ui/impl-trait/no-method-suggested-traits.stderr
@@ -127,8 +127,8 @@ LL |     Foo.method();
    = note: the following traits define an item `method`, perhaps you need to implement one of them:
            candidate #1: `foo::Bar`
            candidate #2: `PubPub`
-           candidate #3: `no_method_suggested_traits::qux::PrivPub`
-           candidate #4: `Reexported`
+           candidate #3: `Reexported`
+           candidate #4: `no_method_suggested_traits::qux::PrivPub`
 
 error[E0599]: no method named `method` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:42:43
@@ -140,8 +140,8 @@ LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method();
    = note: the following traits define an item `method`, perhaps you need to implement one of them:
            candidate #1: `foo::Bar`
            candidate #2: `PubPub`
-           candidate #3: `no_method_suggested_traits::qux::PrivPub`
-           candidate #4: `Reexported`
+           candidate #3: `Reexported`
+           candidate #4: `no_method_suggested_traits::qux::PrivPub`
 
 error[E0599]: no method named `method2` found for type `u64` in the current scope
   --> $DIR/no-method-suggested-traits.rs:45:10
diff --git a/tests/ui/impl-trait/rpit/early_bound.rs b/tests/ui/impl-trait/rpit/early_bound.rs
index 6dda687929c..005bcea59f2 100644
--- a/tests/ui/impl-trait/rpit/early_bound.rs
+++ b/tests/ui/impl-trait/rpit/early_bound.rs
@@ -5,6 +5,7 @@ fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
     let true = n else { loop {} };
     let _ = || {
         let _ = identity::<&'a ()>(test(false));
+        //~^ ERROR expected generic lifetime parameter, found `'_`
     };
     loop {}
 }
diff --git a/tests/ui/impl-trait/rpit/early_bound.stderr b/tests/ui/impl-trait/rpit/early_bound.stderr
index 780dea4e284..b0c7bd4199c 100644
--- a/tests/ui/impl-trait/rpit/early_bound.stderr
+++ b/tests/ui/impl-trait/rpit/early_bound.stderr
@@ -1,3 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/early_bound.rs:7:17
+   |
+LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
+   |                                          -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |         let _ = identity::<&'a ()>(test(false));
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: concrete type differs from previous defining opaque type use
   --> $DIR/early_bound.rs:3:29
    |
@@ -10,5 +19,6 @@ note: previous use here
 LL |         let _ = identity::<&'a ()>(test(false));
    |                                    ^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
new file mode 100644
index 00000000000..5e04e6b091a
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
@@ -0,0 +1,37 @@
+// issue: #111935
+
+#![allow(unconditional_recursion)]
+
+// Lt indirection is necessary to make the lifetime of the function late-bound,
+// in order to bypass some other bugs.
+type Lt<'lt> = Option<*mut &'lt ()>;
+
+mod statik {
+    use super::*;
+    // invalid defining use: Opaque<'static> := ()
+    fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+        let _: () = foo(Lt::<'static>::None);
+        //~^ ERROR expected generic lifetime parameter, found `'static`
+    }
+}
+
+mod infer {
+    use super::*;
+    // invalid defining use: Opaque<'_> := ()
+    fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+        let _: () = foo(Lt::<'_>::None);
+        //~^ ERROR expected generic lifetime parameter, found `'_`
+    }
+}
+
+mod equal {
+    use super::*;
+    // invalid defining use: Opaque<'a, 'a> := ()
+    // because of the use of equal lifetimes in args
+    fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
+        let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
+        //~^ ERROR non-defining opaque type use in defining scope
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
new file mode 100644
index 00000000000..d2a224601fb
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
@@ -0,0 +1,31 @@
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/non-defining-use-lifetimes.rs:13:16
+   |
+LL |     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+   |                                           -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |         let _: () = foo(Lt::<'static>::None);
+   |                ^^
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/non-defining-use-lifetimes.rs:22:16
+   |
+LL |     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+   |                                           -- this generic parameter must be used with a generic lifetime parameter
+LL |         let _: () = foo(Lt::<'_>::None);
+   |                ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/non-defining-use-lifetimes.rs:32:16
+   |
+LL |         let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
+   |                ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/non-defining-use-lifetimes.rs:31:58
+   |
+LL |     fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
+   |                                                          ^^   ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/include-macros/parent_dir.rs b/tests/ui/include-macros/parent_dir.rs
new file mode 100644
index 00000000000..5fadff77a37
--- /dev/null
+++ b/tests/ui/include-macros/parent_dir.rs
@@ -0,0 +1,12 @@
+//@ normalize-stderr-test: "`: .*" -> "`: $$FILE_NOT_FOUND_MSG"
+
+fn main() {
+    let _ = include_str!("include-macros/file.txt");            //~ ERROR couldn't read
+                                                                //~^HELP different directory
+    let _ = include_str!("hello.rs");                           //~ ERROR couldn't read
+                                                                //~^HELP different directory
+    let _ = include_bytes!("../../data.bin");                   //~ ERROR couldn't read
+                                                                //~^HELP different directory
+    let _ = include_str!("tests/ui/include-macros/file.txt");   //~ ERROR couldn't read
+                                                                //~^HELP different directory
+}
diff --git a/tests/ui/include-macros/parent_dir.stderr b/tests/ui/include-macros/parent_dir.stderr
new file mode 100644
index 00000000000..0470d5b1f1e
--- /dev/null
+++ b/tests/ui/include-macros/parent_dir.stderr
@@ -0,0 +1,50 @@
+error: couldn't read `$DIR/include-macros/file.txt`: $FILE_NOT_FOUND_MSG
+  --> $DIR/parent_dir.rs:4:13
+   |
+LL |     let _ = include_str!("include-macros/file.txt");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: there is a file with the same name in a different directory
+   |
+LL |     let _ = include_str!("file.txt");
+   |                          ~~~~~~~~~~
+
+error: couldn't read `$DIR/hello.rs`: $FILE_NOT_FOUND_MSG
+  --> $DIR/parent_dir.rs:6:13
+   |
+LL |     let _ = include_str!("hello.rs");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: there is a file with the same name in a different directory
+   |
+LL |     let _ = include_str!("../hello.rs");
+   |                          ~~~~~~~~~~~~~
+
+error: couldn't read `$DIR/../../data.bin`: $FILE_NOT_FOUND_MSG
+  --> $DIR/parent_dir.rs:8:13
+   |
+LL |     let _ = include_bytes!("../../data.bin");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: there is a file with the same name in a different directory
+   |
+LL |     let _ = include_bytes!("data.bin");
+   |                            ~~~~~~~~~~
+
+error: couldn't read `$DIR/tests/ui/include-macros/file.txt`: $FILE_NOT_FOUND_MSG
+  --> $DIR/parent_dir.rs:10:13
+   |
+LL |     let _ = include_str!("tests/ui/include-macros/file.txt");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: there is a file with the same name in a different directory
+   |
+LL |     let _ = include_str!("file.txt");
+   |                          ~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr
index b37140f60f9..161fce4b031 100644
--- a/tests/ui/issues/issue-11771.stderr
+++ b/tests/ui/issues/issue-11771.stderr
@@ -6,14 +6,14 @@ LL |     1 +
    |
    = help: the trait `Add<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
-             <isize as Add>
-             <isize as Add<&isize>>
-             <i8 as Add>
-             <i8 as Add<&i8>>
-             <i16 as Add>
-             <i16 as Add<&i16>>
-             <i32 as Add>
-             <i32 as Add<&i32>>
+             <&'a f32 as Add<f32>>
+             <&'a f64 as Add<f64>>
+             <&'a i128 as Add<i128>>
+             <&'a i16 as Add<i16>>
+             <&'a i32 as Add<i32>>
+             <&'a i64 as Add<i64>>
+             <&'a i8 as Add<i8>>
+             <&'a isize as Add<isize>>
            and 48 others
 
 error[E0277]: cannot add `()` to `{integer}`
@@ -24,14 +24,14 @@ LL |     1 +
    |
    = help: the trait `Add<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
-             <isize as Add>
-             <isize as Add<&isize>>
-             <i8 as Add>
-             <i8 as Add<&i8>>
-             <i16 as Add>
-             <i16 as Add<&i16>>
-             <i32 as Add>
-             <i32 as Add<&i32>>
+             <&'a f32 as Add<f32>>
+             <&'a f64 as Add<f64>>
+             <&'a i128 as Add<i128>>
+             <&'a i16 as Add<i16>>
+             <&'a i32 as Add<i32>>
+             <&'a i64 as Add<i64>>
+             <&'a i8 as Add<i8>>
+             <&'a isize as Add<isize>>
            and 48 others
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-18446.stderr b/tests/ui/issues/issue-18446.stderr
index d84c490df4d..08a9cfc644f 100644
--- a/tests/ui/issues/issue-18446.stderr
+++ b/tests/ui/issues/issue-18446.stderr
@@ -4,17 +4,17 @@ error[E0034]: multiple applicable items in scope
 LL |     x.foo();
    |       ^^^ multiple `foo` found
    |
-note: candidate #1 is defined in an impl for the type `(dyn T + 'a)`
-  --> $DIR/issue-18446.rs:9:5
-   |
-LL |     fn foo(&self) {}
-   |     ^^^^^^^^^^^^^
-note: candidate #2 is defined in the trait `T`
+note: candidate #1 is defined in the trait `T`
   --> $DIR/issue-18446.rs:5:5
    |
 LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
-help: disambiguate the method for candidate #2
+note: candidate #2 is defined in an impl for the type `(dyn T + 'a)`
+  --> $DIR/issue-18446.rs:9:5
+   |
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
    |
 LL |     T::foo(&x);
    |     ~~~~~~~~~~
diff --git a/tests/ui/issues/issue-24352.stderr b/tests/ui/issues/issue-24352.stderr
index 015569cce06..a9f886158e1 100644
--- a/tests/ui/issues/issue-24352.stderr
+++ b/tests/ui/issues/issue-24352.stderr
@@ -6,10 +6,10 @@ LL |     1.0f64 - 1
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <f64 as Sub>
-             <f64 as Sub<&f64>>
              <&'a f64 as Sub<f64>>
              <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     1.0f64 - 1.0
diff --git a/tests/ui/issues/issue-3702-2.stderr b/tests/ui/issues/issue-3702-2.stderr
index 4edca796f43..7ab6520a0ca 100644
--- a/tests/ui/issues/issue-3702-2.stderr
+++ b/tests/ui/issues/issue-3702-2.stderr
@@ -4,24 +4,24 @@ error[E0034]: multiple applicable items in scope
 LL |         self.to_int() + other.to_int()
    |              ^^^^^^ multiple `to_int` found
    |
-note: candidate #1 is defined in an impl of the trait `ToPrimitive` for the type `isize`
-  --> $DIR/issue-3702-2.rs:2:5
-   |
-LL |     fn to_int(&self) -> isize { 0 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: candidate #2 is defined in an impl of the trait `Add` for the type `isize`
+note: candidate #1 is defined in an impl of the trait `Add` for the type `isize`
   --> $DIR/issue-3702-2.rs:14:5
    |
 LL |     fn to_int(&self) -> isize { *self }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-help: disambiguate the method for candidate #1
+note: candidate #2 is defined in an impl of the trait `ToPrimitive` for the type `isize`
+  --> $DIR/issue-3702-2.rs:2:5
    |
-LL |         ToPrimitive::to_int(&self) + other.to_int()
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the method for candidate #2
+LL |     fn to_int(&self) -> isize { 0 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
    |
 LL |         Add::to_int(&self) + other.to_int()
    |         ~~~~~~~~~~~~~~~~~~
+help: disambiguate the method for candidate #2
+   |
+LL |         ToPrimitive::to_int(&self) + other.to_int()
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr
index 7b65fa25ae3..1967b51128f 100644
--- a/tests/ui/issues/issue-50582.stderr
+++ b/tests/ui/issues/issue-50582.stderr
@@ -16,14 +16,14 @@ LL |     Vec::<[(); 1 + for x in 0..1 {}]>::new();
    |
    = help: the trait `Add<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
-             <isize as Add>
-             <isize as Add<&isize>>
-             <i8 as Add>
-             <i8 as Add<&i8>>
-             <i16 as Add>
-             <i16 as Add<&i16>>
-             <i32 as Add>
-             <i32 as Add<&i32>>
+             <&'a f32 as Add<f32>>
+             <&'a f64 as Add<f64>>
+             <&'a i128 as Add<i128>>
+             <&'a i16 as Add<i16>>
+             <&'a i32 as Add<i32>>
+             <&'a i64 as Add<i64>>
+             <&'a i8 as Add<i8>>
+             <&'a isize as Add<isize>>
            and 48 others
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
index 1bfe765e78a..4d1e4207fdc 100644
--- a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
@@ -33,8 +33,8 @@ LL |     println!("{}", scores.sum::<i32>());
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain-fixable.rs:14:10
    |
@@ -66,8 +66,8 @@ LL |             .sum::<i32>(),
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain-fixable.rs:23:14
    |
@@ -99,8 +99,8 @@ LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain-fixable.rs:27:38
    |
diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
index f68c596367e..9381a98e077 100644
--- a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
@@ -8,8 +8,8 @@ LL |     let x = Some(()).iter().map(|()| 1).sum::<f32>();
    |
    = help: the trait `Sum<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Sum<A>`:
-             <f32 as Sum>
              <f32 as Sum<&'a f32>>
+             <f32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:29
    |
diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr
index 4dc13086912..6129a724f44 100644
--- a/tests/ui/iterators/invalid-iterator-chain.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain.stderr
@@ -33,8 +33,8 @@ LL |     println!("{}", scores.sum::<i32>());
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:12:10
    |
@@ -65,8 +65,8 @@ LL |             .sum::<i32>(),
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:25:14
    |
@@ -104,8 +104,8 @@ LL |             .sum::<i32>(),
    |
    = help: the trait `Sum<f64>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:33:14
    |
@@ -134,8 +134,8 @@ LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:38:38
    |
@@ -162,8 +162,8 @@ LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:39:33
    |
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/lazy-type-alias/trailing-where-clause.stderr b/tests/ui/lazy-type-alias/trailing-where-clause.stderr
index baf4215bbf7..534df382eb6 100644
--- a/tests/ui/lazy-type-alias/trailing-where-clause.stderr
+++ b/tests/ui/lazy-type-alias/trailing-where-clause.stderr
@@ -5,12 +5,12 @@ LL |     let _: Alias<()>;
    |                  ^^ the trait `From<()>` is not implemented for `String`
    |
    = help: the following other types implement trait `From<T>`:
-             <String as From<char>>
+             <String as From<&String>>
+             <String as From<&mut str>>
+             <String as From<&str>>
              <String as From<Box<str>>>
              <String as From<Cow<'a, str>>>
-             <String as From<&str>>
-             <String as From<&mut str>>
-             <String as From<&String>>
+             <String as From<char>>
 note: required by a bound in `Alias`
   --> $DIR/trailing-where-clause.rs:8:13
    |
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/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs
index 20e6d705003..46e865031ec 100644
--- a/tests/ui/macros/macros-nonfatal-errors.rs
+++ b/tests/ui/macros/macros-nonfatal-errors.rs
@@ -1,4 +1,4 @@
-//@ normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG ("
+//@ normalize-stderr-test: "`: .*" -> "`: $$FILE_NOT_FOUND_MSG"
 
 // test that errors in a (selection) of macros don't kill compilation
 // immediately, so that we get more errors listed at a time.
diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr
index ca373ea6cd9..abf43e2a009 100644
--- a/tests/ui/macros/macros-nonfatal-errors.stderr
+++ b/tests/ui/macros/macros-nonfatal-errors.stderr
@@ -200,7 +200,7 @@ error: argument must be a string literal
 LL |     include_str!(invalid);
    |                  ^^^^^^^
 
-error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
+error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
   --> $DIR/macros-nonfatal-errors.rs:113:5
    |
 LL |     include_str!("i'd be quite surprised if a file with this name existed");
@@ -214,7 +214,7 @@ error: argument must be a string literal
 LL |     include_bytes!(invalid);
    |                    ^^^^^^^
 
-error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
+error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
   --> $DIR/macros-nonfatal-errors.rs:115:5
    |
 LL |     include_bytes!("i'd be quite surprised if a file with this name existed");
diff --git a/tests/ui/match/postfix-match/no-unused-parens.rs b/tests/ui/match/postfix-match/no-unused-parens.rs
new file mode 100644
index 00000000000..46cac7a6107
--- /dev/null
+++ b/tests/ui/match/postfix-match/no-unused-parens.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+
+#![feature(postfix_match)]
+
+fn main() {
+    (&1).match { a => a };
+    (1 + 2).match { b => b };
+}
diff --git a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
index 0c775612bfb..0fc0c909ea8 100644
--- a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
@@ -4,20 +4,20 @@ error[E0034]: multiple applicable items in scope
 LL | fn main() { 1_usize.me(); }
    |                     ^^ multiple `me` found
    |
-   = note: candidate #1 is defined in an impl of the trait `Me` for the type `usize`
-note: candidate #2 is defined in an impl of the trait `Me2` for the type `usize`
+note: candidate #1 is defined in an impl of the trait `Me2` for the type `usize`
   --> $DIR/method-ambig-two-traits-cross-crate.rs:10:22
    |
 LL | impl Me2 for usize { fn me(&self) -> usize { *self } }
    |                      ^^^^^^^^^^^^^^^^^^^^^
+   = note: candidate #2 is defined in an impl of the trait `Me` for the type `usize`
 help: disambiguate the method for candidate #1
    |
-LL | fn main() { Me::me(&1_usize); }
-   |             ~~~~~~~~~~~~~~~~
-help: disambiguate the method for candidate #2
-   |
 LL | fn main() { Me2::me(&1_usize); }
    |             ~~~~~~~~~~~~~~~~~
+help: disambiguate the method for candidate #2
+   |
+LL | fn main() { Me::me(&1_usize); }
+   |             ~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
index 9da307436e9..b36ef77fb7e 100644
--- a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
@@ -4,23 +4,23 @@ error[E0034]: multiple applicable items in scope
 LL |     1_usize.method();
    |             ^^^^^^ multiple `method` found
    |
-note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize`
-  --> $DIR/method-ambig-two-traits-with-default-method.rs:5:13
-   |
-LL | trait Foo { fn method(&self) {} }
-   |             ^^^^^^^^^^^^^^^^
-note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize`
+note: candidate #1 is defined in an impl of the trait `Bar` for the type `usize`
   --> $DIR/method-ambig-two-traits-with-default-method.rs:6:13
    |
 LL | trait Bar { fn method(&self) {} }
    |             ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Foo` for the type `usize`
+  --> $DIR/method-ambig-two-traits-with-default-method.rs:5:13
+   |
+LL | trait Foo { fn method(&self) {} }
+   |             ^^^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     Foo::method(&1_usize);
+LL |     Bar::method(&1_usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     Bar::method(&1_usize);
+LL |     Foo::method(&1_usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index 6df49e432a1..7d9b38fb29b 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -64,8 +64,8 @@ note: the trait `Iterator` must be implemented
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following traits define an item `take`, perhaps you need to implement one of them:
-           candidate #1: `std::io::Read`
-           candidate #2: `Iterator`
+           candidate #1: `Iterator`
+           candidate #2: `std::io::Read`
 
 error[E0061]: this method takes 3 arguments but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:21:7
diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 755179650bb..6159d87c73e 100644
--- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -29,33 +29,33 @@ error[E0034]: multiple applicable items in scope
 LL |     let z = x.foo();
    |               ^^^ multiple `foo` found
    |
-note: candidate #1 is defined in an impl of the trait `X` for the type `T`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:45:9
+note: candidate #1 is defined in the trait `FinalFoo`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:59:5
    |
-LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn foo(&self) -> u8;
+   |     ^^^^^^^^^^^^^^^^^^^^
 note: candidate #2 is defined in an impl of the trait `NuisanceFoo` for the type `T`
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:72:9
    |
 LL |         fn foo(self) {}
    |         ^^^^^^^^^^^^
-note: candidate #3 is defined in the trait `FinalFoo`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:59:5
+note: candidate #3 is defined in an impl of the trait `X` for the type `T`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:45:9
    |
-LL |     fn foo(&self) -> u8;
-   |     ^^^^^^^^^^^^^^^^^^^^
+LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     let z = X::foo(x);
-   |             ~~~~~~~~~
+LL |     let z = FinalFoo::foo(&x);
+   |             ~~~~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
 LL |     let z = NuisanceFoo::foo(x);
    |             ~~~~~~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #3
    |
-LL |     let z = FinalFoo::foo(&x);
-   |             ~~~~~~~~~~~~~~~~~
+LL |     let z = X::foo(x);
+   |             ~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24
diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
index b97688d3868..a665500fd9e 100644
--- a/tests/ui/methods/method-not-found-generic-arg-elision.stderr
+++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
@@ -35,10 +35,10 @@ LL |     wrapper.method();
    |             ^^^^^^ method not found in `Wrapper<bool>`
    |
    = note: the method was found for
-           - `Wrapper<i8>`
            - `Wrapper<i16>`
            - `Wrapper<i32>`
            - `Wrapper<i64>`
+           - `Wrapper<i8>`
            and 2 more types
 
 error[E0599]: no method named `other` found for struct `Wrapper` in the current scope
@@ -60,9 +60,9 @@ LL |     wrapper.method();
    |             ^^^^^^ method not found in `Wrapper2<'_, bool, 3>`
    |
    = note: the method was found for
-           - `Wrapper2<'a, i8, C>`
            - `Wrapper2<'a, i16, C>`
            - `Wrapper2<'a, i32, C>`
+           - `Wrapper2<'a, i8, C>`
 
 error[E0599]: no method named `other` found for struct `Wrapper2` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:98:13
diff --git a/tests/ui/mismatched_types/binops.stderr b/tests/ui/mismatched_types/binops.stderr
index b18ab7f7608..3585587ed4c 100644
--- a/tests/ui/mismatched_types/binops.stderr
+++ b/tests/ui/mismatched_types/binops.stderr
@@ -6,14 +6,14 @@ LL |     1 + Some(1);
    |
    = help: the trait `Add<Option<{integer}>>` is not implemented for `{integer}`
    = help: the following other types implement trait `Add<Rhs>`:
-             <isize as Add>
-             <isize as Add<&isize>>
-             <i8 as Add>
-             <i8 as Add<&i8>>
-             <i16 as Add>
-             <i16 as Add<&i16>>
-             <i32 as Add>
-             <i32 as Add<&i32>>
+             <&'a f32 as Add<f32>>
+             <&'a f64 as Add<f64>>
+             <&'a i128 as Add<i128>>
+             <&'a i16 as Add<i16>>
+             <&'a i32 as Add<i32>>
+             <&'a i64 as Add<i64>>
+             <&'a i8 as Add<i8>>
+             <&'a isize as Add<isize>>
            and 48 others
 
 error[E0277]: cannot subtract `Option<{integer}>` from `usize`
@@ -24,10 +24,10 @@ LL |     2 as usize - Some(1);
    |
    = help: the trait `Sub<Option<{integer}>>` is not implemented for `usize`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <usize as Sub>
-             <usize as Sub<&usize>>
              <&'a usize as Sub<usize>>
              <&usize as Sub<&usize>>
+             <usize as Sub<&usize>>
+             <usize as Sub>
 
 error[E0277]: cannot multiply `{integer}` by `()`
   --> $DIR/binops.rs:4:7
@@ -37,14 +37,14 @@ LL |     3 * ();
    |
    = help: the trait `Mul<()>` is not implemented for `{integer}`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <isize as Mul>
-             <isize as Mul<&isize>>
-             <i8 as Mul>
-             <i8 as Mul<&i8>>
-             <i16 as Mul>
-             <i16 as Mul<&i16>>
-             <i32 as Mul>
-             <i32 as Mul<&i32>>
+             <&'a f32 as Mul<f32>>
+             <&'a f64 as Mul<f64>>
+             <&'a i128 as Mul<i128>>
+             <&'a i16 as Mul<i16>>
+             <&'a i32 as Mul<i32>>
+             <&'a i64 as Mul<i64>>
+             <&'a i8 as Mul<i8>>
+             <&'a isize as Mul<isize>>
            and 49 others
 
 error[E0277]: cannot divide `{integer}` by `&str`
@@ -55,14 +55,14 @@ LL |     4 / "";
    |
    = help: the trait `Div<&str>` is not implemented for `{integer}`
    = help: the following other types implement trait `Div<Rhs>`:
-             <isize as Div>
-             <isize as Div<&isize>>
-             <i8 as Div>
-             <i8 as Div<&i8>>
-             <i16 as Div>
-             <i16 as Div<&i16>>
-             <i32 as Div>
-             <i32 as Div<&i32>>
+             <&'a f32 as Div<f32>>
+             <&'a f64 as Div<f64>>
+             <&'a i128 as Div<i128>>
+             <&'a i16 as Div<i16>>
+             <&'a i32 as Div<i32>>
+             <&'a i64 as Div<i64>>
+             <&'a i8 as Div<i8>>
+             <&'a isize as Div<isize>>
            and 54 others
 
 error[E0277]: can't compare `{integer}` with `String`
@@ -73,14 +73,14 @@ LL |     5 < String::new();
    |
    = help: the trait `PartialOrd<String>` is not implemented for `{integer}`
    = help: the following other types implement trait `PartialOrd<Rhs>`:
-             isize
-             i8
+             f32
+             f64
+             i128
              i16
              i32
              i64
-             i128
-             usize
-             u8
+             i8
+             isize
            and 6 others
 
 error[E0277]: can't compare `{integer}` with `Result<{integer}, _>`
@@ -91,14 +91,14 @@ LL |     6 == Ok(1);
    |
    = help: the trait `PartialEq<Result<{integer}, _>>` is not implemented for `{integer}`
    = help: the following other types implement trait `PartialEq<Rhs>`:
-             isize
-             i8
+             f32
+             f64
+             i128
              i16
              i32
              i64
-             i128
-             usize
-             u8
+             i8
+             isize
            and 6 others
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
index ff28480bd99..01abf2e17f1 100644
--- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
+++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -7,8 +7,8 @@ LL |     unconstrained_arg(return);
    |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `Test`:
-             i32
              ()
+             i32
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
    = help: did you intend to use the type `()` here instead?
 note: required by a bound in `unconstrained_arg`
diff --git a/tests/ui/never_type/issue-13352.stderr b/tests/ui/never_type/issue-13352.stderr
index 91885380b1f..1b979d93446 100644
--- a/tests/ui/never_type/issue-13352.stderr
+++ b/tests/ui/never_type/issue-13352.stderr
@@ -6,10 +6,10 @@ LL |     2_usize + (loop {});
    |
    = help: the trait `Add<()>` is not implemented for `usize`
    = help: the following other types implement trait `Add<Rhs>`:
-             <usize as Add>
-             <usize as Add<&usize>>
              <&'a usize as Add<usize>>
              <&usize as Add<&usize>>
+             <usize as Add<&usize>>
+             <usize as Add>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
index be0fc0f98e2..14685a3f937 100644
--- a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
+++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
@@ -6,10 +6,10 @@ LL |     x + 100.0
    |
    = help: the trait `Add<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Add<Rhs>`:
-             <u8 as Add>
-             <u8 as Add<&u8>>
              <&'a u8 as Add<u8>>
              <&u8 as Add<&u8>>
+             <u8 as Add<&u8>>
+             <u8 as Add>
 
 error[E0277]: cannot add `&str` to `f64`
   --> $DIR/not-suggest-float-literal.rs:6:7
@@ -19,10 +19,10 @@ LL |     x + "foo"
    |
    = help: the trait `Add<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Add<Rhs>`:
-             <f64 as Add>
-             <f64 as Add<&f64>>
              <&'a f64 as Add<f64>>
              <&f64 as Add<&f64>>
+             <f64 as Add<&f64>>
+             <f64 as Add>
 
 error[E0277]: cannot add `{integer}` to `f64`
   --> $DIR/not-suggest-float-literal.rs:11:7
@@ -32,10 +32,10 @@ LL |     x + y
    |
    = help: the trait `Add<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Add<Rhs>`:
-             <f64 as Add>
-             <f64 as Add<&f64>>
              <&'a f64 as Add<f64>>
              <&f64 as Add<&f64>>
+             <f64 as Add<&f64>>
+             <f64 as Add>
 
 error[E0277]: cannot subtract `{float}` from `u8`
   --> $DIR/not-suggest-float-literal.rs:15:7
@@ -45,10 +45,10 @@ LL |     x - 100.0
    |
    = help: the trait `Sub<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <u8 as Sub>
-             <u8 as Sub<&u8>>
              <&'a u8 as Sub<u8>>
              <&u8 as Sub<&u8>>
+             <u8 as Sub<&u8>>
+             <u8 as Sub>
 
 error[E0277]: cannot subtract `&str` from `f64`
   --> $DIR/not-suggest-float-literal.rs:19:7
@@ -58,10 +58,10 @@ LL |     x - "foo"
    |
    = help: the trait `Sub<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <f64 as Sub>
-             <f64 as Sub<&f64>>
              <&'a f64 as Sub<f64>>
              <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 
 error[E0277]: cannot subtract `{integer}` from `f64`
   --> $DIR/not-suggest-float-literal.rs:24:7
@@ -71,10 +71,10 @@ LL |     x - y
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <f64 as Sub>
-             <f64 as Sub<&f64>>
              <&'a f64 as Sub<f64>>
              <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 
 error[E0277]: cannot multiply `u8` by `{float}`
   --> $DIR/not-suggest-float-literal.rs:28:7
@@ -84,10 +84,10 @@ LL |     x * 100.0
    |
    = help: the trait `Mul<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <u8 as Mul>
-             <u8 as Mul<&u8>>
              <&'a u8 as Mul<u8>>
              <&u8 as Mul<&u8>>
+             <u8 as Mul<&u8>>
+             <u8 as Mul>
 
 error[E0277]: cannot multiply `f64` by `&str`
   --> $DIR/not-suggest-float-literal.rs:32:7
@@ -97,10 +97,10 @@ LL |     x * "foo"
    |
    = help: the trait `Mul<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <f64 as Mul>
-             <f64 as Mul<&f64>>
              <&'a f64 as Mul<f64>>
              <&f64 as Mul<&f64>>
+             <f64 as Mul<&f64>>
+             <f64 as Mul>
 
 error[E0277]: cannot multiply `f64` by `{integer}`
   --> $DIR/not-suggest-float-literal.rs:37:7
@@ -110,10 +110,10 @@ LL |     x * y
    |
    = help: the trait `Mul<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <f64 as Mul>
-             <f64 as Mul<&f64>>
              <&'a f64 as Mul<f64>>
              <&f64 as Mul<&f64>>
+             <f64 as Mul<&f64>>
+             <f64 as Mul>
 
 error[E0277]: cannot divide `u8` by `{float}`
   --> $DIR/not-suggest-float-literal.rs:41:7
@@ -123,11 +123,11 @@ LL |     x / 100.0
    |
    = help: the trait `Div<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Div<Rhs>`:
-             <u8 as Div>
-             <u8 as Div<NonZero<u8>>>
-             <u8 as Div<&u8>>
              <&'a u8 as Div<u8>>
              <&u8 as Div<&u8>>
+             <u8 as Div<&u8>>
+             <u8 as Div<NonZero<u8>>>
+             <u8 as Div>
 
 error[E0277]: cannot divide `f64` by `&str`
   --> $DIR/not-suggest-float-literal.rs:45:7
@@ -137,10 +137,10 @@ LL |     x / "foo"
    |
    = help: the trait `Div<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Div<Rhs>`:
-             <f64 as Div>
-             <f64 as Div<&f64>>
              <&'a f64 as Div<f64>>
              <&f64 as Div<&f64>>
+             <f64 as Div<&f64>>
+             <f64 as Div>
 
 error[E0277]: cannot divide `f64` by `{integer}`
   --> $DIR/not-suggest-float-literal.rs:50:7
@@ -150,10 +150,10 @@ LL |     x / y
    |
    = help: the trait `Div<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Div<Rhs>`:
-             <f64 as Div>
-             <f64 as Div<&f64>>
              <&'a f64 as Div<f64>>
              <&f64 as Div<&f64>>
+             <f64 as Div<&f64>>
+             <f64 as Div>
 
 error: aborting due to 12 previous errors
 
diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr
index 929a9e3b595..03779d35637 100644
--- a/tests/ui/numbers-arithmetic/suggest-float-literal.stderr
+++ b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr
@@ -6,10 +6,10 @@ LL |     x + 100
    |
    = help: the trait `Add<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <f32 as Add>
-             <f32 as Add<&f32>>
              <&'a f32 as Add<f32>>
              <&f32 as Add<&f32>>
+             <f32 as Add<&f32>>
+             <f32 as Add>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x + 100.0
@@ -23,10 +23,10 @@ LL |     x + 100
    |
    = help: the trait `Add<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Add<Rhs>`:
-             <f64 as Add>
-             <f64 as Add<&f64>>
              <&'a f64 as Add<f64>>
              <&f64 as Add<&f64>>
+             <f64 as Add<&f64>>
+             <f64 as Add>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x + 100.0
@@ -40,10 +40,10 @@ LL |     x - 100
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <f32 as Sub>
-             <f32 as Sub<&f32>>
              <&'a f32 as Sub<f32>>
              <&f32 as Sub<&f32>>
+             <f32 as Sub<&f32>>
+             <f32 as Sub>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x - 100.0
@@ -57,10 +57,10 @@ LL |     x - 100
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <f64 as Sub>
-             <f64 as Sub<&f64>>
              <&'a f64 as Sub<f64>>
              <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x - 100.0
@@ -74,10 +74,10 @@ LL |     x * 100
    |
    = help: the trait `Mul<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <f32 as Mul>
-             <f32 as Mul<&f32>>
              <&'a f32 as Mul<f32>>
              <&f32 as Mul<&f32>>
+             <f32 as Mul<&f32>>
+             <f32 as Mul>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x * 100.0
@@ -91,10 +91,10 @@ LL |     x * 100
    |
    = help: the trait `Mul<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <f64 as Mul>
-             <f64 as Mul<&f64>>
              <&'a f64 as Mul<f64>>
              <&f64 as Mul<&f64>>
+             <f64 as Mul<&f64>>
+             <f64 as Mul>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x * 100.0
@@ -108,10 +108,10 @@ LL |     x / 100
    |
    = help: the trait `Div<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Div<Rhs>`:
-             <f32 as Div>
-             <f32 as Div<&f32>>
              <&'a f32 as Div<f32>>
              <&f32 as Div<&f32>>
+             <f32 as Div<&f32>>
+             <f32 as Div>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x / 100.0
@@ -125,10 +125,10 @@ LL |     x / 100
    |
    = help: the trait `Div<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Div<Rhs>`:
-             <f64 as Div>
-             <f64 as Div<&f64>>
              <&'a f64 as Div<f64>>
              <&f64 as Div<&f64>>
+             <f64 as Div<&f64>>
+             <f64 as Div>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x / 100.0
diff --git a/tests/ui/on-unimplemented/multiple-impls.stderr b/tests/ui/on-unimplemented/multiple-impls.stderr
index f59c93a7c37..b50dc251baa 100644
--- a/tests/ui/on-unimplemented/multiple-impls.stderr
+++ b/tests/ui/on-unimplemented/multiple-impls.stderr
@@ -8,8 +8,8 @@ LL |     Index::index(&[] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Foo<usize>>>
              <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:33
@@ -21,8 +21,8 @@ LL |     Index::index(&[] as &[i32], Foo(2u32));
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
    = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Foo<usize>>>
              <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:33
@@ -34,8 +34,8 @@ LL |     Index::index(&[] as &[i32], Bar(2u32));
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
    = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Foo<usize>>>
              <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:5
@@ -45,8 +45,8 @@ LL |     Index::index(&[] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Foo<usize>>>
              <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:5
@@ -56,8 +56,8 @@ LL |     Index::index(&[] as &[i32], Foo(2u32));
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
    = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Foo<usize>>>
              <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:5
@@ -67,8 +67,8 @@ LL |     Index::index(&[] as &[i32], Bar(2u32));
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
    = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Foo<usize>>>
              <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index c0314fa42d7..f17f3cfce8d 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -17,8 +17,8 @@ LL |     x[..1i32];
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`, which is required by `[i32]: Index<_>`
    = help: the following other types implement trait `SliceIndex<T>`:
-             <RangeTo<usize> as SliceIndex<str>>
              <RangeTo<usize> as SliceIndex<[T]>>
+             <RangeTo<usize> as SliceIndex<str>>
    = note: required for `[i32]` to implement `Index<RangeTo<i32>>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/on-unimplemented/sum.stderr b/tests/ui/on-unimplemented/sum.stderr
index 257dec20074..65bab458cf1 100644
--- a/tests/ui/on-unimplemented/sum.stderr
+++ b/tests/ui/on-unimplemented/sum.stderr
@@ -8,8 +8,8 @@ LL |     vec![(), ()].iter().sum::<i32>();
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
-             <i32 as Sum>
              <i32 as Sum<&'a i32>>
+             <i32 as Sum>
 note: the method call chain might not have had the expected associated types
   --> $DIR/sum.rs:4:18
    |
@@ -30,8 +30,8 @@ LL |     vec![(), ()].iter().product::<i32>();
    |
    = help: the trait `Product<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Product<A>`:
-             <i32 as Product>
              <i32 as Product<&'a i32>>
+             <i32 as Product>
 note: the method call chain might not have had the expected associated types
   --> $DIR/sum.rs:7:18
    |
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/range/range-1.stderr b/tests/ui/range/range-1.stderr
index 3d9b7a940b7..f98420557c6 100644
--- a/tests/ui/range/range-1.stderr
+++ b/tests/ui/range/range-1.stderr
@@ -11,14 +11,14 @@ LL |     for i in false..true {}
    |              ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`, which is required by `std::ops::Range<bool>: IntoIterator`
    |
    = help: the following other types implement trait `Step`:
+             Char
+             Ipv4Addr
+             Ipv6Addr
              char
-             isize
-             i8
+             i128
              i16
              i32
              i64
-             i128
-             usize
            and 8 others
    = note: required for `std::ops::Range<bool>` to implement `Iterator`
    = note: required for `std::ops::Range<bool>` to implement `IntoIterator`
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/sanitizer/cfi-closure-fn-ptr-cast.rs b/tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs
index a46a3afd734..1ae494d87d4 100644
--- a/tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs
+++ b/tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs
@@ -5,11 +5,15 @@
 //
 // This checks that the reified function pointer will have the expected alias set at its call-site.
 
-//@ needs-sanitizer-cfi
+//@ revisions: cfi kcfi
 // FIXME(#122848) Remove only-linux once OSX CFI binaries work
 //@ only-linux
-//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
-//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
+//@ [cfi] needs-sanitizer-cfi
+//@ [kcfi] needs-sanitizer-kcfi
+//@ compile-flags: -C target-feature=-crt-static
+//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
+//@ [cfi] compile-flags: -Z sanitizer=cfi
+//@ [kcfi] compile-flags: -Z sanitizer=kcfi
 //@ run-pass
 
 pub fn main() {
diff --git a/tests/ui/sanitizer/cfi-complex-receiver.rs b/tests/ui/sanitizer/cfi-complex-receiver.rs
index c3e59258db2..52095a384b2 100644
--- a/tests/ui/sanitizer/cfi-complex-receiver.rs
+++ b/tests/ui/sanitizer/cfi-complex-receiver.rs
@@ -2,11 +2,15 @@
 // * Arc<dyn Foo> as for custom receivers
 // * &dyn Bar<T=Baz> for type constraints
 
-//@ needs-sanitizer-cfi
+//@ revisions: cfi kcfi
 // FIXME(#122848) Remove only-linux once OSX CFI binaries work
 //@ only-linux
-//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
-//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
+//@ [cfi] needs-sanitizer-cfi
+//@ [kcfi] needs-sanitizer-kcfi
+//@ compile-flags: -C target-feature=-crt-static
+//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
+//@ [cfi] compile-flags: -Z sanitizer=cfi
+//@ [kcfi] compile-flags: -Z sanitizer=kcfi
 //@ run-pass
 
 use std::sync::Arc;
diff --git a/tests/ui/sanitizer/cfi-drop-in-place.rs b/tests/ui/sanitizer/cfi-drop-in-place.rs
new file mode 100644
index 00000000000..8ce2c432602
--- /dev/null
+++ b/tests/ui/sanitizer/cfi-drop-in-place.rs
@@ -0,0 +1,20 @@
+// Verifies that drops can be called on arbitrary trait objects.
+//
+// FIXME(#122848): Remove only-linux when fixed.
+//@ only-linux
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Clto -Copt-level=0 -Cprefer-dynamic=off -Ctarget-feature=-crt-static -Zsanitizer=cfi
+//@ run-pass
+
+struct EmptyDrop;
+
+struct NonEmptyDrop;
+
+impl Drop for NonEmptyDrop {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let _ = Box::new(EmptyDrop) as Box<dyn Send>;
+    let _ = Box::new(NonEmptyDrop) as Box<dyn Send>;
+}
diff --git a/tests/ui/sanitizer/cfi-self-ref.rs b/tests/ui/sanitizer/cfi-self-ref.rs
index 32d0b100702..f8793aec6e2 100644
--- a/tests/ui/sanitizer/cfi-self-ref.rs
+++ b/tests/ui/sanitizer/cfi-self-ref.rs
@@ -1,10 +1,14 @@
 // Check that encoding self-referential types works with #[repr(transparent)]
 
-//@ needs-sanitizer-cfi
+//@ revisions: cfi kcfi
 // FIXME(#122848) Remove only-linux once OSX CFI binaries work
 //@ only-linux
-//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
-//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
+//@ [cfi] needs-sanitizer-cfi
+//@ [kcfi] needs-sanitizer-kcfi
+//@ compile-flags: -C target-feature=-crt-static
+//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
+//@ [cfi] compile-flags: -Z sanitizer=cfi
+//@ [kcfi] compile-flags: -Z sanitizer=kcfi
 //@ run-pass
 
 use std::marker::PhantomData;
diff --git a/tests/ui/sanitizer/cfi-virtual-auto.rs b/tests/ui/sanitizer/cfi-virtual-auto.rs
index 7a0c246a412..517c3d49f76 100644
--- a/tests/ui/sanitizer/cfi-virtual-auto.rs
+++ b/tests/ui/sanitizer/cfi-virtual-auto.rs
@@ -1,10 +1,14 @@
 // Tests that calling a trait object method on a trait object with additional auto traits works.
 
-//@ needs-sanitizer-cfi
+//@ revisions: cfi kcfi
 // FIXME(#122848) Remove only-linux once OSX CFI binaries work
 //@ only-linux
-//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
-//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
+//@ [cfi] needs-sanitizer-cfi
+//@ [kcfi] needs-sanitizer-kcfi
+//@ compile-flags: -C target-feature=-crt-static
+//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
+//@ [cfi] compile-flags: -Z sanitizer=cfi
+//@ [kcfi] compile-flags: -Z sanitizer=kcfi
 //@ run-pass
 
 trait Foo {
diff --git a/tests/ui/span/multiline-span-simple.stderr b/tests/ui/span/multiline-span-simple.stderr
index f0eec632aa1..2de792b03d7 100644
--- a/tests/ui/span/multiline-span-simple.stderr
+++ b/tests/ui/span/multiline-span-simple.stderr
@@ -6,10 +6,10 @@ LL |     foo(1 as u32 +
    |
    = help: the trait `Add<()>` is not implemented for `u32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <u32 as Add>
-             <u32 as Add<&u32>>
              <&'a u32 as Add<u32>>
              <&u32 as Add<&u32>>
+             <u32 as Add<&u32>>
+             <u32 as Add>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
index 6465eeb8bc6..e74c2c4214f 100644
--- a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
+++ b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
@@ -16,8 +16,8 @@ LL | fn bar() -> impl Bar {
    |             ^^^^^^^^ the trait `Bar` is not implemented for `()`
    |
    = help: the following other types implement trait `Bar`:
-             i32
              Qux
+             i32
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr
index d10a294c7d2..2fdfab8bdc5 100644
--- a/tests/ui/suggestions/into-str.stderr
+++ b/tests/ui/suggestions/into-str.stderr
@@ -8,12 +8,12 @@ LL |     foo(String::new());
    |
    = note: to coerce a `String` into a `&str`, use `&*` as a prefix
    = help: the following other types implement trait `From<T>`:
-             <String as From<char>>
+             <String as From<&String>>
+             <String as From<&mut str>>
+             <String as From<&str>>
              <String as From<Box<str>>>
              <String as From<Cow<'a, str>>>
-             <String as From<&str>>
-             <String as From<&mut str>>
-             <String as From<&String>>
+             <String as From<char>>
    = note: required for `String` to implement `Into<&str>`
 note: required by a bound in `foo`
   --> $DIR/into-str.rs:1:31
diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr
index 0f6bfbeec45..e626b5b0eb7 100644
--- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr
+++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -5,14 +5,14 @@ LL |     let _: &[i8] = data.into();
    |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`, which is required by `&[u8]: Into<_>`
    |
    = help: the following other types implement trait `From<T>`:
-             <[bool; N] as From<Mask<T, N>>>
-             <[T; N] as From<Simd<T, N>>>
+             <[T; 10] as From<(T, T, T, T, T, T, T, T, T, T)>>
+             <[T; 11] as From<(T, T, T, T, T, T, T, T, T, T, T)>>
+             <[T; 12] as From<(T, T, T, T, T, T, T, T, T, T, T, T)>>
              <[T; 1] as From<(T,)>>
              <[T; 2] as From<(T, T)>>
              <[T; 3] as From<(T, T, T)>>
              <[T; 4] as From<(T, T, T, T)>>
              <[T; 5] as From<(T, T, T, T, T)>>
-             <[T; 6] as From<(T, T, T, T, T, T)>>
            and 6 others
    = note: required for `&[u8]` to implement `Into<&[i8]>`
 
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
index bd9838bc623..27006f59b90 100644
--- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
@@ -6,13 +6,13 @@ LL |     s.strip_suffix(b'\n').unwrap_or(s)
    |
    = help: the trait `FnMut<(char,)>` is not implemented for `u8`, which is required by `u8: Pattern<'_>`
    = help: the following other types implement trait `Pattern<'a>`:
-             char
-             [char; N]
              &'b String
              &'b [char; N]
              &'b [char]
-             &'c &'b str
              &'b str
+             &'c &'b str
+             [char; N]
+             char
    = note: required for `u8` to implement `Pattern<'_>`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr
index 0d8bd8ee964..4d968e7bee1 100644
--- a/tests/ui/traits/method-on-unbounded-type-param.stderr
+++ b/tests/ui/traits/method-on-unbounded-type-param.stderr
@@ -9,10 +9,10 @@ LL |     a.cmp(&b)
    = help: items from traits can only be used if the type parameter is bounded by the trait
 help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them:
    |
-LL | fn f<T: Ord>(a: T, b: T) -> std::cmp::Ordering {
-   |       +++++
 LL | fn f<T: Iterator>(a: T, b: T) -> std::cmp::Ordering {
    |       ++++++++++
+LL | fn f<T: Ord>(a: T, b: T) -> std::cmp::Ordering {
+   |       +++++
 
 error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied
   --> $DIR/method-on-unbounded-type-param.rs:5:10
@@ -30,10 +30,10 @@ LL |     (&a).cmp(&b)
    = help: items from traits can only be used if the type parameter is bounded by the trait
 help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them:
    |
-LL | fn g<T: Ord>(a: T, b: T) -> std::cmp::Ordering {
-   |       +++++
 LL | fn g<T: Iterator>(a: T, b: T) -> std::cmp::Ordering {
    |       ++++++++++
+LL | fn g<T: Ord>(a: T, b: T) -> std::cmp::Ordering {
+   |       +++++
 
 error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied
   --> $DIR/method-on-unbounded-type-param.rs:8:7
@@ -51,10 +51,10 @@ LL |     a.cmp(&b)
    = help: items from traits can only be used if the type parameter is bounded by the trait
 help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them:
    |
-LL | fn h<T: Ord>(a: &T, b: T) -> std::cmp::Ordering {
-   |       +++++
 LL | fn h<T: Iterator>(a: &T, b: T) -> std::cmp::Ordering {
    |       ++++++++++
+LL | fn h<T: Ord>(a: &T, b: T) -> std::cmp::Ordering {
+   |       +++++
 
 error[E0599]: the method `cmp` exists for struct `Box<dyn T>`, but its trait bounds were not satisfied
   --> $DIR/method-on-unbounded-type-param.rs:14:7
@@ -76,8 +76,8 @@ LL |     x.cmp(&x);
            which is required by `&mut dyn T: Iterator`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following traits define an item `cmp`, perhaps you need to implement one of them:
-           candidate #1: `Ord`
-           candidate #2: `Iterator`
+           candidate #1: `Iterator`
+           candidate #2: `Ord`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr
index 79f270fd1bb..8a6c5fc10c5 100644
--- a/tests/ui/traits/question-mark-result-err-mismatch.stderr
+++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr
@@ -31,12 +31,12 @@ LL |         .map_err(|_| ())?;
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
-             <String as From<char>>
+             <String as From<&String>>
+             <String as From<&mut str>>
+             <String as From<&str>>
              <String as From<Box<str>>>
              <String as From<Cow<'a, str>>>
-             <String as From<&str>>
-             <String as From<&mut str>>
-             <String as From<&String>>
+             <String as From<char>>
    = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, ()>>`
 
 error[E0277]: `?` couldn't convert the error to `String`
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/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 817acc8fc99..e3edec6a4c7 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -10,8 +10,8 @@ LL |     Ok(Err(123_i32)?)
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
-             <u8 as From<bool>>
              <u8 as From<Char>>
+             <u8 as From<bool>>
    = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
 
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
@@ -24,8 +24,8 @@ LL |     Some(3)?;
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
    = help: the following other types implement trait `FromResidual<R>`:
-             <Result<T, F> as FromResidual<Yeet<E>>>
              <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
 
 error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:17:31
@@ -37,8 +37,8 @@ LL |     Ok(ControlFlow::Break(123)?)
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
    = help: the following other types implement trait `FromResidual<R>`:
-             <Result<T, F> as FromResidual<Yeet<E>>>
              <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:22:22
diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr
index 34618de78cd..a0dd18fa039 100644
--- a/tests/ui/try-trait/issue-32709.stderr
+++ b/tests/ui/try-trait/issue-32709.stderr
@@ -10,7 +10,6 @@ LL |     Err(5)?;
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
-             <(T,) as From<[T; 1]>>
              <(T, T) as From<[T; 2]>>
              <(T, T, T) as From<[T; 3]>>
              <(T, T, T, T) as From<[T; 4]>>
@@ -18,6 +17,7 @@ LL |     Err(5)?;
              <(T, T, T, T, T, T) as From<[T; 6]>>
              <(T, T, T, T, T, T, T) as From<[T; 7]>>
              <(T, T, T, T, T, T, T, T) as From<[T; 8]>>
+             <(T, T, T, T, T, T, T, T, T) as From<[T; 9]>>
            and 4 others
    = note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>`
 
diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr
index 1c4d718f1ee..fabc1ff2c76 100644
--- a/tests/ui/try-trait/option-to-result.stderr
+++ b/tests/ui/try-trait/option-to-result.stderr
@@ -9,8 +9,8 @@ LL |     a?;
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
    = help: the following other types implement trait `FromResidual<R>`:
-             <Result<T, F> as FromResidual<Yeet<E>>>
              <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/option-to-result.rs:11:6
diff --git a/tests/ui/try-trait/try-on-option.stderr b/tests/ui/try-trait/try-on-option.stderr
index eeb0439df29..fad6a1fe823 100644
--- a/tests/ui/try-trait/try-on-option.stderr
+++ b/tests/ui/try-trait/try-on-option.stderr
@@ -9,8 +9,8 @@ LL |     x?;
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
    = help: the following other types implement trait `FromResidual<R>`:
-             <Result<T, F> as FromResidual<Yeet<E>>>
              <Result<T, F> as FromResidual<Result<Infallible, E>>>
+             <Result<T, F> as FromResidual<Yeet<E>>>
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option.rs:11:6
diff --git a/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
new file mode 100644
index 00000000000..3b83b2e544b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
@@ -0,0 +1,18 @@
+// The defining use below has an unconstrained lifetime argument.
+// Opaque<'{empty}, 'a> := ();
+// Make sure we accept it because the lifetime parameter in such position is
+// irrelevant - it is an artifact of how we internally represent opaque
+// generics.
+// See issue #122307 for details.
+
+//@ check-pass
+#![feature(type_alias_impl_trait)]
+#![allow(unconditional_recursion)]
+
+type Opaque<'a> = impl Sized + 'a;
+
+fn test<'a>() -> Opaque<'a> {
+    let _: () = test::<'a>();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
index d97a3010a17..0e1d44e7bb3 100644
--- a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
+++ b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
@@ -8,12 +8,24 @@ impl<T> Equate for T { type Proj = T; }
 trait Indirect { type Ty; }
 impl<A, B: Equate<Proj = A>> Indirect for (A, B) { type Ty = (); }
 
-type Opq = impl Sized;
-fn define_1(_: Opq) {
-    let _ = None::<<(Opq, u8) as Indirect>::Ty>;
+mod basic {
+    use super::*;
+    type Opq = impl Sized;
+    fn define_1(_: Opq) {
+        let _ = None::<<(Opq, u8) as Indirect>::Ty>;
+    }
+    fn define_2() -> Opq {
+        0u8
+    }
 }
-fn define_2() -> Opq {
-    0u8
+
+// `Opq<'a> == &'b u8` shouldn't be an error because `'a == 'b`.
+mod lifetime {
+    use super::*;
+    type Opq<'a> = impl Sized + 'a;
+    fn define<'a: 'b, 'b: 'a>(_: Opq<'a>) {
+        let _ = None::<<(Opq<'a>, &'b u8) as Indirect>::Ty>;
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
new file mode 100644
index 00000000000..9101e4385b3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+mod case1 {
+    type Opaque<'x> = impl Sized + 'x;
+    fn foo<'s>() -> Opaque<'s> {
+        let _ = || { let _: Opaque<'s> = (); };
+        //~^ ERROR expected generic lifetime parameter, found `'_`
+    }
+}
+
+mod case2 {
+    type Opaque<'x> = impl Sized + 'x;
+    fn foo<'s>() -> Opaque<'s> {
+        let _ = || -> Opaque<'s> {};
+        //~^ ERROR expected generic lifetime parameter, found `'_`
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
new file mode 100644
index 00000000000..a8fd1f691dd
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
@@ -0,0 +1,21 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/defined-in-closure-external-lifetime.rs:6:29
+   |
+LL |     type Opaque<'x> = impl Sized + 'x;
+   |                 -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn foo<'s>() -> Opaque<'s> {
+LL |         let _ = || { let _: Opaque<'s> = (); };
+   |                             ^^^^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/defined-in-closure-external-lifetime.rs:14:34
+   |
+LL |     type Opaque<'x> = impl Sized + 'x;
+   |                 -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn foo<'s>() -> Opaque<'s> {
+LL |         let _ = || -> Opaque<'s> {};
+   |                                  ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
new file mode 100644
index 00000000000..59ba2694a76
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
@@ -0,0 +1,37 @@
+// issue: #112841
+
+#![feature(type_alias_impl_trait)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+mod mod1 {
+    type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    fn test<'a>() -> Opaque<'a, 'a> {}
+    //~^ ERROR non-defining opaque type use in defining scope
+    //~| ERROR non-defining opaque type use in defining scope
+}
+
+mod mod2 {
+    type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {}
+    //~^ ERROR non-defining opaque type use in defining scope
+}
+
+mod mod3 {
+    type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a }
+    //~^ ERROR non-defining opaque type use in defining scope
+}
+
+// This is similar to the previous cases in that 'a is equal to 'static,
+// which is is some sense an implicit parameter to `Opaque`.
+// For example, given a defining use `Opaque<'a> := &'a ()`,
+// it is ambiguous whether `Opaque<'a> := &'a ()` or `Opaque<'a> := &'static ()`
+mod mod4 {
+    type Opaque<'a> = impl super::Trait<'a, 'a>;
+    fn test<'a: 'static>() -> Opaque<'a> {}
+    //~^ ERROR expected generic lifetime parameter, found `'static`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
new file mode 100644
index 00000000000..b08bc8b8268
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
@@ -0,0 +1,59 @@
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:10:22
+   |
+LL |     fn test<'a>() -> Opaque<'a, 'a> {}
+   |                      ^^^^^^^^^^^^^^ generic argument `'a` used twice
+   |
+note: for this opaque type
+  --> $DIR/equal-lifetime-params-not-ok.rs:9:27
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:10:37
+   |
+LL |     fn test<'a>() -> Opaque<'a, 'a> {}
+   |                                     ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/equal-lifetime-params-not-ok.rs:9:17
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                 ^^  ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:17:49
+   |
+LL |     fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {}
+   |                                                 ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/equal-lifetime-params-not-ok.rs:16:17
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                 ^^  ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/equal-lifetime-params-not-ok.rs:23:61
+   |
+LL |     fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a }
+   |                                                             ^
+   |
+note: lifetime used multiple times
+  --> $DIR/equal-lifetime-params-not-ok.rs:22:17
+   |
+LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+   |                 ^^  ^^
+
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/equal-lifetime-params-not-ok.rs:33:42
+   |
+LL |     type Opaque<'a> = impl super::Trait<'a, 'a>;
+   |                 -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |     fn test<'a: 'static>() -> Opaque<'a> {}
+   |                                          ^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
new file mode 100644
index 00000000000..0ce85a4d6cb
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
@@ -0,0 +1,52 @@
+// Normally we do not allow equal lifetimes in opaque type generic args at
+// their defining sites. An exception to this rule, however, is when the bounds
+// of the opaque type *require* the lifetimes to be equal.
+// issue: #113916
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+#![feature(impl_trait_in_assoc_type)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+mod equal_params {
+    type Opaque<'a: 'b, 'b: 'a> = impl super::Trait<'a, 'b>;
+    fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {
+        let _ = None::<&'a &'b &'a ()>;
+        0u8
+    }
+}
+
+mod equal_static {
+    type Opaque<'a: 'static> = impl Sized + 'a;
+    fn test<'a: 'static>() -> Opaque<'a> {
+        let _ = None::<&'static &'a ()>;
+        0u8
+    }
+}
+
+mod implied_bounds {
+    trait Traitor {
+        type Assoc;
+        fn define(self) -> Self::Assoc;
+    }
+
+    impl<'a> Traitor for &'static &'a () {
+        type Assoc = impl Sized + 'a;
+        fn define(self) -> Self::Assoc {
+            let _ = None::<&'static &'a ()>;
+            0u8
+        }
+    }
+
+    impl<'a, 'b> Traitor for (&'a &'b (), &'b &'a ()) {
+        type Assoc = impl Sized + 'a + 'b;
+        fn define(self) -> Self::Assoc {
+            let _ = None::<(&'a &'b (), &'b &'a ())>;
+            0u8
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
new file mode 100644
index 00000000000..e5f86c8c193
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/generic-not-strictly-equal.rs:33:5
+   |
+LL | type Opaque<'a> = impl Copy + Captures<'a>;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     relate(opaque, hidden); // defining use: Opaque<'?1> := u8
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
new file mode 100644
index 00000000000..693af69d6fa
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
@@ -0,0 +1,15 @@
+error[E0700]: hidden type for `Opaque<'x>` captures lifetime that does not appear in bounds
+  --> $DIR/generic-not-strictly-equal.rs:33:5
+   |
+LL | type Opaque<'a> = impl Copy + Captures<'a>;
+   |                   ------------------------ opaque type defined here
+LL |
+LL | fn test<'x>(_: Opaque<'x>) {
+   |         -- hidden type `&'x u8` captures the lifetime `'x` as defined here
+...
+LL |     relate(opaque, hidden); // defining use: Opaque<'?1> := u8
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
new file mode 100644
index 00000000000..a059fd3b822
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
@@ -0,0 +1,38 @@
+// `Opaque<'?1> := u8` is not a valid defining use here.
+//
+// Due to fundamental limitations of the member constraints algorithm,
+// we require '?1 to be *equal* to some universal region.
+//
+// While '?1 is eventually inferred to be equal to 'x because of the constraint '?1: 'x,
+// we don't consider them equal in the strict sense because they lack the bidirectional outlives
+// constraints ['?1: 'x, 'x: '?1]. In NLL terms, they are not part of the same SCC.
+//
+// See #113971 for details.
+
+//@ revisions: basic member_constraints
+#![feature(type_alias_impl_trait)]
+
+trait Captures<'a> {}
+impl<T> Captures<'_> for T {}
+
+fn ensure_outlives<'a, X: 'a>(_: X) {}
+fn relate<X>(_: X, _: X) {}
+
+type Opaque<'a> = impl Copy + Captures<'a>;
+
+fn test<'x>(_: Opaque<'x>) {
+    let opaque = None::<Opaque<'_>>; // let's call this lifetime '?1
+
+    #[cfg(basic)]
+    let hidden = None::<u8>;
+
+    #[cfg(member_constraints)]
+    let hidden = None::<&'x u8>;
+
+    ensure_outlives::<'x>(opaque); // outlives constraint: '?1: 'x
+    relate(opaque, hidden); // defining use: Opaque<'?1> := u8
+    //[basic]~^ ERROR expected generic lifetime parameter, found `'_`
+    //[member_constraints]~^^ ERROR captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
index ef9fe604ea7..3b54fb7ea99 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
@@ -13,6 +13,7 @@ type FutNothing<'a> = impl 'a + Future<Output = ()>;
 async fn operation(_: &mut ()) -> () {
     //~^ ERROR: concrete type differs from previous
     call(operation).await
+    //~^ ERROR: expected generic lifetime parameter, found `'any`
 }
 
 async fn call<F>(_f: F)
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index d7a0452727e..c41ed0642a4 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -6,20 +6,17 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |
    = note: `FutNothing` must be used in combination with a concrete type within the same module
 
-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}`
-   |
-note: previous use here
+error[E0792]: expected generic lifetime parameter, found `'any`
   --> $DIR/hkl_forbidden4.rs:15:5
    |
+LL | async fn operation(_: &mut ()) -> () {
+   |                       - this generic parameter must be used with a generic lifetime parameter
+LL |
 LL |     call(operation).await
    |     ^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:21:1
+  --> $DIR/hkl_forbidden4.rs:22:1
    |
 LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                   -- this generic parameter must be used with a generic lifetime parameter
@@ -29,6 +26,18 @@ LL | |
 LL | | }
    | |_^
 
-error: aborting due to 3 previous errors
+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 of operation()}`
+   |
+note: previous use here
+  --> $DIR/hkl_forbidden4.rs:15:5
+   |
+LL |     call(operation).await
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
index 9ec585d93f5..45a55050c44 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
@@ -5,7 +5,6 @@ type Foo<'a> = impl Sized;
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
     (x, y)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 type Bar<'a, 'b> = impl std::fmt::Debug;
@@ -13,9 +12,6 @@ type Bar<'a, 'b> = impl std::fmt::Debug;
 fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) {
     (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
index 7f54f47d27d..4f7b0f17407 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
@@ -14,53 +14,7 @@ LL |     (x, y)
    |     ^^^^^^
 
 error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:6:5
-   |
-LL |     (x, y)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'a` used here
-   |     lifetime `'b` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:6:5
-   |
-LL |     (x, y)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'x` used here
-   |     lifetime `'y` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
+  --> $DIR/lifetime_mismatch.rs:13:5
    |
 LL |     (i, j)
    |     ^^^^^^
@@ -69,27 +23,10 @@ LL |     (i, j)
    |     lifetime `'y` previously used here
    |
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
+  --> $DIR/lifetime_mismatch.rs:13:5
    |
 LL |     (i, j)
    |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
index 5bec38c5e5b..580fb58ef83 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
@@ -3,11 +3,8 @@
 type Foo<'a, 'b> = impl std::fmt::Debug;
 
 fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
-    (i, i)
+    (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
index 0ccb3e2221d..b2b9e604a6b 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
@@ -1,7 +1,7 @@
 error: opaque type used twice with different lifetimes
   --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
    |
-LL |     (i, i)
+LL |     (i, j)
    |     ^^^^^^
    |     |
    |     lifetime `'x` used here
@@ -10,55 +10,8 @@ LL |     (i, i)
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
   --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
    |
-LL |     (i, i)
+LL |     (i, j)
    |     ^^^^^^
 
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'x` used here
-   |     lifetime `'y` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr
index c549ca5b2ce..241342b0509 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr
@@ -8,8 +8,8 @@ LL |     ()
    |     -- return type was inferred to be `()` here
    |
    = help: the following other types implement trait `Foo<A>`:
-             <() as Foo<u32>>
              <() as Foo<()>>
+             <() as Foo<u32>>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.rs b/tests/ui/type-alias-impl-trait/param_mismatch4.rs
new file mode 100644
index 00000000000..e072f3ab8e0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/param_mismatch4.rs
@@ -0,0 +1,16 @@
+//! This test checks that when checking for opaque types that
+//! only differ in lifetimes, we handle the case of non-generic
+//! regions correctly.
+#![feature(type_alias_impl_trait)]
+
+type Opq<'a> = impl Sized;
+
+// Two defining uses: Opq<'{empty}> and Opq<'a>.
+// This used to ICE.
+// issue: #122782
+fn build<'a>() -> Opq<'a> {
+    let _: Opq<'_> = ();
+    //~^ ERROR expected generic lifetime parameter, found `'_`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
new file mode 100644
index 00000000000..d3fdea25a3d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/param_mismatch4.rs:12:12
+   |
+LL | type Opq<'a> = impl Sized;
+   |          -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     let _: Opq<'_> = ();
+   |            ^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
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/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr
index 10d600cbfcc..9ba63ffe9c9 100644
--- a/tests/ui/type/type-check-defaults.stderr
+++ b/tests/ui/type/type-check-defaults.stderr
@@ -66,10 +66,10 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
    |
    = help: the trait `Add<u8>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <i32 as Add>
-             <i32 as Add<&i32>>
              <&'a i32 as Add<i32>>
              <&i32 as Add<&i32>>
+             <i32 as Add<&i32>>
+             <i32 as Add>
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/typeck/issue-81293.stderr b/tests/ui/typeck/issue-81293.stderr
index 292c63070ae..6976be71135 100644
--- a/tests/ui/typeck/issue-81293.stderr
+++ b/tests/ui/typeck/issue-81293.stderr
@@ -21,10 +21,10 @@ LL |     a = c + b * 5;
    |
    = help: the trait `Add<u16>` is not implemented for `usize`
    = help: the following other types implement trait `Add<Rhs>`:
-             <usize as Add>
-             <usize as Add<&usize>>
              <&'a usize as Add<usize>>
              <&usize as Add<&usize>>
+             <usize as Add<&usize>>
+             <usize as Add>
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr
index d5ba157974d..800d7e9594a 100644
--- a/tests/ui/typeck/issue-90101.stderr
+++ b/tests/ui/typeck/issue-90101.stderr
@@ -7,11 +7,11 @@ LL |     func(Path::new("hello").to_path_buf().to_string_lossy(), "world")
    |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `From<T>`:
+             <PathBuf as From<&T>>
              <PathBuf as From<Box<Path>>>
              <PathBuf as From<Cow<'a, Path>>>
              <PathBuf as From<OsString>>
              <PathBuf as From<String>>
-             <PathBuf as From<&T>>
    = note: required for `Cow<'_, str>` to implement `Into<PathBuf>`
 note: required by a bound in `func`
   --> $DIR/issue-90101.rs:3:20
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index 8bcad56916a..7977504dae1 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -546,6 +546,15 @@ help: use type parameters instead
 LL |         fn fn_test10<T>(&self, _x : T) { }
    |                     +++             ~
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
+  --> $DIR/typeck_type_placeholder_item.rs:194:14
+   |
+LL |     const D: _ = 42;
+   |              ^
+   |              |
+   |              not allowed in type signatures
+   |              help: replace with the correct type: `i32`
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:217:31
    |
@@ -574,19 +583,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:209:14
    |
 LL |     const D: _ = 42;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `i32`
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:194:14
-   |
-LL |     const D: _ = 42;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `i32`
+   |              ^ not allowed in type signatures
 
 error[E0046]: not all trait items implemented, missing: `F`
   --> $DIR/typeck_type_placeholder_item.rs:200:1
diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index c1281ce6a42..964fd4af009 100644
--- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -6,10 +6,10 @@ LL |     <i32 as Add<u32>>::add(1, 2);
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <i32 as Add>
-             <i32 as Add<&i32>>
              <&'a i32 as Add<i32>>
              <&i32 as Add<&i32>>
+             <i32 as Add<&i32>>
+             <i32 as Add>
 
 error[E0277]: cannot add `u32` to `i32`
   --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
@@ -19,10 +19,10 @@ LL |     <i32 as Add<u32>>::add(1, 2);
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <i32 as Add>
-             <i32 as Add<&i32>>
              <&'a i32 as Add<i32>>
              <&i32 as Add<&i32>>
+             <i32 as Add<&i32>>
+             <i32 as Add>
 
 error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:7:28
diff --git a/triagebot.toml b/triagebot.toml
index a42bafe148c..0df71c60d54 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.
@@ -709,6 +717,9 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 [mentions."src/doc/unstable-book/src/compiler-flags/check-cfg.md"]
 cc = ["@Urgau"]
 
+[mentions."src/doc/rustc/src/platform-support"]
+cc = ["@Nilstrieb"]
+
 [mentions."tests/codegen/sanitizer"]
 cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]