about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2025-02-01 05:39:41 +0000
committerGitHub <noreply@github.com>2025-02-01 05:39:41 +0000
commitb82463fcbfd2ed60a77003261445df0f430a3e50 (patch)
tree532e602a81dd19c551f37b0cdc93e5b811c4b13b
parent829bfc3f5ee4c4826b2571da419722e3242aa155 (diff)
parentc925c826bf4eb093f1b6bcded7a4b99a9d489851 (diff)
downloadrust-b82463fcbfd2ed60a77003261445df0f430a3e50.tar.gz
rust-b82463fcbfd2ed60a77003261445df0f430a3e50.zip
Merge pull request #4169 from rust-lang/rustup-2025-02-01
Automatic Rustup
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_ast/src/expand/autodiff_attrs.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs4
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs38
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs118
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/debuginfo.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/misc.rs4
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs45
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs53
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs3
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/thousands/mod.rs16
-rw-r--r--compiler/rustc_data_structures/src/thousands/tests.rs14
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs5
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs82
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs94
-rw-r--r--compiler/rustc_hir_analysis/src/delegation.rs360
-rw-r--r--compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/variance/xform.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs1
-rw-r--r--compiler/rustc_infer/src/infer/at.rs24
-rw-r--r--compiler/rustc_interface/src/passes.rs91
-rw-r--r--compiler/rustc_interface/src/tests.rs13
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp222
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs6
-rw-r--r--compiler/rustc_middle/messages.ftl7
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/error.rs14
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs23
-rw-r--r--compiler/rustc_middle/src/macros.rs31
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs4
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs15
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs43
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs1
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs6
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/query/keys.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs7
-rw-r--r--compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs2
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs17
-rw-r--r--compiler/rustc_middle/src/util/bug.rs6
-rw-r--r--compiler/rustc_middle/src/util/common.rs22
-rw-r--r--compiler/rustc_middle/src/util/common/tests.rs14
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs47
-rw-r--r--compiler/rustc_middle/src/util/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs7
-rw-r--r--compiler/rustc_mir_build/src/lib.rs7
-rw-r--r--compiler/rustc_mir_build/src/thir/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs12
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs198
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_null.rs110
-rw-r--r--compiler/rustc_mir_transform/src/check_pointers.rs234
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs6
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs19
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs32
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/autodiff.rs121
-rw-r--r--compiler/rustc_passes/src/check_attr.rs1
-rw-r--r--compiler/rustc_passes/src/input_stats.rs16
-rw-r--r--compiler/rustc_session/src/code_stats.rs60
-rw-r--r--compiler/rustc_session/src/config.rs36
-rw-r--r--compiler/rustc_session/src/options.rs51
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs4
-rw-r--r--compiler/rustc_target/src/asm/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/messages.ftl2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs105
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs175
-rw-r--r--compiler/stable_mir/src/mir/body.rs2
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs3
-rw-r--r--compiler/stable_mir/src/mir/visit.rs5
-rw-r--r--library/core/src/hint.rs4
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/panicking.rs16
-rw-r--r--library/core/src/sync/atomic.rs18
-rw-r--r--library/coretests/tests/lib.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs9
-rw-r--r--src/ci/github-actions/jobs.yml6
-rw-r--r--src/doc/rustc-dev-guide/src/building/new-target.md5
-rw-r--r--src/doc/rustc-dev-guide/src/compiler-debugging.md2
-rw-r--r--src/doc/rustc-dev-guide/src/conventions.md2
-rw-r--r--src/doc/rustc/src/profile-guided-optimization.md2
-rw-r--r--src/doc/rustc/src/target-tier-policy.md11
-rw-r--r--src/doc/rustdoc/src/unstable-features.md64
-rw-r--r--src/doc/style-guide/src/editions.md4
-rw-r--r--src/doc/style-guide/src/expressions.md55
-rw-r--r--src/doc/unstable-book/src/compiler-flags/autodiff.md23
-rw-r--r--src/librustdoc/config.rs60
-rw-r--r--src/librustdoc/doctest.rs51
-rw-r--r--src/librustdoc/doctest/extracted.rs141
-rw-r--r--src/librustdoc/lib.rs10
-rw-r--r--src/tools/clippy/src/driver.rs2
m---------src/tools/enzyme0
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs18
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs20
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs40
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/src/machine.rs11
-rw-r--r--src/tools/miri/src/shims/extern_static.rs8
-rw-r--r--src/tools/miri/src/shims/panic.rs11
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs24
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.rs52
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.stdout2
-rw-r--r--src/tools/miri/tests/ui.rs33
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
-rw-r--r--src/tools/rustfmt/src/bin/main.rs9
-rw-r--r--src/tools/rustfmt/src/config/mod.rs2
-rw-r--r--src/tools/rustfmt/src/config/options.rs4
-rw-r--r--src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs73
-rw-r--r--tests/codegen/addr-of-mutate.rs6
-rw-r--r--tests/codegen/asm/bpf-clobbers.rs31
-rw-r--r--tests/codegen/cast-target-abi.rs2
-rw-r--r--tests/codegen/function-arguments.rs4
-rw-r--r--tests/codegen/i128-x86-align.rs21
-rw-r--r--tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs4
-rw-r--r--tests/codegen/packed.rs4
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64d-abi.rs2
-rw-r--r--tests/mir-opt/null_check_references.rs16
-rw-r--r--tests/rustdoc-ui/coverage/html.stderr2
-rw-r--r--tests/rustdoc-ui/doctest-output.rs1
-rw-r--r--tests/rustdoc-ui/doctest-output.stderr2
-rw-r--r--tests/rustdoc-ui/extract-doctests.rs15
-rw-r--r--tests/rustdoc-ui/extract-doctests.stdout1
-rw-r--r--tests/rustdoc-ui/intra-doc/auxiliary/issue-103463-aux.rs (renamed from tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs)0
-rw-r--r--tests/rustdoc-ui/intra-doc/ice-extern-trait-local-impl-104145.rs (renamed from tests/rustdoc/intra-doc/issue-104145.rs)3
-rw-r--r--tests/rustdoc-ui/intra-doc/ice-priv-use-103463.rs (renamed from tests/rustdoc/intra-doc/issue-103463.rs)3
-rw-r--r--tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr2
-rw-r--r--tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr2
-rw-r--r--tests/rustdoc/inline_cross/doc-hidden-broken-link-28480.rs (renamed from tests/rustdoc/inline_cross/issue-28480.rs)5
-rw-r--r--tests/rustdoc/inline_cross/doc-reachability-impl-31948-1.rs (renamed from tests/rustdoc/inline_cross/issue-31948-1.rs)13
-rw-r--r--tests/rustdoc/inline_cross/doc-reachability-impl-31948-2.rs (renamed from tests/rustdoc/inline_cross/issue-31948-2.rs)13
-rw-r--r--tests/rustdoc/inline_cross/doc-reachability-impl-31948.rs (renamed from tests/rustdoc/inline_cross/issue-31948.rs)17
-rw-r--r--tests/rustdoc/inline_cross/impl-dyn-trait-32881.rs (renamed from tests/rustdoc/inline_cross/issue-32881.rs)5
-rw-r--r--tests/rustdoc/inline_cross/impl-ref-33113.rs (renamed from tests/rustdoc/inline_cross/issue-33113.rs)5
-rw-r--r--tests/rustdoc/inline_cross/rustc-private-76736-1.rs (renamed from tests/rustdoc/inline_cross/issue-76736-1.rs)2
-rw-r--r--tests/rustdoc/inline_cross/rustc-private-76736-2.rs (renamed from tests/rustdoc/inline_cross/issue-76736-2.rs)2
-rw-r--r--tests/rustdoc/inline_cross/rustc-private-76736-3.rs (renamed from tests/rustdoc/inline_cross/issue-76736-3.rs)2
-rw-r--r--tests/rustdoc/inline_cross/rustc-private-76736-4.rs (renamed from tests/rustdoc/inline_cross/issue-76736-4.rs)2
-rw-r--r--tests/rustdoc/inline_cross/self-sized-bounds-24183.method_no_where_self_sized.html (renamed from tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html)0
-rw-r--r--tests/rustdoc/inline_cross/self-sized-bounds-24183.rs (renamed from tests/rustdoc/inline_cross/issue-24183.rs)1
-rw-r--r--tests/rustdoc/inline_local/doc-no-inline-32343.rs (renamed from tests/rustdoc/inline_local/issue-32343.rs)13
-rw-r--r--tests/rustdoc/inline_local/pub-re-export-28537.rs (renamed from tests/rustdoc/inline_local/issue-28537.rs)7
-rw-r--r--tests/rustdoc/intra-doc/enum-self-82209.rs (renamed from tests/rustdoc/intra-doc/issue-82209.rs)2
-rw-r--r--tests/rustdoc/intra-doc/link-same-name-different-disambiguator-108459.rs (renamed from tests/rustdoc/intra-doc/issue-108459.rs)11
-rw-r--r--tests/rustdoc/intra-doc/same-name-different-crates-66159.rs (renamed from tests/rustdoc/intra-doc/issue-66159.rs)5
-rw-r--r--tests/ui/abi/segfault-no-out-of-stack.rs1
-rw-r--r--tests/ui/associated-consts/associated-const-in-trait.stderr4
-rw-r--r--tests/ui/associated-item/issue-48027.stderr2
-rw-r--r--tests/ui/async-await/async-fn/dyn-pos.stderr2
-rw-r--r--tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr18
-rw-r--r--tests/ui/async-await/in-trait/dyn-compatibility.stderr2
-rw-r--r--tests/ui/async-await/inference_var_self_argument.stderr2
-rw-r--r--tests/ui/closures/return-type-doesnt-match-bound.rs25
-rw-r--r--tests/ui/closures/return-type-doesnt-match-bound.stderr37
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-102768.stderr2
-rw-r--r--tests/ui/consts/const-slice-array-deref.rs9
-rw-r--r--tests/ui/consts/const-slice-array-deref.stderr33
-rw-r--r--tests/ui/diagnostic-width/long-E0308.ascii.stderr16
-rw-r--r--tests/ui/diagnostic-width/long-E0308.rs4
-rw-r--r--tests/ui/diagnostic-width/long-E0308.unicode.stderr16
-rw-r--r--tests/ui/diagnostic-width/non-copy-type-moved.rs4
-rw-r--r--tests/ui/diagnostic-width/non-copy-type-moved.stderr4
-rw-r--r--tests/ui/diagnostic-width/secondary-label-with-long-type.rs4
-rw-r--r--tests/ui/diagnostic-width/secondary-label-with-long-type.stderr4
-rw-r--r--tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr2
-rw-r--r--tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr6
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.curr.stderr4
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr2
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr4
-rw-r--r--tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr2
-rw-r--r--tests/ui/dyn-compatibility/bounds.stderr2
-rw-r--r--tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr2
-rw-r--r--tests/ui/dyn-compatibility/generics.curr.stderr10
-rw-r--r--tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr4
-rw-r--r--tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr4
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr6
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.curr.stderr8
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr4
-rw-r--r--tests/ui/dyn-compatibility/missing-assoc-type.stderr2
-rw-r--r--tests/ui/dyn-compatibility/no-static.curr.stderr6
-rw-r--r--tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/dyn-compatibility/sized-2.curr.stderr4
-rw-r--r--tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/dyn-compatibility/sized.curr.stderr4
-rw-r--r--tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr2
-rw-r--r--tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr2
-rw-r--r--tests/ui/dyn-compatibility/taint-const-eval.curr.stderr6
-rw-r--r--tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr6
-rw-r--r--tests/ui/error-codes/E0038.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr10
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr2
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.stderr6
-rw-r--r--tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-67510-pass.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-67510.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-71176.stderr6
-rw-r--r--tests/ui/generic-associated-types/issue-76535.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-78671.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-79422.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.rs3
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.stderr2
-rw-r--r--tests/ui/generic-associated-types/missing_lifetime_args.stderr2
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr2
-rw-r--r--tests/ui/generic-associated-types/trait-objects.stderr6
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs6
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr37
-rw-r--r--tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr4
-rw-r--r--tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr6
-rw-r--r--tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.rs14
-rw-r--r--tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.stderr17
-rw-r--r--tests/ui/impl-trait/in-trait/dyn-compatibility.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr2
-rw-r--r--tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs3
-rw-r--r--tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr10
-rw-r--r--tests/ui/infinite/infinite-instantiation.rs3
-rw-r--r--tests/ui/infinite/infinite-instantiation.stderr6
-rw-r--r--tests/ui/issues/issue-18959.stderr10
-rw-r--r--tests/ui/issues/issue-19380.stderr6
-rw-r--r--tests/ui/issues/issue-26056.stderr2
-rw-r--r--tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs3
-rw-r--r--tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr6
-rw-r--r--tests/ui/issues/issue-50781.stderr6
-rw-r--r--tests/ui/issues/issue-67552.rs3
-rw-r--r--tests/ui/issues/issue-67552.stderr6
-rw-r--r--tests/ui/issues/issue-8727.rs3
-rw-r--r--tests/ui/issues/issue-8727.stderr8
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr4
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/mir/null/addrof_null.rs14
-rw-r--r--tests/ui/mir/null/borrowed_mut_null.rs8
-rw-r--r--tests/ui/mir/null/borrowed_null.rs8
-rw-r--r--tests/ui/mir/null/null_lhs.rs10
-rw-r--r--tests/ui/mir/null/null_rhs.rs10
-rw-r--r--tests/ui/mir/null/place_without_read.rs10
-rw-r--r--tests/ui/mir/null/two_pointers.rs12
-rw-r--r--tests/ui/mir/null/zero_sized_access.rs15
-rw-r--r--tests/ui/never_type/fallback-closure-wrap.fallback.stderr13
-rw-r--r--tests/ui/never_type/fallback-closure-wrap.rs2
-rw-r--r--tests/ui/recursion/recursion.rs3
-rw-r--r--tests/ui/recursion/recursion.stderr6
-rw-r--r--tests/ui/resolve/issue-3907-2.stderr2
-rw-r--r--tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr4
-rw-r--r--tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr2
-rw-r--r--tests/ui/statics/unsizing-wfcheck-issue-127299.stderr6
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr4
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr4
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr4
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr2
-rw-r--r--tests/ui/suggestions/issue-116434-2015.stderr4
-rw-r--r--tests/ui/suggestions/issue-98500.stderr2
-rw-r--r--tests/ui/traits/alias/generic-default-in-dyn.stderr4
-rw-r--r--tests/ui/traits/alias/object-fail.stderr2
-rw-r--r--tests/ui/traits/alias/self-in-const-generics.stderr2
-rw-r--r--tests/ui/traits/alias/self-in-generics.stderr2
-rw-r--r--tests/ui/traits/issue-20692.stderr4
-rw-r--r--tests/ui/traits/issue-28576.stderr2
-rw-r--r--tests/ui/traits/issue-38404.stderr6
-rw-r--r--tests/ui/traits/issue-38604.stderr4
-rw-r--r--tests/ui/traits/issue-72410.stderr2
-rw-r--r--tests/ui/traits/item-privacy.stderr2
-rw-r--r--tests/ui/traits/missing-for-type-in-impl.e2015.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr6
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs (renamed from tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs)0
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr (renamed from tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr)0
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.rs (renamed from tests/ui/type-alias-impl-trait/non-lifetime-binder.rs)0
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.stderr (renamed from tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr)0
-rw-r--r--tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr4
-rw-r--r--tests/ui/traits/object/macro-matcher.stderr2
-rw-r--r--tests/ui/traits/object/print_vtable_sizes.rs62
-rw-r--r--tests/ui/traits/object/print_vtable_sizes.stdout11
-rw-r--r--tests/ui/traits/object/safety.stderr4
-rw-r--r--tests/ui/traits/on_unimplemented_long_types.rs3
-rw-r--r--tests/ui/traits/on_unimplemented_long_types.stderr6
-rw-r--r--tests/ui/traits/sized-coniductive.rs14
-rw-r--r--tests/ui/traits/solver-cycles/129541-recursive-struct-and-array-impl.rs23
-rw-r--r--tests/ui/traits/solver-cycles/129541-recursive-struct.rs5
-rw-r--r--tests/ui/traits/test-2.stderr6
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.rs27
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.stderr26
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs26
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.run.stdout1
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs37
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr26
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs34
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.run.stdout1
-rw-r--r--tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs30
-rw-r--r--tests/ui/traits/vtable/multiple-markers.rs33
-rw-r--r--tests/ui/traits/vtable/multiple-markers.stderr32
-rw-r--r--tests/ui/traits/vtable/vtable-diamond.rs31
-rw-r--r--tests/ui/traits/vtable/vtable-diamond.stderr45
-rw-r--r--tests/ui/traits/vtable/vtable-dyn-incompatible.rs7
-rw-r--r--tests/ui/traits/vtable/vtable-dyn-incompatible.stderr16
-rw-r--r--tests/ui/traits/vtable/vtable-multi-level.rs99
-rw-r--r--tests/ui/traits/vtable/vtable-multi-level.stderr197
-rw-r--r--tests/ui/traits/vtable/vtable-multiple.rs22
-rw-r--r--tests/ui/traits/vtable/vtable-multiple.stderr33
-rw-r--r--tests/ui/traits/vtable/vtable-vacant.rs15
-rw-r--r--tests/ui/traits/vtable/vtable-vacant.stderr22
-rw-r--r--tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr2
-rw-r--r--tests/ui/type_length_limit.rs3
-rw-r--r--tests/ui/type_length_limit.stderr4
-rw-r--r--tests/ui/wf/issue-87495.stderr2
-rw-r--r--tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr6
-rw-r--r--tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr6
-rw-r--r--tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr4
-rw-r--r--tests/ui/wf/wf-dyn-incompatible.stderr2
-rw-r--r--tests/ui/wf/wf-fn-where-clause.stderr2
-rw-r--r--tests/ui/wf/wf-trait-default-fn-ret.rs3
-rw-r--r--tests/ui/wf/wf-trait-default-fn-ret.stderr4
-rw-r--r--triagebot.toml1
383 files changed, 3637 insertions, 2213 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 04bb96be369..75c6ab37bd1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4234,6 +4234,7 @@ name = "rustc_monomorphize"
 version = "0.0.0"
 dependencies = [
  "rustc_abi",
+ "rustc_ast",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -4243,6 +4244,7 @@ dependencies = [
  "rustc_middle",
  "rustc_session",
  "rustc_span",
+ "rustc_symbol_mangling",
  "rustc_target",
  "serde",
  "serde_json",
diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
index 7ef8bc17973..ecc522ec39d 100644
--- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs
+++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
@@ -79,6 +79,7 @@ pub struct AutoDiffItem {
     pub target: String,
     pub attrs: AutoDiffAttrs,
 }
+
 #[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct AutoDiffAttrs {
     /// Conceptually either forward or reverse mode AD, as described in various autodiff papers and
@@ -231,7 +232,7 @@ impl AutoDiffAttrs {
         self.ret_activity == DiffActivity::ActiveOnly
     }
 
-    pub fn error() -> Self {
+    pub const fn error() -> Self {
         AutoDiffAttrs {
             mode: DiffMode::Error,
             ret_activity: DiffActivity::None,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 07dcbba019a..0118b72962d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -3777,7 +3777,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let tcx = self.infcx.tcx;
         if let Some(Terminator { kind: TerminatorKind::Call { call_source, fn_span, .. }, .. }) =
             &self.body[loan.reserve_location.block].terminator
-            && let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
+            && let Some((method_did, method_args)) = mir::find_self_call(
                 tcx,
                 self.body,
                 loan.assigned_place.local,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index bd6f77156ca..5fe8eef3460 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -17,7 +17,7 @@ use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
     LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
-    StatementKind, Terminator, TerminatorKind,
+    StatementKind, Terminator, TerminatorKind, find_self_call,
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -1016,12 +1016,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
         }) = &self.body[location.block].terminator
         {
-            let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
-                self.infcx.tcx,
-                self.body,
-                target_temp,
-                location.block,
-            ) else {
+            let Some((method_did, method_args)) =
+                find_self_call(self.infcx.tcx, self.body, target_temp, location.block)
+            else {
                 return normal_ret;
             };
 
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 34066eb83fc..c7c9c6236d1 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -417,6 +417,16 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                             Some(source_info.span),
                         );
                     }
+                    AssertKind::NullPointerDereference => {
+                        let location = fx.get_caller_location(source_info).load_scalar(fx);
+
+                        codegen_panic_inner(
+                            fx,
+                            rustc_hir::LangItem::PanicNullPointerDereference,
+                            &[location],
+                            Some(source_info.span),
+                        )
+                    }
                     _ => {
                         let location = fx.get_caller_location(source_info).load_scalar(fx);
 
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 3e7b81a96b6..425b2adf32a 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -6,7 +6,7 @@ use cranelift_module::*;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{AllocId, GlobalAlloc, Scalar, read_target_uint};
-use rustc_middle::ty::{Binder, ExistentialTraitRef, ScalarInt};
+use rustc_middle::ty::{ExistentialTraitRef, ScalarInt};
 
 use crate::prelude::*;
 
@@ -167,7 +167,9 @@ pub(crate) fn codegen_const_value<'tcx>(
                             &mut fx.constants_cx,
                             fx.module,
                             ty,
-                            dyn_ty.principal(),
+                            dyn_ty.principal().map(|principal| {
+                                fx.tcx.instantiate_bound_regions_with_erased(principal)
+                            }),
                         );
                         let local_data_id =
                             fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
@@ -243,7 +245,7 @@ pub(crate) fn data_id_for_vtable<'tcx>(
     cx: &mut ConstantCx,
     module: &mut dyn Module,
     ty: Ty<'tcx>,
-    trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
+    trait_ref: Option<ExistentialTraitRef<'tcx>>,
 ) -> DataId {
     let alloc_id = tcx.vtable_allocation((ty, trait_ref));
     data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
@@ -460,9 +462,15 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                 GlobalAlloc::Memory(target_alloc) => {
                     data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability)
                 }
-                GlobalAlloc::VTable(ty, dyn_ty) => {
-                    data_id_for_vtable(tcx, cx, module, ty, dyn_ty.principal())
-                }
+                GlobalAlloc::VTable(ty, dyn_ty) => data_id_for_vtable(
+                    tcx,
+                    cx,
+                    module,
+                    ty,
+                    dyn_ty
+                        .principal()
+                        .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
+                ),
                 GlobalAlloc::Static(def_id) => {
                     if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
                     {
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index 2843e5bbdfb..f8bbb214920 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -61,7 +61,12 @@ pub(crate) fn unsized_info<'tcx>(
                 old_info
             }
         }
-        (_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
+        (_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(
+            fx,
+            source,
+            data.principal()
+                .map(|principal| fx.tcx.instantiate_bound_regions_with_erased(principal)),
+        ),
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index 82b6178be9d..a460023b59c 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -90,7 +90,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
 pub(crate) fn get_vtable<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     ty: Ty<'tcx>,
-    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
 ) -> Value {
     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);
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index bd5d6ba387c..20a3482aaa2 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -234,7 +234,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                     GlobalAlloc::VTable(ty, dyn_ty) => {
                         let alloc = self
                             .tcx
-                            .global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
+                            .global_alloc(self.tcx.vtable_allocation((
+                                ty,
+                                dyn_ty.principal().map(|principal| {
+                                    self.tcx.instantiate_bound_regions_with_erased(principal)
+                                }),
+                            )))
                             .unwrap_memory();
                         let init = const_alloc_to_gcc(self, alloc);
                         self.static_addr_of(init, alloc.inner().align, None)
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 30732c74eb3..570ef938dc4 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
     LayoutOfHelpers,
 };
-use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::source_map::respan;
 use rustc_span::{DUMMY_SP, Span};
@@ -90,7 +90,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
     pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
     /// Cache generated vtables
     pub vtables:
-        RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
+        RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
 
     // TODO(antoyo): improve the SSA API to not require those.
     /// Mapping from function pointer type to indexes of on stack parameters.
@@ -401,7 +401,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
 impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn vtables(
         &self,
-    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
+    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
         &self.vtables
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 4b84b1dbfd3..86d3de225f7 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::{self, Body, SourceScope};
-use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
+use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
 use rustc_session::config::DebugInfo;
 use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
 use rustc_target::abi::Size;
@@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn create_vtable_debuginfo(
         &self,
         _ty: Ty<'tcx>,
-        _trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
+        _trait_ref: Option<ExistentialTraitRef<'tcx>>,
         _vtable: Self::Value,
     ) {
         // TODO(antoyo)
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index bfe73c38435..58a26801b67 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -3,8 +3,6 @@
 // Run-time:
 //   status: 0
 
-#![feature(const_black_box)]
-
 /*
  * Code
  */
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index 6b17b5f6989..9e8e4e1c567 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -62,8 +62,8 @@ fn generate_enzyme_call<'ll>(
     // add outer_fn name to ad_name to make it unique, in case users apply autodiff to multiple
     // functions. Unwrap will only panic, if LLVM gave us an invalid string.
     let name = llvm::get_value_name(outer_fn);
-    let outer_fn_name = std::ffi::CStr::from_bytes_with_nul(name).unwrap().to_str().unwrap();
-    ad_name.push_str(outer_fn_name.to_string().as_str());
+    let outer_fn_name = std::str::from_utf8(name).unwrap();
+    ad_name.push_str(outer_fn_name);
 
     // Let us assume the user wrote the following function square:
     //
@@ -255,14 +255,14 @@ fn generate_enzyme_call<'ll>(
             // have no debug info to copy, which would then be ok.
             trace!("no dbg info");
         }
+
         // Now that we copied the metadata, get rid of dummy code.
-        llvm::LLVMRustEraseInstBefore(entry, last_inst);
-        llvm::LLVMRustEraseInstFromParent(last_inst);
+        llvm::LLVMRustEraseInstUntilInclusive(entry, last_inst);
 
-        if cx.val_ty(outer_fn) != cx.type_void() {
-            builder.ret(call);
-        } else {
+        if cx.val_ty(call) == cx.type_void() {
             builder.ret_void();
+        } else {
+            builder.ret(call);
         }
 
         // Let's crash in case that we messed something up above and generated invalid IR.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index f8b30cb507a..8c94a46ebf3 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -314,7 +314,12 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                     GlobalAlloc::VTable(ty, dyn_ty) => {
                         let alloc = self
                             .tcx
-                            .global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
+                            .global_alloc(self.tcx.vtable_allocation((
+                                ty,
+                                dyn_ty.principal().map(|principal| {
+                                    self.tcx.instantiate_bound_regions_with_erased(principal)
+                                }),
+                            )))
                             .unwrap_memory();
                         let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
                         let value = self.static_addr_of_impl(init, alloc.inner().align, None);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 79381f35a3c..ba4fd75fb94 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -77,8 +77,7 @@ pub(crate) struct CodegenCx<'ll, 'tcx> {
     /// Cache instances of monomorphic and polymorphic items
     pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
     /// Cache generated vtables
-    pub vtables:
-        RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
+    pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>>,
     /// Cache of constant strings,
     pub const_str_cache: RefCell<FxHashMap<String, &'ll Value>>,
 
@@ -663,15 +662,14 @@ impl<'ll> SimpleCx<'ll> {
 impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn vtables(
         &self,
-    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
-    {
+    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>> {
         &self.vtables
     }
 
     fn apply_vcall_visibility_metadata(
         &self,
         ty: Ty<'tcx>,
-        poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+        poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
         vtable: &'ll Value,
     ) {
         apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index fd22421c7fc..9a2473d6cf2 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -298,7 +298,7 @@ struct UsageSets<'tcx> {
 /// 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 MonoItemPartitions { all_mono_items, codegen_units } =
+    let MonoItemPartitions { all_mono_items, codegen_units, .. } =
         tcx.collect_and_partition_mono_items(());
 
     // Obtain a MIR body for each function participating in codegen, via an
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 6eae16d8be6..3a0c7f007bd 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -13,7 +13,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{
-    self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
+    self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
 };
 use rustc_session::config::{self, DebugInfo, Lto};
 use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene};
@@ -1399,7 +1399,7 @@ pub(crate) fn build_global_var_di_node<'ll>(
 fn build_vtable_type_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     ty: Ty<'tcx>,
-    poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
 ) -> &'ll DIType {
     let tcx = cx.tcx;
 
@@ -1510,7 +1510,7 @@ fn find_vtable_behind_cast<'ll>(vtable: &'ll Value) -> &'ll Value {
 pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     ty: Ty<'tcx>,
-    trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
+    trait_ref: Option<ExistentialTraitRef<'tcx>>,
     vtable: &'ll Value,
 ) {
     // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
@@ -1531,7 +1531,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
     let vtable = find_vtable_behind_cast(vtable);
     let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
     let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
-    let trait_def_id = trait_ref_self.def_id();
+    let trait_def_id = trait_ref_self.def_id;
     let trait_vis = cx.tcx.visibility(trait_def_id);
 
     let cgus = cx.sess().codegen_units().as_usize();
@@ -1590,7 +1590,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
 pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     ty: Ty<'tcx>,
-    poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
     vtable: &'ll Value,
 ) {
     if cx.dbg_cx.is_none() {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index a37e719d43f..af1d503ad6a 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt};
 
 use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
 use crate::common::{AsCCharPtr, CodegenCx};
@@ -44,7 +44,7 @@ pub(super) enum UniqueTypeId<'tcx> {
     /// The ID for the additional wrapper struct type describing an enum variant in CPP-like mode.
     VariantStructTypeCppLikeWrapper(Ty<'tcx>, VariantIdx, private::HiddenZst),
     /// The ID of the artificial type we create for VTables.
-    VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, private::HiddenZst),
+    VTableTy(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>, private::HiddenZst),
 }
 
 impl<'tcx> UniqueTypeId<'tcx> {
@@ -88,7 +88,7 @@ impl<'tcx> UniqueTypeId<'tcx> {
     pub(crate) fn for_vtable_ty(
         tcx: TyCtxt<'tcx>,
         self_type: Ty<'tcx>,
-        implemented_trait: Option<PolyExistentialTraitRef<'tcx>>,
+        implemented_trait: Option<ExistentialTraitRef<'tcx>>,
     ) -> Self {
         assert_eq!(
             self_type,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 5089560784a..b1ce52667bd 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -588,7 +588,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn create_vtable_debuginfo(
         &self,
         ty: Ty<'tcx>,
-        trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+        trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
         vtable: Self::Value,
     ) {
         metadata::create_vtable_di_node(self, ty, trait_ref, vtable)
diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
index 729d6f62e24..ae813fe5ebf 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
@@ -7,11 +7,13 @@ use crate::llvm::Bool;
 extern "C" {
     // Enzyme
     pub fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
-    pub fn LLVMRustEraseInstBefore(BB: &BasicBlock, I: &Value);
+    pub fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
     pub fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
     pub fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
     pub fn LLVMRustEraseInstFromParent(V: &Value);
     pub fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
+    pub fn LLVMDumpModule(M: &Module);
+    pub fn LLVMDumpValue(V: &Value);
     pub fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
 
     pub fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 186b8171dd8..22e262546c3 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -16,6 +16,8 @@ codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$erro
 
 codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
 
+codegen_ssa_autodiff_without_lto = using the autodiff feature requires using fat-lto
+
 codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty
 
 codegen_ssa_cgu_not_recorded =
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index b40bb4ed5d2..914f2c21fa7 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -7,6 +7,7 @@ use std::sync::mpsc::{Receiver, Sender, channel};
 use std::{fs, io, mem, str, thread};
 
 use rustc_ast::attr;
+use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::jobserver::{self, Acquired};
 use rustc_data_structures::memmap::Mmap;
@@ -40,7 +41,7 @@ use tracing::debug;
 use super::link::{self, ensure_removed};
 use super::lto::{self, SerializedModule};
 use super::symbol_export::symbol_name_for_instance_in_crate;
-use crate::errors::ErrorCreatingRemarkDir;
+use crate::errors::{AutodiffWithoutLto, ErrorCreatingRemarkDir};
 use crate::traits::*;
 use crate::{
     CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
@@ -118,6 +119,7 @@ pub struct ModuleConfig {
     pub merge_functions: bool,
     pub emit_lifetime_markers: bool,
     pub llvm_plugins: Vec<String>,
+    pub autodiff: Vec<config::AutoDiff>,
 }
 
 impl ModuleConfig {
@@ -266,6 +268,7 @@ impl ModuleConfig {
 
             emit_lifetime_markers: sess.emit_lifetime_markers(),
             llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
+            autodiff: if_regular!(sess.opts.unstable_opts.autodiff.clone(), vec![]),
         }
     }
 
@@ -389,6 +392,7 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
 
 fn generate_lto_work<B: ExtraBackendMethods>(
     cgcx: &CodegenContext<B>,
+    autodiff: Vec<AutoDiffItem>,
     needs_fat_lto: Vec<FatLtoInput<B>>,
     needs_thin_lto: Vec<(String, B::ThinBuffer)>,
     import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
@@ -397,11 +401,19 @@ fn generate_lto_work<B: ExtraBackendMethods>(
 
     if !needs_fat_lto.is_empty() {
         assert!(needs_thin_lto.is_empty());
-        let module =
+        let mut module =
             B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules).unwrap_or_else(|e| e.raise());
+        if cgcx.lto == Lto::Fat {
+            let config = cgcx.config(ModuleKind::Regular);
+            module = unsafe { module.autodiff(cgcx, autodiff, config).unwrap() };
+        }
         // We are adding a single work item, so the cost doesn't matter.
         vec![(WorkItem::LTO(module), 0)]
     } else {
+        if !autodiff.is_empty() {
+            let dcx = cgcx.create_dcx();
+            dcx.handle().emit_fatal(AutodiffWithoutLto {});
+        }
         assert!(needs_fat_lto.is_empty());
         let (lto_modules, copy_jobs) = B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules)
             .unwrap_or_else(|e| e.raise());
@@ -1021,6 +1033,9 @@ pub(crate) enum Message<B: WriteBackendMethods> {
     /// Sent from a backend worker thread.
     WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>>, worker_id: usize },
 
+    /// A vector containing all the AutoDiff tasks that we have to pass to Enzyme.
+    AddAutoDiffItems(Vec<AutoDiffItem>),
+
     /// The frontend has finished generating something (backend IR or a
     /// post-LTO artifact) for a codegen unit, and it should be passed to the
     /// backend. Sent from the main thread.
@@ -1348,6 +1363,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
 
         // This is where we collect codegen units that have gone all the way
         // through codegen and LLVM.
+        let mut autodiff_items = Vec::new();
         let mut compiled_modules = vec![];
         let mut compiled_allocator_module = None;
         let mut needs_link = Vec::new();
@@ -1459,9 +1475,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
                     let needs_thin_lto = mem::take(&mut needs_thin_lto);
                     let import_only_modules = mem::take(&mut lto_import_only_modules);
 
-                    for (work, cost) in
-                        generate_lto_work(&cgcx, needs_fat_lto, needs_thin_lto, import_only_modules)
-                    {
+                    for (work, cost) in generate_lto_work(
+                        &cgcx,
+                        autodiff_items.clone(),
+                        needs_fat_lto,
+                        needs_thin_lto,
+                        import_only_modules,
+                    ) {
                         let insertion_index = work_items
                             .binary_search_by_key(&cost, |&(_, cost)| cost)
                             .unwrap_or_else(|e| e);
@@ -1596,6 +1616,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
                     main_thread_state = MainThreadState::Idle;
                 }
 
+                Message::AddAutoDiffItems(mut items) => {
+                    autodiff_items.append(&mut items);
+                }
+
                 Message::CodegenComplete => {
                     if codegen_state != Aborted {
                         codegen_state = Completed;
@@ -2070,6 +2094,10 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
         drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>)));
     }
 
+    pub(crate) fn submit_autodiff_items(&self, items: Vec<AutoDiffItem>) {
+        drop(self.coordinator.sender.send(Box::new(Message::<B>::AddAutoDiffItems(items))));
+    }
+
     pub(crate) fn check_for_errors(&self, sess: &Session) {
         self.shared_emitter_main.check(sess, false);
     }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 83a9e6e2309..6e0333cf3ce 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -18,14 +18,13 @@ use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, Debugger
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::middle::{exported_symbols, lang_items};
 use rustc_middle::mir::BinOp;
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
+use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
 use rustc_span::{DUMMY_SP, Symbol, sym};
-use rustc_trait_selection::infer::at::ToTrace;
 use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
 use tracing::{debug, info};
@@ -129,14 +128,9 @@ pub fn validate_trivial_unsize<'tcx>(
                     BoundRegionConversionTime::HigherRankedType,
                     hr_source_principal,
                 );
-                let Ok(()) = ocx.eq_trace(
+                let Ok(()) = ocx.eq(
                     &ObligationCause::dummy(),
                     param_env,
-                    ToTrace::to_trace(
-                        &ObligationCause::dummy(),
-                        hr_target_principal,
-                        hr_source_principal,
-                    ),
                     target_principal,
                     source_principal,
                 ) else {
@@ -211,7 +205,12 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 old_info
             }
         }
-        (_, ty::Dynamic(data, _, _)) => meth::get_vtable(cx, source, data.principal()),
+        (_, ty::Dynamic(data, _, _)) => meth::get_vtable(
+            cx,
+            source,
+            data.principal()
+                .map(|principal| bx.tcx().instantiate_bound_regions_with_erased(principal)),
+        ),
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
     }
 }
@@ -624,7 +623,9 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
     // Run the monomorphization collector and partition the collected items into
     // codegen units.
-    let codegen_units = tcx.collect_and_partition_mono_items(()).codegen_units;
+    let MonoItemPartitions { codegen_units, autodiff_items, .. } =
+        tcx.collect_and_partition_mono_items(());
+    let autodiff_fncs = autodiff_items.to_vec();
 
     // Force all codegen_unit queries so they are already either red or green
     // when compile_codegen_unit accesses them. We are not able to re-execute
@@ -695,6 +696,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         );
     }
 
+    if !autodiff_fncs.is_empty() {
+        ongoing_codegen.submit_autodiff_items(autodiff_fncs);
+    }
+
     // For better throughput during parallel processing by LLVM, we used to sort
     // CGUs largest to smallest. This would lead to better thread utilization
     // by, for example, preventing a large CGU from being processed last and
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index a0bc2d4ea48..4166387dad0 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,5 +1,10 @@
+use std::str::FromStr;
+
 use rustc_ast::attr::list_contains_name;
-use rustc_ast::{MetaItemInner, attr};
+use rustc_ast::expand::autodiff_attrs::{
+    AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
+};
+use rustc_ast::{MetaItem, MetaItemInner, attr};
 use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::codes::*;
@@ -13,6 +18,7 @@ use rustc_middle::middle::codegen_fn_attrs::{
 };
 use rustc_middle::mir::mono::Linkage;
 use rustc_middle::query::Providers;
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self as ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_session::{Session, lint};
@@ -65,6 +71,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
+    // If our rustc version supports autodiff/enzyme, then we call our handler
+    // to check for any `#[rustc_autodiff(...)]` attributes.
+    if cfg!(llvm_enzyme) {
+        let ad = autodiff_attrs(tcx, did.into());
+        codegen_fn_attrs.autodiff_item = ad;
+    }
+
     // When `no_builtins` is applied at the crate level, we should add the
     // `no-builtins` attribute to each function to ensure it takes effect in LTO.
     let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
@@ -856,6 +869,109 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
     }
 }
 
+/// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]
+/// macros. There are two forms. The pure one without args to mark primal functions (the functions
+/// being differentiated). The other form is #[rustc_autodiff(Mode, ActivityList)] on top of the
+/// placeholder functions. We wrote the rustc_autodiff attributes ourself, so this should never
+/// panic, unless we introduced a bug when parsing the autodiff macro.
+fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
+    let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
+
+    let attrs =
+        attrs.filter(|attr| attr.name_or_empty() == sym::rustc_autodiff).collect::<Vec<_>>();
+
+    // check for exactly one autodiff attribute on placeholder functions.
+    // There should only be one, since we generate a new placeholder per ad macro.
+    // FIXME(ZuseZ4): re-enable this check. Currently we add multiple, which doesn't cause harm but
+    // looks strange e.g. under cargo-expand.
+    let attr = match &attrs[..] {
+        [] => return None,
+        [attr] => attr,
+        // These two attributes are the same and unfortunately duplicated due to a previous bug.
+        [attr, _attr2] => attr,
+        _ => {
+            //FIXME(ZuseZ4): Once we fixed our parser, we should also prohibit the two-attribute
+            //branch above.
+            span_bug!(attrs[1].span, "cg_ssa: rustc_autodiff should only exist once per source");
+        }
+    };
+
+    let list = attr.meta_item_list().unwrap_or_default();
+
+    // empty autodiff attribute macros (i.e. `#[autodiff]`) are used to mark source functions
+    if list.is_empty() {
+        return Some(AutoDiffAttrs::source());
+    }
+
+    let [mode, input_activities @ .., ret_activity] = &list[..] else {
+        span_bug!(attr.span, "rustc_autodiff attribute must contain mode and activities");
+    };
+    let mode = if let MetaItemInner::MetaItem(MetaItem { path: ref p1, .. }) = mode {
+        p1.segments.first().unwrap().ident
+    } else {
+        span_bug!(attr.span, "rustc_autodiff attribute must contain mode");
+    };
+
+    // parse mode
+    let mode = match mode.as_str() {
+        "Forward" => DiffMode::Forward,
+        "Reverse" => DiffMode::Reverse,
+        "ForwardFirst" => DiffMode::ForwardFirst,
+        "ReverseFirst" => DiffMode::ReverseFirst,
+        _ => {
+            span_bug!(mode.span, "rustc_autodiff attribute contains invalid mode");
+        }
+    };
+
+    // First read the ret symbol from the attribute
+    let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: ref p1, .. }) = ret_activity {
+        p1.segments.first().unwrap().ident
+    } else {
+        span_bug!(attr.span, "rustc_autodiff attribute must contain the return activity");
+    };
+
+    // Then parse it into an actual DiffActivity
+    let Ok(ret_activity) = DiffActivity::from_str(ret_symbol.as_str()) else {
+        span_bug!(ret_symbol.span, "invalid return activity");
+    };
+
+    // Now parse all the intermediate (input) activities
+    let mut arg_activities: Vec<DiffActivity> = vec![];
+    for arg in input_activities {
+        let arg_symbol = if let MetaItemInner::MetaItem(MetaItem { path: ref p2, .. }) = arg {
+            match p2.segments.first() {
+                Some(x) => x.ident,
+                None => {
+                    span_bug!(
+                        arg.span(),
+                        "rustc_autodiff attribute must contain the input activity"
+                    );
+                }
+            }
+        } else {
+            span_bug!(arg.span(), "rustc_autodiff attribute must contain the input activity");
+        };
+
+        match DiffActivity::from_str(arg_symbol.as_str()) {
+            Ok(arg_activity) => arg_activities.push(arg_activity),
+            Err(_) => {
+                span_bug!(arg_symbol.span, "invalid input activity");
+            }
+        }
+    }
+
+    for &input in &arg_activities {
+        if !valid_input_activity(mode, input) {
+            span_bug!(attr.span, "Invalid input activity {} for {} mode", input, mode);
+        }
+    }
+    if !valid_ret_activity(mode, ret_activity) {
+        span_bug!(attr.span, "Invalid return activity {} for {} mode", ret_activity, mode);
+    }
+
+    Some(AutoDiffAttrs { mode, ret_activity, input_activity: arg_activities })
+}
+
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
 }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index d766ae37e5b..05175371591 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -507,7 +507,7 @@ pub enum VTableNameKind {
 pub fn compute_debuginfo_vtable_name<'tcx>(
     tcx: TyCtxt<'tcx>,
     t: Ty<'tcx>,
-    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
     kind: VTableNameKind,
 ) -> String {
     let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
@@ -530,8 +530,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
     }
 
     if let Some(trait_ref) = trait_ref {
-        let trait_ref = tcx
-            .normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
+        let trait_ref =
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
         push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name);
         visited.clear();
         push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index f3afb37a9ef..3ddbe4aeeec 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -40,6 +40,10 @@ pub(crate) struct CguNotRecorded<'a> {
 }
 
 #[derive(Diagnostic)]
+#[diag(codegen_ssa_autodiff_without_lto)]
+pub struct AutodiffWithoutLto;
+
+#[derive(Diagnostic)]
 #[diag(codegen_ssa_unknown_reuse_kind)]
 pub(crate) struct UnknownReuseKind {
     #[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 64cd4c38937..399c592432a 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -1,5 +1,5 @@
 use rustc_middle::bug;
-use rustc_middle::ty::{self, GenericArgKind, Ty};
+use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt};
 use rustc_session::config::Lto;
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::callconv::FnAbi;
@@ -72,12 +72,19 @@ impl<'a, 'tcx> VirtualIndex {
 
 /// This takes a valid `self` receiver type and extracts the principal trait
 /// ref of the type. Return `None` if there is no principal trait.
-fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> {
+fn dyn_trait_in_self<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+) -> Option<ty::ExistentialTraitRef<'tcx>> {
     for arg in ty.peel_refs().walk() {
         if let GenericArgKind::Type(ty) = arg.unpack()
             && let ty::Dynamic(data, _, _) = ty.kind()
         {
-            return data.principal();
+            // FIXME(arbitrary_self_types): This is likely broken for receivers which
+            // have a "non-self" trait objects as a generic argument.
+            return data
+                .principal()
+                .map(|principal| tcx.instantiate_bound_regions_with_erased(principal));
         }
     }
 
@@ -96,7 +103,7 @@ fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> {
 pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
     cx: &Cx,
     ty: Ty<'tcx>,
-    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
 ) -> Cx::Value {
     let tcx = cx.tcx();
 
@@ -131,7 +138,7 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
         && bx.cx().sess().lto() == Lto::Fat
     {
-        if let Some(trait_ref) = dyn_trait_in_self(ty) {
+        if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) {
             let typeid = bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref)).unwrap();
             let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
             return func;
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index b0a1dedd646..4be363ca9a2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -713,6 +713,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // and `#[track_caller]` adds an implicit third argument.
                 (LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
             }
+            AssertKind::NullPointerDereference => {
+                // It's `fn panic_null_pointer_dereference()`,
+                // `#[track_caller]` adds an implicit argument.
+                (LangItem::PanicNullPointerDereference, vec![location])
+            }
             _ => {
                 // It's `pub fn panic_...()` and `#[track_caller]` adds an implicit argument.
                 (msg.panic_function(), vec![location])
diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
index fe135e911fb..30d77c206a5 100644
--- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
@@ -2,7 +2,7 @@ use std::ops::Range;
 
 use rustc_abi::Size;
 use rustc_middle::mir;
-use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
+use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
 use rustc_span::{SourceFile, Span, Symbol};
 use rustc_target::callconv::FnAbi;
 
@@ -13,7 +13,7 @@ pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes {
     fn create_vtable_debuginfo(
         &self,
         ty: Ty<'tcx>,
-        trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
+        trait_ref: Option<ExistentialTraitRef<'tcx>>,
         vtable: Self::Value,
     );
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs
index 5b33fd7ab10..4004947b464 100644
--- a/compiler/rustc_codegen_ssa/src/traits/misc.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs
@@ -10,11 +10,11 @@ use super::BackendTypes;
 pub trait MiscCodegenMethods<'tcx>: BackendTypes {
     fn vtables(
         &self,
-    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
+    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), Self::Value>>;
     fn apply_vcall_visibility_metadata(
         &self,
         _ty: Ty<'tcx>,
-        _poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+        _poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
         _vtable: Self::Value,
     ) {
     }
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 16ead1b9785..4834fd3d34c 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -634,7 +634,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place) => {
                 // These are only inserted for slice length, so the place must already be indirect.
                 // This implies we do not have to worry about whether the borrow escapes.
-                assert!(place.is_indirect(), "fake borrows are always indirect");
+                if !place.is_indirect() {
+                    self.tcx.dcx().span_delayed_bug(
+                        self.body.source_info(location).span,
+                        "fake borrows are always indirect",
+                    );
+                }
             }
 
             Rvalue::Cast(
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6a339d69542..82e0a6e6666 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -508,6 +508,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
                     found: eval_to_int(found)?,
                 }
             }
+            NullPointerDereference => NullPointerDereference,
         };
         Err(ConstEvalErrKind::AssertFailure(err)).into()
     }
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index e6a34193c9d..e2e6e16d8a7 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -5,6 +5,7 @@ use std::borrow::Cow;
 
 use either::{Left, Right};
 use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx};
+use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef};
 use rustc_middle::{bug, mir, span_bug};
@@ -693,25 +694,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 trace!("Virtual call dispatches to {fn_inst:#?}");
                 // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that
                 // produces the same result.
-                if cfg!(debug_assertions) {
-                    let tcx = *self.tcx;
-
-                    let trait_def_id = tcx.trait_of_item(def_id).unwrap();
-                    let virtual_trait_ref =
-                        ty::TraitRef::from_method(tcx, trait_def_id, instance.args);
-                    let existential_trait_ref =
-                        ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
-                    let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
-
-                    let concrete_method = Instance::expect_resolve_for_vtable(
-                        tcx,
-                        self.typing_env,
-                        def_id,
-                        instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
-                        self.cur_span(),
-                    );
-                    assert_eq!(fn_inst, concrete_method);
-                }
+                self.assert_virtual_instance_matches_concrete(dyn_ty, def_id, instance, fn_inst);
 
                 // Adjust receiver argument. Layout can be any (thin) ptr.
                 let receiver_ty = Ty::new_mut_ptr(self.tcx.tcx, dyn_ty);
@@ -744,6 +727,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
+    fn assert_virtual_instance_matches_concrete(
+        &self,
+        dyn_ty: Ty<'tcx>,
+        def_id: DefId,
+        virtual_instance: ty::Instance<'tcx>,
+        concrete_instance: ty::Instance<'tcx>,
+    ) {
+        let tcx = *self.tcx;
+
+        let trait_def_id = tcx.trait_of_item(def_id).unwrap();
+        let virtual_trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, virtual_instance.args);
+        let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
+        let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
+
+        let concrete_method = Instance::expect_resolve_for_vtable(
+            tcx,
+            self.typing_env,
+            def_id,
+            virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
+            self.cur_span(),
+        );
+        assert_eq!(concrete_instance, concrete_method);
+    }
+
     /// Initiate a tail call to this function -- popping the current stack frame, pushing the new
     /// stack frame and initializing the arguments.
     pub(super) fn init_fn_tail_call(
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index ef3e96784ce..e110c155da0 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -414,36 +414,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
                 // Sanity-check that `supertrait_vtable_slot` in this type's vtable indeed produces
                 // our destination trait.
-                if cfg!(debug_assertions) {
-                    let vptr_entry_idx =
-                        self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty));
-                    let vtable_entries = self.vtable_entries(data_a.principal(), ty);
-                    if let Some(entry_idx) = vptr_entry_idx {
-                        let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
-                            vtable_entries.get(entry_idx)
-                        else {
-                            span_bug!(
-                                self.cur_span(),
-                                "invalid vtable entry index in {} -> {} upcast",
-                                src_pointee_ty,
-                                dest_pointee_ty
-                            );
-                        };
-                        let erased_trait_ref = upcast_trait_ref
-                            .map_bound(|r| ty::ExistentialTraitRef::erase_self_ty(*self.tcx, r));
-                        assert!(
-                            data_b
-                                .principal()
-                                .is_some_and(|b| self.eq_in_param_env(erased_trait_ref, b))
+                let vptr_entry_idx =
+                    self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty));
+                let vtable_entries = self.vtable_entries(data_a.principal(), ty);
+                if let Some(entry_idx) = vptr_entry_idx {
+                    let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
+                        vtable_entries.get(entry_idx)
+                    else {
+                        span_bug!(
+                            self.cur_span(),
+                            "invalid vtable entry index in {} -> {} upcast",
+                            src_pointee_ty,
+                            dest_pointee_ty
                         );
-                    } else {
-                        // In this case codegen would keep using the old vtable. We don't want to do
-                        // that as it has the wrong trait. The reason codegen can do this is that
-                        // one vtable is a prefix of the other, so we double-check that.
-                        let vtable_entries_b = self.vtable_entries(data_b.principal(), ty);
-                        assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b);
                     };
-                }
+                    let erased_trait_ref =
+                        ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref);
+                    assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env(
+                        erased_trait_ref,
+                        self.tcx.instantiate_bound_regions_with_erased(b)
+                    )));
+                } else {
+                    // In this case codegen would keep using the old vtable. We don't want to do
+                    // that as it has the wrong trait. The reason codegen can do this is that
+                    // one vtable is a prefix of the other, so we double-check that.
+                    let vtable_entries_b = self.vtable_entries(data_b.principal(), ty);
+                    assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b);
+                };
 
                 // Get the destination trait vtable and return that.
                 let new_vptr = self.get_vtable_ptr(ty, data_b)?;
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index af8d618b6b5..4cfaacebfcd 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -54,7 +54,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> &'tcx [VtblEntry<'tcx>] {
         if let Some(trait_) = trait_ {
             let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty);
-            let trait_ref = self.tcx.erase_regions(trait_ref);
+            let trait_ref =
+                self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
             self.tcx.vtable_entries(trait_ref)
         } else {
             TyCtxt::COMMON_VTABLE_ENTRIES
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 65d586124b3..6ef73debadd 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -76,6 +76,7 @@ pub mod sync;
 pub mod tagged_ptr;
 pub mod temp_dir;
 pub mod thinvec;
+pub mod thousands;
 pub mod transitive_relation;
 pub mod unhash;
 pub mod unord;
diff --git a/compiler/rustc_data_structures/src/thousands/mod.rs b/compiler/rustc_data_structures/src/thousands/mod.rs
new file mode 100644
index 00000000000..e7ab7ec2932
--- /dev/null
+++ b/compiler/rustc_data_structures/src/thousands/mod.rs
@@ -0,0 +1,16 @@
+//! This is an extremely bare-bones alternative to the `thousands` crate on
+//! crates.io, for printing large numbers in a readable fashion.
+
+#[cfg(test)]
+mod tests;
+
+// Converts the number to a string, with underscores as the thousands separator.
+pub fn format_with_underscores(n: usize) -> String {
+    let mut s = n.to_string();
+    let mut i = s.len();
+    while i > 3 {
+        i -= 3;
+        s.insert(i, '_');
+    }
+    s
+}
diff --git a/compiler/rustc_data_structures/src/thousands/tests.rs b/compiler/rustc_data_structures/src/thousands/tests.rs
new file mode 100644
index 00000000000..906605d9a93
--- /dev/null
+++ b/compiler/rustc_data_structures/src/thousands/tests.rs
@@ -0,0 +1,14 @@
+use super::*;
+
+#[test]
+fn test_format_with_underscores() {
+    assert_eq!("0", format_with_underscores(0));
+    assert_eq!("1", format_with_underscores(1));
+    assert_eq!("99", format_with_underscores(99));
+    assert_eq!("345", format_with_underscores(345));
+    assert_eq!("1_000", format_with_underscores(1_000));
+    assert_eq!("12_001", format_with_underscores(12_001));
+    assert_eq!("999_999", format_with_underscores(999_999));
+    assert_eq!("1_000_000", format_with_underscores(1_000_000));
+    assert_eq!("12_345_678", format_with_underscores(12_345_678));
+}
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 93f3d2ab911..699742aa0ea 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -7,6 +7,7 @@ use rustc_ast_pretty::pprust as pprust_ast;
 use rustc_middle::bug;
 use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_mir_build::thir::print::{thir_flat, thir_tree};
 use rustc_session::Session;
 use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode};
 use rustc_smir::rustc_internal::pretty::write_smir_pretty;
@@ -313,7 +314,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
             tcx.dcx().abort_if_errors();
             debug!("pretty printing THIR tree");
             for did in tcx.hir().body_owners() {
-                let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did));
+                let _ = writeln!(out, "{:?}:\n{}\n", did, thir_tree(tcx, did));
             }
             out
         }
@@ -324,7 +325,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
             tcx.dcx().abort_if_errors();
             debug!("pretty printing THIR flat");
             for did in tcx.hir().body_owners() {
-                let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did));
+                let _ = writeln!(out, "{:?}:\n{}\n", did, thir_flat(tcx, did));
             }
             out
         }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 17433eed9e7..684fc5e37e0 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1136,7 +1136,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     rustc_attr!(
         TEST, rustc_dump_vtable, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes
+        WarnFollowing, EncodeCrossCrate::No
     ),
     rustc_attr!(
         TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/),
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 02bc069fc5f..d9759580e8f 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -316,6 +316,7 @@ language_item_table! {
     PanicAsyncFnResumedPanic, sym::panic_const_async_fn_resumed_panic, panic_const_async_fn_resumed_panic, Target::Fn, GenericRequirement::None;
     PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None;
     PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None;
+    PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
     /// libstd panic entry point. Necessary for const eval to be able to catch it
     BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn,             GenericRequirement::None;
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 7332888c5f9..3bff5fe02c0 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -424,12 +424,12 @@ fn compare_method_predicate_entailment<'tcx>(
     Ok(())
 }
 
-struct RemapLateParam<'a, 'tcx> {
+struct RemapLateParam<'tcx> {
     tcx: TyCtxt<'tcx>,
-    mapping: &'a FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,
+    mapping: FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'_, 'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> {
     fn cx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -653,6 +653,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                 }))),
                 terr,
                 false,
+                None,
             );
             return Err(diag.emit());
         }
@@ -1070,6 +1071,7 @@ fn report_trait_method_mismatch<'tcx>(
         }))),
         terr,
         false,
+        None,
     );
 
     diag.emit()
@@ -1862,6 +1864,7 @@ fn compare_const_predicate_entailment<'tcx>(
             }))),
             terr,
             false,
+            None,
         );
         return Err(diag.emit());
     };
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 494e9560c81..0e9e9b48ab3 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -299,8 +299,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
     })
     .collect();
 
-    let mut return_ty =
-        trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping: &mapping });
+    let mut return_ty = trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping });
 
     if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() {
         let ty::Alias(ty::Projection, future_ty) = return_ty.kind() else {
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 0876bb82848..d7dfe482da4 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -1,7 +1,3 @@
-// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
-//
-// We don't do any drop checking during hir typeck.
-
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::codes::*;
 use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
@@ -32,7 +28,10 @@ use crate::hir::def_id::{DefId, LocalDefId};
 ///    struct/enum definition for the nominal type itself (i.e.
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 ///
-pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
+pub(crate) fn check_drop_impl(
+    tcx: TyCtxt<'_>,
+    drop_impl_did: DefId,
+) -> Result<(), ErrorGuaranteed> {
     match tcx.impl_polarity(drop_impl_did) {
         ty::ImplPolarity::Positive => {}
         ty::ImplPolarity::Negative => {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 8aa95d1c1d5..cf3d4897304 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -199,7 +199,8 @@ pub fn check_intrinsic_type(
         let split: Vec<&str> = name_str.split('_').collect();
         assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
 
-        //We only care about the operation here
+        // Each atomic op has variants with different suffixes (`_seq_cst`, `_acquire`, etc.). Use
+        // string ops to strip the suffixes, because the variants all get the same treatment here.
         let (n_tps, inputs, output) = match split[1] {
             "cxchg" | "cxchgweak" => (
                 1,
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 814c784710a..96b33bdd250 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -455,18 +455,14 @@ fn fn_sig_suggestion<'tcx>(
     let mut output = sig.output();
 
     let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
-        output = if let ty::Alias(_, alias_ty) = *output.kind() {
-            tcx.explicit_item_self_bounds(alias_ty.def_id)
+        output = if let ty::Alias(_, alias_ty) = *output.kind()
+            && let Some(output) = tcx
+                .explicit_item_self_bounds(alias_ty.def_id)
                 .iter_instantiated_copied(tcx, alias_ty.args)
                 .find_map(|(bound, _)| {
                     bound.as_projection_clause()?.no_bound_vars()?.term.as_type()
-                })
-                .unwrap_or_else(|| {
-                    span_bug!(
-                        ident.span,
-                        "expected async fn to have `impl Future` output, but it returns {output}"
-                    )
-                })
+                }) {
+            output
         } else {
             span_bug!(
                 ident.span,
@@ -649,6 +645,7 @@ pub fn check_function_signature<'tcx>(
                 }))),
                 err,
                 false,
+                None,
             );
             return Err(diag.emit());
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 83bb8c0dfaf..c9837ca3716 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -2267,14 +2267,12 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
 
 fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
     let items = tcx.hir_module_items(module);
-    let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id));
-    res =
-        res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
-    res =
-        res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
-    res = res
-        .and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
-    res = res.and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
+    let res = items
+        .par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id))
+        .and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
+        .and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
+        .and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
+        .and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
     if module == LocalModDefId::CRATE_DEF_ID {
         super::entry::check_for_entry_fn(tcx);
     }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 6bbd76633da..30f51fe1724 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -404,17 +404,12 @@ pub(crate) fn coerce_unsized_info<'tcx>(
             check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
         }
 
-        (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
-            ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
-            ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
-            &|ty| Ty::new_imm_ptr(tcx, ty),
-        ),
-
-        (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
-            ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
-            ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
-            &|ty| Ty::new_imm_ptr(tcx, ty),
-        ),
+        (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
+        | (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
+            let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
+            let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
+            check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
+        }
 
         (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
             if def_a.is_struct() && def_b.is_struct() =>
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 4e5f0a3186a..b9ef166fc3f 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -158,12 +158,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
         let trait_ref = trait_header.trait_ref.instantiate_identity();
         let trait_def = tcx.trait_def(trait_ref.def_id);
 
-        res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def));
-        res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref));
-
-        res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def));
-        res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));
-        res = res.and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
+        res = res
+            .and(check_impl(tcx, impl_def_id, trait_ref, trait_def))
+            .and(check_object_overlap(tcx, impl_def_id, trait_ref))
+            .and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def))
+            .and(tcx.ensure().orphan_check_impl(impl_def_id))
+            .and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
     }
 
     res
@@ -199,10 +199,9 @@ fn check_object_overlap<'tcx>(
 
         for component_def_id in component_def_ids {
             if !tcx.is_dyn_compatible(component_def_id) {
-                // FIXME(dyn_compat_renaming): Rename test and update comment.
                 // Without the 'dyn_compatible_for_dispatch' feature this is an error
                 // which will be reported by wfcheck. Ignore it here.
-                // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
+                // This is tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`.
                 // With the feature enabled, the trait is not implemented automatically,
                 // so this is valid.
             } else {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index cad7b2a1e57..226370fccad 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -57,7 +57,7 @@ mod type_of;
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     resolve_bound_vars::provide(providers);
     *providers = Providers {
         type_of: type_of::type_of,
@@ -122,7 +122,7 @@ pub fn provide(providers: &mut Providers) {
 /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
 /// `probe_ty_param_bounds` requests, drawing the information from
 /// the HIR (`hir::Generics`), recursively.
-pub struct ItemCtxt<'tcx> {
+pub(crate) struct ItemCtxt<'tcx> {
     tcx: TyCtxt<'tcx>,
     item_def_id: LocalDefId,
     tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
@@ -148,7 +148,7 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
     }
 }
 
-pub struct CollectItemTypesVisitor<'tcx> {
+pub(crate) struct CollectItemTypesVisitor<'tcx> {
     pub tcx: TyCtxt<'tcx>,
 }
 
@@ -364,19 +364,19 @@ fn bad_placeholder<'cx, 'tcx>(
 }
 
 impl<'tcx> ItemCtxt<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
+    pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
         ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
     }
 
-    pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
+    pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         self.lowerer().lower_ty(hir_ty)
     }
 
-    pub fn hir_id(&self) -> hir::HirId {
+    pub(crate) fn hir_id(&self) -> hir::HirId {
         self.tcx.local_def_id_to_hir_id(self.item_def_id)
     }
 
-    pub fn node(&self) -> hir::Node<'tcx> {
+    pub(crate) fn node(&self) -> hir::Node<'tcx> {
         self.tcx.hir_node(self.hir_id())
     }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index f1022d95753..4a508fc0cf6 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -1,7 +1,8 @@
+use rustc_hir as hir;
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
 use rustc_hir::intravisit;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 
 pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
@@ -87,3 +88,82 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
         }
     }
 }
+
+pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
+    for id in tcx.hir().items() {
+        let def_id = id.owner_id.def_id;
+
+        let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else {
+            continue;
+        };
+
+        let vtable_entries = match tcx.hir().item(id).kind {
+            hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
+                let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity();
+                if trait_ref.has_non_region_param() {
+                    tcx.dcx().span_err(
+                        attr.span,
+                        "`rustc_dump_vtable` must be applied to non-generic impl",
+                    );
+                    continue;
+                }
+                if !tcx.is_dyn_compatible(trait_ref.def_id) {
+                    tcx.dcx().span_err(
+                        attr.span,
+                        "`rustc_dump_vtable` must be applied to dyn-compatible trait",
+                    );
+                    continue;
+                }
+                let Ok(trait_ref) = tcx
+                    .try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref)
+                else {
+                    tcx.dcx().span_err(
+                        attr.span,
+                        "`rustc_dump_vtable` applied to impl header that cannot be normalized",
+                    );
+                    continue;
+                };
+                tcx.vtable_entries(trait_ref)
+            }
+            hir::ItemKind::TyAlias(_, _) => {
+                let ty = tcx.type_of(def_id).instantiate_identity();
+                if ty.has_non_region_param() {
+                    tcx.dcx().span_err(
+                        attr.span,
+                        "`rustc_dump_vtable` must be applied to non-generic type",
+                    );
+                    continue;
+                }
+                let Ok(ty) =
+                    tcx.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
+                else {
+                    tcx.dcx().span_err(
+                        attr.span,
+                        "`rustc_dump_vtable` applied to type alias that cannot be normalized",
+                    );
+                    continue;
+                };
+                let ty::Dynamic(data, _, _) = *ty.kind() else {
+                    tcx.dcx().span_err(attr.span, "`rustc_dump_vtable` to type alias of dyn type");
+                    continue;
+                };
+                if let Some(principal) = data.principal() {
+                    tcx.vtable_entries(
+                        tcx.instantiate_bound_regions_with_erased(principal).with_self_ty(tcx, ty),
+                    )
+                } else {
+                    TyCtxt::COMMON_VTABLE_ENTRIES
+                }
+            }
+            _ => {
+                tcx.dcx().span_err(
+                    attr.span,
+                    "`rustc_dump_vtable` only applies to impl, or type alias of dyn type",
+                );
+                continue;
+            }
+        };
+
+        tcx.dcx().span_err(tcx.def_span(def_id), format!("vtable entries: {vtable_entries:#?}"));
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 72baf5c4b58..d67b9d33596 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -12,13 +12,11 @@ use std::ops::ControlFlow;
 
 use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::sorted_map::SortedMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
 use rustc_hir::{
-    self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap,
-    LifetimeName, Node,
+    self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
 };
 use rustc_macros::extension;
 use rustc_middle::hir::nested_filter;
@@ -26,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_middle::{bug, span_bug};
-use rustc_span::def_id::{DefId, LocalDefId, LocalDefIdMap};
+use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::{Ident, Span, sym};
 use tracing::{debug, debug_span, instrument};
 
@@ -62,33 +60,9 @@ impl ResolvedArg {
     }
 }
 
-/// Maps the id of each bound variable reference to the variable decl
-/// that it corresponds to.
-///
-/// FIXME. This struct gets converted to a `ResolveBoundVars` for
-/// actual use. It has the same data, but indexed by `LocalDefId`. This
-/// is silly.
-#[derive(Debug, Default)]
-struct NamedVarMap {
-    // maps from every use of a named (not anonymous) bound var to a
-    // `ResolvedArg` describing how that variable is bound
-    defs: ItemLocalMap<ResolvedArg>,
-
-    // Maps relevant hir items to the bound vars on them. These include:
-    // - function defs
-    // - function pointers
-    // - closures
-    // - trait refs
-    // - bound types (like `T` in `for<'a> T<'a>: Foo`)
-    late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
-
-    // List captured variables for each opaque type.
-    opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
-}
-
 struct BoundVarContext<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    map: &'a mut NamedVarMap,
+    rbv: &'a mut ResolveBoundVars,
     scope: ScopeRef<'a>,
 }
 
@@ -267,19 +241,12 @@ pub(crate) fn provide(providers: &mut Providers) {
 
 /// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
 /// You should not read the result of this query directly, but rather use
-/// `named_variable_map`, `is_late_bound_map`, etc.
+/// `named_variable_map`, `late_bound_vars_map`, etc.
 #[instrument(level = "debug", skip(tcx))]
 fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
-    let mut named_variable_map = NamedVarMap {
-        defs: Default::default(),
-        late_bound_vars: Default::default(),
-        opaque_captured_lifetimes: Default::default(),
-    };
-    let mut visitor = BoundVarContext {
-        tcx,
-        map: &mut named_variable_map,
-        scope: &Scope::Root { opt_parent_item: None },
-    };
+    let mut rbv = ResolveBoundVars::default();
+    let mut visitor =
+        BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
     match tcx.hir_owner_node(local_def_id) {
         hir::OwnerNode::Item(item) => visitor.visit_item(item),
         hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
@@ -299,19 +266,10 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
         hir::OwnerNode::Synthetic => unreachable!(),
     }
 
-    let defs = named_variable_map.defs.into_sorted_stable_ord();
-    let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
-    let opaque_captured_lifetimes = named_variable_map.opaque_captured_lifetimes;
-    let rl = ResolveBoundVars {
-        defs: SortedMap::from_presorted_elements(defs),
-        late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
-        opaque_captured_lifetimes,
-    };
-
-    debug!(?rl.defs);
-    debug!(?rl.late_bound_vars);
-    debug!(?rl.opaque_captured_lifetimes);
-    rl
+    debug!(?rbv.defs);
+    debug!(?rbv.late_bound_vars);
+    debug!(?rbv.opaque_captured_lifetimes);
+    rbv
 }
 
 fn late_arg_as_bound_arg<'tcx>(
@@ -404,7 +362,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Binder { hir_id, .. } => {
                     // Nested poly trait refs have the binders concatenated
                     let mut full_binders =
-                        self.map.late_bound_vars.entry(hir_id.local_id).or_default().clone();
+                        self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
                     full_binders.extend(supertrait_bound_vars);
                     break (full_binders, BinderScopeType::Concatenating);
                 }
@@ -646,7 +604,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
 
         let captures = captures.into_inner().into_iter().collect();
         debug!(?captures);
-        self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures);
+        self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -848,7 +806,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
             hir::TyKind::Ref(lifetime_ref, ref mt) => {
                 self.visit_lifetime(lifetime_ref);
                 let scope = Scope::ObjectLifetimeDefault {
-                    lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
+                    lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
                     s: self.scope,
                 };
                 self.with(scope, |this| this.visit_ty_unambig(mt.ty));
@@ -966,7 +924,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
             let bound_vars: Vec<_> =
                 self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
             let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-            self.map.late_bound_vars.insert(hir_id.local_id, bound_vars);
+            self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
         }
         self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
         intravisit::walk_fn_kind(self, fk);
@@ -1140,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     where
         F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
     {
-        let BoundVarContext { tcx, map, .. } = self;
-        let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
+        let BoundVarContext { tcx, rbv, .. } = self;
+        let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
         let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
         {
             let _enter = span.enter();
@@ -1150,10 +1108,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     }
 
     fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
-        if let Some(old) = self.map.late_bound_vars.insert(hir_id.local_id, binder) {
+        if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
             bug!(
                 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
-                self.map.late_bound_vars[&hir_id.local_id]
+                self.rbv.late_bound_vars[&hir_id.local_id]
             )
         }
     }
@@ -1597,9 +1555,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         kind.descr(param_def_id.to_def_id())
                     ),
                 };
-                self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
+                self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
             } else {
-                self.map.defs.insert(hir_id.local_id, def);
+                self.rbv.defs.insert(hir_id.local_id, def);
             }
             return;
         }
@@ -1632,7 +1590,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                             bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
                         }
                     });
-                    self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
+                    self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
                     return;
                 }
                 Scope::Root { .. } => break,
@@ -1725,7 +1683,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 }
             };
 
-            let map = &self.map;
+            let rbv = &self.rbv;
             let generics = self.tcx.generics_of(def_id);
 
             // `type_def_id` points to an item, so there is nothing to inherit generics from.
@@ -1744,7 +1702,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     // This index can be used with `generic_args` since `parent_count == 0`.
                     let index = generics.param_def_id_to_index[&param_def_id] as usize;
                     generic_args.args.get(index).and_then(|arg| match arg {
-                        GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id.local_id).copied(),
+                        GenericArg::Lifetime(lt) => rbv.defs.get(&lt.hir_id.local_id).copied(),
                         _ => None,
                     })
                 }
@@ -2042,7 +2000,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
         debug!(span = ?lifetime_ref.ident.span);
-        self.map.defs.insert(lifetime_ref.hir_id.local_id, def);
+        self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
     }
 
     // When we have a return type notation type in a where clause, like
@@ -2197,7 +2155,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
         // And this is exercised in:
         // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
-        let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
+        let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
         let existing_bound_vars_saved = existing_bound_vars.clone();
         existing_bound_vars.extend(bound_vars);
         self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index e65420ea8bf..ed45833b614 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -100,213 +100,156 @@ enum InheritanceKind {
     Own,
 }
 
-struct GenericsBuilder<'tcx> {
+fn build_generics<'tcx>(
     tcx: TyCtxt<'tcx>,
     sig_id: DefId,
     parent: Option<DefId>,
     inh_kind: InheritanceKind,
-}
-
-impl<'tcx> GenericsBuilder<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
-        GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) }
-    }
-
-    fn with_parent(mut self, parent: DefId) -> Self {
-        self.parent = Some(parent);
-        self
-    }
-
-    fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
-        self.inh_kind = inh_kind;
-        self
-    }
-
-    fn build(self) -> ty::Generics {
-        let mut own_params = vec![];
+) -> ty::Generics {
+    let mut own_params = vec![];
 
-        let sig_generics = self.tcx.generics_of(self.sig_id);
-        if let InheritanceKind::WithParent(has_self) = self.inh_kind
-            && let Some(parent_def_id) = sig_generics.parent
-        {
-            let sig_parent_generics = self.tcx.generics_of(parent_def_id);
-            own_params.append(&mut sig_parent_generics.own_params.clone());
-            if !has_self {
-                own_params.remove(0);
-            }
+    let sig_generics = tcx.generics_of(sig_id);
+    if let InheritanceKind::WithParent(has_self) = inh_kind
+        && let Some(parent_def_id) = sig_generics.parent
+    {
+        let sig_parent_generics = tcx.generics_of(parent_def_id);
+        own_params.append(&mut sig_parent_generics.own_params.clone());
+        if !has_self {
+            own_params.remove(0);
         }
-        own_params.append(&mut sig_generics.own_params.clone());
+    }
+    own_params.append(&mut sig_generics.own_params.clone());
+
+    // Lifetime parameters must be declared before type and const parameters.
+    // Therefore, When delegating from a free function to a associated function,
+    // generic parameters need to be reordered:
+    //
+    // trait Trait<'a, A> {
+    //     fn foo<'b, B>(...) {...}
+    // }
+    //
+    // reuse Trait::foo;
+    // desugaring:
+    // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
+    //     Trait::foo(...)
+    // }
+    own_params.sort_by_key(|key| key.kind.is_ty_or_const());
+
+    let param_def_id_to_index =
+        own_params.iter().map(|param| (param.def_id, param.index)).collect();
+
+    let (parent_count, has_self) = if let Some(def_id) = parent {
+        let parent_generics = tcx.generics_of(def_id);
+        let parent_kind = tcx.def_kind(def_id);
+        (parent_generics.count(), parent_kind == DefKind::Trait)
+    } else {
+        (0, false)
+    };
 
-        // Lifetime parameters must be declared before type and const parameters.
-        // Therefore, When delegating from a free function to a associated function,
-        // generic parameters need to be reordered:
+    for (idx, param) in own_params.iter_mut().enumerate() {
+        param.index = (idx + parent_count) as u32;
+        // FIXME(fn_delegation): Default parameters are not inherited, because they are
+        // not permitted in functions. Therefore, there are 2 options here:
         //
-        // trait Trait<'a, A> {
-        //     fn foo<'b, B>(...) {...}
-        // }
+        // - We can create non-default generic parameters.
+        // - We can substitute default parameters into the signature.
         //
-        // reuse Trait::foo;
-        // desugaring:
-        // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
-        //     Trait::foo(...)
-        // }
-        own_params.sort_by_key(|key| key.kind.is_ty_or_const());
-
-        let param_def_id_to_index =
-            own_params.iter().map(|param| (param.def_id, param.index)).collect();
-
-        let (parent_count, has_self) = if let Some(def_id) = self.parent {
-            let parent_generics = self.tcx.generics_of(def_id);
-            let parent_kind = self.tcx.def_kind(def_id);
-            (parent_generics.count(), parent_kind == DefKind::Trait)
-        } else {
-            (0, false)
-        };
-
-        for (idx, param) in own_params.iter_mut().enumerate() {
-            param.index = (idx + parent_count) as u32;
-            // FIXME(fn_delegation): Default parameters are not inherited, because they are
-            // not permitted in functions. Therefore, there are 2 options here:
-            //
-            // - We can create non-default generic parameters.
-            // - We can substitute default parameters into the signature.
-            //
-            // At the moment, first option has been selected as the most general.
-            if let ty::GenericParamDefKind::Type { has_default, .. }
-            | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
-            {
-                *has_default = false;
-            }
+        // At the moment, first option has been selected as the most general.
+        if let ty::GenericParamDefKind::Type { has_default, .. }
+        | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
+        {
+            *has_default = false;
         }
+    }
 
-        ty::Generics {
-            parent: self.parent,
-            parent_count,
-            own_params,
-            param_def_id_to_index,
-            has_self,
-            has_late_bound_regions: sig_generics.has_late_bound_regions,
-        }
+    ty::Generics {
+        parent,
+        parent_count,
+        own_params,
+        param_def_id_to_index,
+        has_self,
+        has_late_bound_regions: sig_generics.has_late_bound_regions,
     }
 }
 
-struct PredicatesBuilder<'tcx> {
+fn build_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     sig_id: DefId,
     parent: Option<DefId>,
     inh_kind: InheritanceKind,
     args: ty::GenericArgsRef<'tcx>,
-}
-
-impl<'tcx> PredicatesBuilder<'tcx> {
-    fn new(
+) -> ty::GenericPredicates<'tcx> {
+    struct PredicatesCollector<'tcx> {
         tcx: TyCtxt<'tcx>,
+        preds: Vec<(ty::Clause<'tcx>, Span)>,
         args: ty::GenericArgsRef<'tcx>,
-        sig_id: DefId,
-    ) -> PredicatesBuilder<'tcx> {
-        PredicatesBuilder {
-            tcx,
-            sig_id,
-            parent: None,
-            inh_kind: InheritanceKind::WithParent(false),
-            args,
-        }
-    }
-
-    fn with_parent(mut self, parent: DefId) -> Self {
-        self.parent = Some(parent);
-        self
     }
 
-    fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
-        self.inh_kind = inh_kind;
-        self
-    }
-
-    fn build(self) -> ty::GenericPredicates<'tcx> {
-        struct PredicatesCollector<'tcx> {
-            tcx: TyCtxt<'tcx>,
-            preds: Vec<(ty::Clause<'tcx>, Span)>,
-            args: ty::GenericArgsRef<'tcx>,
+    impl<'tcx> PredicatesCollector<'tcx> {
+        fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
+            PredicatesCollector { tcx, preds: vec![], args }
         }
 
-        impl<'tcx> PredicatesCollector<'tcx> {
-            fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
-                PredicatesCollector { tcx, preds: vec![], args }
-            }
-
-            fn with_own_preds(
-                mut self,
-                f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
-                def_id: DefId,
-            ) -> Self {
-                let preds = f(def_id).instantiate_own(self.tcx, self.args);
-                self.preds.extend(preds);
-                self
-            }
+        fn with_own_preds(
+            mut self,
+            f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
+            def_id: DefId,
+        ) -> Self {
+            let preds = f(def_id).instantiate_own(self.tcx, self.args);
+            self.preds.extend(preds);
+            self
+        }
 
-            fn with_preds(
-                mut self,
-                f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
-                def_id: DefId,
-            ) -> Self {
-                let preds = f(def_id);
-                if let Some(parent_def_id) = preds.parent {
-                    self = self.with_own_preds(f, parent_def_id);
-                }
-                self.with_own_preds(f, def_id)
+        fn with_preds(
+            mut self,
+            f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
+            def_id: DefId,
+        ) -> Self {
+            let preds = f(def_id);
+            if let Some(parent_def_id) = preds.parent {
+                self = self.with_own_preds(f, parent_def_id);
             }
+            self.with_own_preds(f, def_id)
         }
-        let collector = PredicatesCollector::new(self.tcx, self.args);
-
-        // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
-        // Note: `predicates_of` query can also add inferred outlives predicates, but that
-        // is not the case here as `sig_id` is either a trait or a function.
-        let preds = match self.inh_kind {
-            InheritanceKind::WithParent(false) => {
-                collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id)
-            }
-            InheritanceKind::WithParent(true) => {
-                collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
-            }
-            InheritanceKind::Own => {
-                collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
-            }
+    }
+    let collector = PredicatesCollector::new(tcx, args);
+
+    // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
+    // Note: `predicates_of` query can also add inferred outlives predicates, but that
+    // is not the case here as `sig_id` is either a trait or a function.
+    let preds = match inh_kind {
+        InheritanceKind::WithParent(false) => {
+            collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id)
         }
-        .preds;
-
-        ty::GenericPredicates {
-            parent: self.parent,
-            predicates: self.tcx.arena.alloc_from_iter(preds),
+        InheritanceKind::WithParent(true) => {
+            collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id)
+        }
+        InheritanceKind::Own => {
+            collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id)
         }
     }
+    .preds;
+
+    ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) }
 }
 
-struct GenericArgsBuilder<'tcx> {
+fn build_generic_args<'tcx>(
     tcx: TyCtxt<'tcx>,
-    remap_table: RemapTable,
     sig_id: DefId,
     def_id: LocalDefId,
-}
+    args: ty::GenericArgsRef<'tcx>,
+) -> ty::GenericArgsRef<'tcx> {
+    let caller_generics = tcx.generics_of(def_id);
+    let callee_generics = tcx.generics_of(sig_id);
 
-impl<'tcx> GenericArgsBuilder<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> {
-        GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id }
+    let mut remap_table = FxHashMap::default();
+    for caller_param in &caller_generics.own_params {
+        let callee_index = callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
+        remap_table.insert(callee_index, caller_param.index);
     }
 
-    fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> {
-        let caller_generics = self.tcx.generics_of(self.def_id);
-        let callee_generics = self.tcx.generics_of(self.sig_id);
-
-        for caller_param in &caller_generics.own_params {
-            let callee_index =
-                callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap();
-            self.remap_table.insert(callee_index, caller_param.index);
-        }
-
-        let mut folder = ParamIndexRemapper { tcx: self.tcx, remap_table: self.remap_table };
-        args.fold_with(&mut folder)
-    }
+    let mut folder = ParamIndexRemapper { tcx, remap_table };
+    args.fold_with(&mut folder)
 }
 
 fn create_generic_args<'tcx>(
@@ -314,8 +257,6 @@ fn create_generic_args<'tcx>(
     def_id: LocalDefId,
     sig_id: DefId,
 ) -> ty::GenericArgsRef<'tcx> {
-    let builder = GenericArgsBuilder::new(tcx, sig_id, def_id);
-
     let caller_kind = fn_kind(tcx, def_id.into());
     let callee_kind = fn_kind(tcx, sig_id);
     match (caller_kind, callee_kind) {
@@ -325,7 +266,7 @@ fn create_generic_args<'tcx>(
         | (FnKind::AssocTrait, FnKind::Free)
         | (FnKind::AssocTrait, FnKind::AssocTrait) => {
             let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
-            builder.build_from_args(args)
+            build_generic_args(tcx, sig_id, def_id, args)
         }
 
         (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
@@ -335,8 +276,9 @@ fn create_generic_args<'tcx>(
                 tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args;
 
             let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
-            let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
-            let method_args = builder.build_from_args(method_args);
+            let method_args =
+                tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
+            let method_args = build_generic_args(tcx, sig_id, def_id, method_args);
 
             tcx.mk_args_from_iter(parent_args.iter().chain(method_args))
         }
@@ -347,16 +289,16 @@ fn create_generic_args<'tcx>(
             let generic_self_ty = ty::GenericArg::from(self_ty);
 
             let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
-            let trait_args = builder.build_from_args(trait_args);
+            let trait_args = build_generic_args(tcx, sig_id, def_id, trait_args);
 
             let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
             tcx.mk_args_from_iter(args)
         }
 
         // For trait impl's `sig_id` is always equal to the corresponding trait method.
+        // For inherent methods delegation is not yet supported.
         (FnKind::AssocTraitImpl, _)
         | (_, FnKind::AssocTraitImpl)
-        // Delegation to inherent methods is not yet supported.
         | (_, FnKind::AssocInherentImpl) => unreachable!(),
     }
 }
@@ -377,39 +319,31 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
     def_id: LocalDefId,
     sig_id: DefId,
 ) -> ty::Generics {
-    let builder = GenericsBuilder::new(tcx, sig_id);
-
     let caller_kind = fn_kind(tcx, def_id.into());
     let callee_kind = fn_kind(tcx, sig_id);
     match (caller_kind, callee_kind) {
-        (FnKind::Free, FnKind::Free)
-        | (FnKind::Free, FnKind::AssocTrait) => builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build(),
+        (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
+            build_generics(tcx, sig_id, None, InheritanceKind::WithParent(true))
+        }
 
         (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
-            builder
-            .with_parent(tcx.parent(def_id.into()))
-            .with_inheritance_kind(InheritanceKind::Own)
-            .build()
+            build_generics(tcx, sig_id, Some(tcx.parent(def_id.into())), InheritanceKind::Own)
         }
 
         (FnKind::AssocInherentImpl, FnKind::AssocTrait)
-        | (FnKind::AssocTrait, FnKind::AssocTrait) => {
-            builder
-            .with_parent(tcx.parent(def_id.into()))
-            .build()
-        }
-
-        (FnKind::AssocInherentImpl, FnKind::Free)
-        | (FnKind::AssocTrait, FnKind::Free) => {
-            builder
-            .with_parent(tcx.parent(def_id.into()))
-            .build()
-        }
+        | (FnKind::AssocTrait, FnKind::AssocTrait)
+        | (FnKind::AssocInherentImpl, FnKind::Free)
+        | (FnKind::AssocTrait, FnKind::Free) => build_generics(
+            tcx,
+            sig_id,
+            Some(tcx.parent(def_id.into())),
+            InheritanceKind::WithParent(false),
+        ),
 
         // For trait impl's `sig_id` is always equal to the corresponding trait method.
+        // For inherent methods delegation is not yet supported.
         (FnKind::AssocTraitImpl, _)
         | (_, FnKind::AssocTraitImpl)
-        // Delegation to inherent methods is not yet supported.
         | (_, FnKind::AssocInherentImpl) => unreachable!(),
     }
 }
@@ -420,36 +354,36 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
     sig_id: DefId,
 ) -> ty::GenericPredicates<'tcx> {
     let args = create_generic_args(tcx, def_id, sig_id);
-    let builder = PredicatesBuilder::new(tcx, args, sig_id);
-
     let caller_kind = fn_kind(tcx, def_id.into());
     let callee_kind = fn_kind(tcx, sig_id);
     match (caller_kind, callee_kind) {
-        (FnKind::Free, FnKind::Free)
-        | (FnKind::Free, FnKind::AssocTrait) => {
-            builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build()
+        (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
+            build_predicates(tcx, sig_id, None, InheritanceKind::WithParent(true), args)
         }
 
-        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
-            builder
-            .with_parent(tcx.parent(def_id.into()))
-            .with_inheritance_kind(InheritanceKind::Own)
-            .build()
-        }
+        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => build_predicates(
+            tcx,
+            sig_id,
+            Some(tcx.parent(def_id.into())),
+            InheritanceKind::Own,
+            args,
+        ),
 
         (FnKind::AssocInherentImpl, FnKind::AssocTrait)
         | (FnKind::AssocTrait, FnKind::AssocTrait)
         | (FnKind::AssocInherentImpl, FnKind::Free)
-        | (FnKind::AssocTrait, FnKind::Free) => {
-            builder
-                .with_parent(tcx.parent(def_id.into()))
-                .build()
-        }
+        | (FnKind::AssocTrait, FnKind::Free) => build_predicates(
+            tcx,
+            sig_id,
+            Some(tcx.parent(def_id.into())),
+            InheritanceKind::WithParent(false),
+            args,
+        ),
 
         // For trait impl's `sig_id` is always equal to the corresponding trait method.
+        // For inherent methods delegation is not yet supported.
         (FnKind::AssocTraitImpl, _)
         | (_, FnKind::AssocTraitImpl)
-        // Delegation to inherent methods is not yet supported.
         | (_, FnKind::AssocInherentImpl) => unreachable!(),
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index 67407349729..b2501d647a5 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -495,6 +495,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                         .iter()
                         .any(|constraint| constraint.ident.name == item.name)
                 })
+                .filter(|item| !item.is_impl_trait_in_trait())
                 .map(|item| self.tcx.item_ident(item.def_id).to_string())
                 .collect()
         } else {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index fe3dcb35639..43137397870 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -273,7 +273,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
 
                             // We lower to an infer even when the feature gate is not enabled
                             // as it is useful for diagnostics to be able to see a `ConstKind::Infer`
-                            args.push(ctx.provided_kind(&args, param, arg));
+                            args.push(ctx.provided_kind(param, arg));
                             args_iter.next();
                             params.next();
                         }
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 61d5869c19f..b4cab3330af 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -296,7 +296,6 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
 
     fn provided_kind(
         &mut self,
-        preceding_args: &[ty::GenericArg<'tcx>],
         param: &ty::GenericParamDef,
         arg: &GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx>;
@@ -480,7 +479,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             fn provided_kind(
                 &mut self,
-                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 32694d5f4bc..af1107b499f 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -34,7 +34,7 @@
 //! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
 //! ```
 //!
-//! We get that the generic pamameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
+//! We get that the generic parameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
 //! `T` is constrained to be `<I as Iterator>::Item`, so we check only
 //! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The
 //! predicates of `impl1` are only `T: Sized`, which is also a predicate of
@@ -119,7 +119,6 @@ fn check_always_applicable(
     impl2_node: Node,
 ) -> Result<(), ErrorGuaranteed> {
     let span = tcx.def_span(impl1_def_id);
-    let mut res = check_has_items(tcx, impl1_def_id, impl2_node, span);
 
     let (impl1_args, impl2_args) = get_impl_args(tcx, impl1_def_id, impl2_node)?;
     let impl2_def_id = impl2_node.def_id();
@@ -131,11 +130,10 @@ fn check_always_applicable(
         unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
     };
 
-    res = res.and(check_static_lifetimes(tcx, &parent_args, span));
-    res = res.and(check_duplicate_params(tcx, impl1_args, parent_args, span));
-    res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span));
-
-    res
+    check_has_items(tcx, impl1_def_id, impl2_node, span)
+        .and(check_static_lifetimes(tcx, &parent_args, span))
+        .and(check_duplicate_params(tcx, impl1_args, parent_args, span))
+        .and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span))
 }
 
 fn check_has_items(
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index bc7d4365eee..ae054a9eaeb 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -83,12 +83,11 @@ pub mod autoderef;
 mod bounds;
 mod check_unused;
 mod coherence;
-mod delegation;
-pub mod hir_ty_lowering;
-// FIXME: This module shouldn't be public.
-pub mod collect;
+mod collect;
 mod constrained_generic_params;
+mod delegation;
 mod errors;
+pub mod hir_ty_lowering;
 pub mod hir_wf_check;
 mod impl_wf_check;
 mod outlives;
@@ -104,7 +103,8 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 
-use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
+pub use crate::collect::suggest_impl_trait;
+use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
@@ -152,11 +152,14 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     });
 
     if tcx.features().rustc_attrs() {
-        tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx));
-        tcx.sess.time("variance_dumping", || variance::dump::variances(tcx));
-        collect::dump::opaque_hidden_types(tcx);
-        collect::dump::predicates_and_item_bounds(tcx);
-        collect::dump::def_parents(tcx);
+        tcx.sess.time("dumping_rustc_attr_data", || {
+            outlives::dump::inferred_outlives(tcx);
+            variance::dump::variances(tcx);
+            collect::dump::opaque_hidden_types(tcx);
+            collect::dump::predicates_and_item_bounds(tcx);
+            collect::dump::def_parents(tcx);
+            collect::dump::vtables(tcx);
+        });
     }
 
     // Make sure we evaluate all static and (non-associated) const items, even if unused.
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index c2377b4781c..036163b9f14 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -24,7 +24,7 @@ pub(super) fn infer_predicates(
 
     // If new predicates were added then we need to re-calculate
     // all crates since there could be new implied predicates.
-    'outer: loop {
+    loop {
         let mut predicates_added = false;
 
         // Visit all the crates and infer predicates
@@ -90,7 +90,7 @@ pub(super) fn infer_predicates(
         }
 
         if !predicates_added {
-            break 'outer;
+            break;
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 02cfb57b836..a7760326bb4 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -27,9 +27,6 @@ mod solve;
 
 pub(crate) mod dump;
 
-/// Code for transforming variances.
-mod xform;
-
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { variances_of, crate_variances, ..*providers };
 }
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index d0bdca86779..4106c1a5b63 100644
--- a/compiler/rustc_hir_analysis/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
@@ -12,8 +12,26 @@ use tracing::debug;
 use super::constraints::*;
 use super::terms::VarianceTerm::*;
 use super::terms::*;
-use super::xform::*;
 
+fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
+    // Greatest lower bound of the variance lattice as defined in The Paper:
+    //
+    //       *
+    //    -     +
+    //       o
+    match (v1, v2) {
+        (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
+
+        (ty::Covariant, ty::Contravariant) => ty::Invariant,
+        (ty::Contravariant, ty::Covariant) => ty::Invariant,
+
+        (ty::Covariant, ty::Covariant) => ty::Covariant,
+
+        (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
+
+        (x, ty::Bivariant) | (ty::Bivariant, x) => x,
+    }
+}
 struct SolveContext<'a, 'tcx> {
     terms_cx: TermsContext<'a, 'tcx>,
     constraints: Vec<Constraint<'a>>,
diff --git a/compiler/rustc_hir_analysis/src/variance/xform.rs b/compiler/rustc_hir_analysis/src/variance/xform.rs
deleted file mode 100644
index 2e9964788e6..00000000000
--- a/compiler/rustc_hir_analysis/src/variance/xform.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use rustc_middle::ty;
-
-pub(crate) fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
-    // Greatest lower bound of the variance lattice as
-    // defined in The Paper:
-    //
-    //       *
-    //    -     +
-    //       o
-    match (v1, v2) {
-        (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
-
-        (ty::Covariant, ty::Contravariant) => ty::Invariant,
-        (ty::Contravariant, ty::Covariant) => ty::Invariant,
-
-        (ty::Covariant, ty::Covariant) => ty::Covariant,
-
-        (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
-
-        (x, ty::Bivariant) | (ty::Bivariant, x) => x,
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 8e647ad3c6a..e84ae65f903 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1261,7 +1261,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             fn provided_kind(
                 &mut self,
-                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8e78fb3e219..fb5fc109ce4 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1147,6 +1147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Some(self.param_env.and(trace.values)),
                                 e,
                                 true,
+                                None,
                             );
                         }
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index d432199f037..b77e6de52ff 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -31,12 +31,12 @@ use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
 /// functions, closures, and `const`s, including performing type inference
 /// with [`InferCtxt`].
 ///
-/// This is in contrast to [`ItemCtxt`], which is used to type-check item *signatures*
-/// and thus does not perform type inference.
+/// This is in contrast to `rustc_hir_analysis::collect::ItemCtxt`, which is
+/// used to type-check item *signatures* and thus does not perform type
+/// inference.
 ///
-/// See [`ItemCtxt`]'s docs for more.
+/// See `ItemCtxt`'s docs for more.
 ///
-/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
 /// [`InferCtxt`]: infer::InferCtxt
 pub(crate) struct FnCtxt<'a, 'tcx> {
     pub(super) body_id: LocalDefId,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index aea2e0fd3a3..60f9265bfcc 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -12,8 +12,8 @@ use rustc_hir::{
     GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
     WherePredicateKind, expr_needs_parens,
 };
-use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
+use rustc_hir_analysis::suggest_impl_trait;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 880ee83c80a..5c1c38aeb95 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -413,7 +413,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
             fn provided_kind(
                 &mut self,
-                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 12e2bbc968f..ad15b764bcc 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -402,6 +402,18 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
     }
 }
 
+impl<'tcx> ToTrace<'tcx> for ty::ExistentialTraitRef<'tcx> {
+    fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
+        TypeTrace {
+            cause: cause.clone(),
+            values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(
+                ty::Binder::dummy(a),
+                ty::Binder::dummy(b),
+            )),
+        }
+    }
+}
+
 impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
     fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
         TypeTrace {
@@ -410,3 +422,15 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
         }
     }
 }
+
+impl<'tcx> ToTrace<'tcx> for ty::ExistentialProjection<'tcx> {
+    fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
+        TypeTrace {
+            cause: cause.clone(),
+            values: ValuePairs::ExistentialProjection(ExpectedFound::new(
+                ty::Binder::dummy(a),
+                ty::Binder::dummy(b),
+            )),
+        }
+    }
+}
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 241bc35857a..0b91c023cfc 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -26,7 +26,6 @@ use rustc_parse::{
 };
 use rustc_passes::{abi_test, input_stats, layout_test};
 use rustc_resolve::Resolver;
-use rustc_session::code_stats::VTableSizeInfo;
 use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
 use rustc_session::cstore::Untracked;
 use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name};
@@ -989,90 +988,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
         // we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
         let _ = tcx.all_diagnostic_items(());
     });
-
-    if sess.opts.unstable_opts.print_vtable_sizes {
-        let traits = tcx.traits(LOCAL_CRATE);
-
-        for &tr in traits {
-            if !tcx.is_dyn_compatible(tr) {
-                continue;
-            }
-
-            let name = ty::print::with_no_trimmed_paths!(tcx.def_path_str(tr));
-
-            let mut first_dsa = true;
-
-            // Number of vtable entries, if we didn't have upcasting
-            let mut entries_ignoring_upcasting = 0;
-            // Number of vtable entries needed solely for upcasting
-            let mut entries_for_upcasting = 0;
-
-            let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr));
-
-            // A slightly edited version of the code in
-            // `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self
-            // type and just counts number of entries.
-            //
-            // Note that this is technically wrong, for traits which have associated types in
-            // supertraits:
-            //
-            //   trait A: AsRef<Self::T> + AsRef<()> { type T; }
-            //
-            // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>`
-            // and `AsRef<()>` are the same trait, thus we assume that those are different, and
-            // potentially over-estimate how many vtable entries there are.
-            //
-            // Similarly this is wrong for traits that have methods with possibly-impossible bounds.
-            // For example:
-            //
-            //   trait B<T> { fn f(&self) where T: Copy; }
-            //
-            // Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3.
-            // However, since we don't know `T`, we can't know if `T: Copy` holds or not,
-            // thus we lean on the bigger side and say it has 4 entries.
-            traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| {
-                match segment {
-                    traits::vtable::VtblSegment::MetadataDSA => {
-                        // If this is the first dsa, it would be included either way,
-                        // otherwise it's needed for upcasting
-                        if std::mem::take(&mut first_dsa) {
-                            entries_ignoring_upcasting += 3;
-                        } else {
-                            entries_for_upcasting += 3;
-                        }
-                    }
-
-                    traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                        // Lookup the shape of vtable for the trait.
-                        let own_existential_entries =
-                            tcx.own_existential_vtable_entries(trait_ref.def_id());
-
-                        // The original code here ignores the method if its predicates are
-                        // impossible. We can't really do that as, for example, all not trivial
-                        // bounds on generic parameters are impossible (since we don't know the
-                        // parameters...), see the comment above.
-                        entries_ignoring_upcasting += own_existential_entries.len();
-
-                        if emit_vptr {
-                            entries_for_upcasting += 1;
-                        }
-                    }
-                }
-
-                std::ops::ControlFlow::Continue::<std::convert::Infallible>(())
-            });
-
-            sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo {
-                trait_name: name.clone(),
-                entries: entries_ignoring_upcasting + entries_for_upcasting,
-                entries_ignoring_upcasting,
-                entries_for_upcasting,
-                upcasting_cost_percent: entries_for_upcasting as f64
-                    / entries_ignoring_upcasting as f64
-                    * 100.,
-            })
-        }
-    }
 }
 
 /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
@@ -1153,12 +1068,6 @@ pub(crate) fn start_codegen<'tcx>(
         tcx.sess.code_stats.print_type_sizes();
     }
 
-    if tcx.sess.opts.unstable_opts.print_vtable_sizes {
-        let crate_name = tcx.crate_name(LOCAL_CRATE);
-
-        tcx.sess.code_stats.print_vtable_sizes(crate_name);
-    }
-
     codegen
 }
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 9495030f124..fb69dd54811 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -8,12 +8,12 @@ use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::emitter::HumanReadableErrorType;
 use rustc_errors::{ColorConfig, registry};
 use rustc_session::config::{
-    BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions,
-    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
-    FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay,
-    LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig,
-    OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes,
-    PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
+    AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel,
+    CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
+    Externs, FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage,
+    InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans,
+    NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
+    Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
     SymbolManglingVersion, WasiExecModel, build_configuration, build_session_options,
     rustc_optgroups,
 };
@@ -760,6 +760,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(allow_features, Some(vec![String::from("lang_items")]));
     tracked!(always_encode_mir, true);
     tracked!(assume_incomplete_release, true);
+    tracked!(autodiff, vec![AutoDiff::Print]);
     tracked!(binary_dep_depinfo, true);
     tracked!(box_noalias, false);
     tracked!(
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
index 9fde35f82d8..35db8632625 100644
--- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -37,7 +37,7 @@ declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTAB
 impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         let def_id = item.owner_id.to_def_id();
-        // NOTE(nbdd0121): use `object_safety_violations` instead of `is_dyn_compatible` because
+        // NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because
         // the latter will report `where_clause_object_safety` lint.
         if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
             && cx.tcx.is_dyn_compatible(def_id)
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 35186778671..7ff316ba83a 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -319,7 +319,11 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
   case LLVMRustAttributeKind::NoAlias:
     return Attribute::NoAlias;
   case LLVMRustAttributeKind::NoCapture:
+#if LLVM_VERSION_GE(21, 0)
+    report_fatal_error("NoCapture doesn't exist in LLVM 21");
+#else
     return Attribute::NoCapture;
+#endif
   case LLVMRustAttributeKind::NoCfCheck:
     return Attribute::NoCfCheck;
   case LLVMRustAttributeKind::NoInline:
@@ -431,6 +435,12 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
 
 extern "C" LLVMAttributeRef
 LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
+#if LLVM_VERSION_GE(21, 0)
+  // LLVM 21 replaced the NoCapture attribute with Captures(none).
+  if (RustAttr == LLVMRustAttributeKind::NoCapture) {
+    return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
+  }
+#endif
   return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
 }
 
@@ -667,8 +677,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
       unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
 }
 
-typedef DIBuilder *LLVMRustDIBuilderRef;
-
 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
   return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
 }
@@ -677,12 +685,6 @@ template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
 #define DIArray DINodeArray
 #define unwrapDI unwrapDIPtr
 
-// FIXME(Zalathar): This is a temporary typedef to avoid churning dozens of
-// bindings that are going to be deleted and replaced with their LLVM-C
-// equivalents, as part of #134009. After that happens, the remaining bindings
-// can be adjusted to use `LLVMDIFlags` instead of relying on this typedef.
-typedef LLVMDIFlags LLVMRustDIFlags;
-
 // Statically assert that `LLVMDIFlags` (C) and `DIFlags` (C++) have the same
 // layout, at least for the flags we know about. This isn't guaranteed, but is
 // likely to remain true, and as long as it is true it makes conversions easy.
@@ -955,7 +957,8 @@ extern "C" LLVMValueRef LLVMRustGetLastInstruction(LLVMBasicBlockRef BB) {
   return nullptr;
 }
 
-extern "C" void LLVMRustEraseInstBefore(LLVMBasicBlockRef bb, LLVMValueRef I) {
+extern "C" void LLVMRustEraseInstUntilInclusive(LLVMBasicBlockRef bb,
+                                                LLVMValueRef I) {
   auto &BB = *unwrap(bb);
   auto &Inst = *unwrap<Instruction>(I);
   auto It = BB.begin();
@@ -963,8 +966,6 @@ extern "C" void LLVMRustEraseInstBefore(LLVMBasicBlockRef bb, LLVMValueRef I) {
     ++It;
   // Make sure we found the Instruction.
   assert(It != BB.end());
-  // We don't want to erase the instruction itself.
-  It--;
   // Delete in rev order to ensure no dangling references.
   while (It != BB.begin()) {
     auto Prev = std::prev(It);
@@ -994,34 +995,34 @@ extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind,
   unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
 }
 
-extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
-  return new DIBuilder(*unwrap(M));
+extern "C" LLVMDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
+  return wrap(new DIBuilder(*unwrap(M)));
 }
 
-extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
-  delete Builder;
+extern "C" void LLVMRustDIBuilderDispose(LLVMDIBuilderRef Builder) {
+  delete unwrap(Builder);
 }
 
-extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
-  Builder->finalize();
+extern "C" void LLVMRustDIBuilderFinalize(LLVMDIBuilderRef Builder) {
+  unwrap(Builder)->finalize();
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
-    LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
+    LLVMDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
     const char *Producer, size_t ProducerLen, bool isOptimized,
     const char *Flags, unsigned RuntimeVer, const char *SplitName,
     size_t SplitNameLen, LLVMRustDebugEmissionKind Kind, uint64_t DWOId,
     bool SplitDebugInlining, LLVMRustDebugNameTableKind TableKind) {
   auto *File = unwrapDI<DIFile>(FileRef);
 
-  return wrap(Builder->createCompileUnit(
+  return wrap(unwrap(Builder)->createCompileUnit(
       Lang, File, StringRef(Producer, ProducerLen), isOptimized, Flags,
       RuntimeVer, StringRef(SplitName, SplitNameLen), fromRust(Kind), DWOId,
       SplitDebugInlining, false, fromRust(TableKind)));
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
+LLVMRustDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
                             size_t FilenameLen, const char *Directory,
                             size_t DirectoryLen, LLVMRustChecksumKind CSKind,
                             const char *Checksum, size_t ChecksumLen,
@@ -1034,29 +1035,29 @@ LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
   std::optional<StringRef> oSource{};
   if (Source)
     oSource = StringRef(Source, SourceLen);
-  return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
-                                  StringRef(Directory, DirectoryLen), CSInfo,
-                                  oSource));
+  return wrap(unwrap(Builder)->createFile(StringRef(Filename, FilenameLen),
+                                          StringRef(Directory, DirectoryLen),
+                                          CSInfo, oSource));
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
+LLVMRustDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder,
                                       LLVMMetadataRef ParameterTypes) {
-  return wrap(Builder->createSubroutineType(
+  return wrap(unwrap(Builder)->createSubroutineType(
       DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
     LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
-    unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags,
+    unsigned ScopeLine, LLVMDIFlags Flags, LLVMRustDISPFlags SPFlags,
     LLVMValueRef MaybeFn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) {
   DITemplateParameterArray TParams =
       DITemplateParameterArray(unwrap<MDTuple>(TParam));
   DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
   DINode::DIFlags llvmFlags = fromRust(Flags);
-  DISubprogram *Sub = Builder->createFunction(
+  DISubprogram *Sub = unwrap(Builder)->createFunction(
       unwrapDI<DIScope>(Scope), StringRef(Name, NameLen),
       StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
       unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, llvmSPFlags,
@@ -1067,15 +1068,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
     LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
-    LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
+    LLVMDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
   DITemplateParameterArray TParams =
       DITemplateParameterArray(unwrap<MDTuple>(TParam));
   DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
   DINode::DIFlags llvmFlags = fromRust(Flags);
-  DISubprogram *Sub = Builder->createMethod(
+  DISubprogram *Sub = unwrap(Builder)->createMethod(
       unwrapDI<DIScope>(Scope), StringRef(Name, NameLen),
       StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
       unwrapDI<DISubroutineType>(Ty), 0, 0,
@@ -1085,39 +1086,39 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
+LLVMRustDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name,
                                  size_t NameLen, uint64_t SizeInBits,
                                  unsigned Encoding) {
-  return wrap(
-      Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
+  return wrap(unwrap(Builder)->createBasicType(StringRef(Name, NameLen),
+                                               SizeInBits, Encoding));
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateTypedef(LLVMRustDIBuilderRef Builder,
-                               LLVMMetadataRef Type, const char *Name,
-                               size_t NameLen, LLVMMetadataRef File,
-                               unsigned LineNo, LLVMMetadataRef Scope) {
-  return wrap(Builder->createTypedef(
+LLVMRustDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type,
+                               const char *Name, size_t NameLen,
+                               LLVMMetadataRef File, unsigned LineNo,
+                               LLVMMetadataRef Scope) {
+  return wrap(unwrap(Builder)->createTypedef(
       unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
       LineNo, unwrapDIPtr<DIScope>(Scope)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
-    uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
-    const char *Name, size_t NameLen) {
-  return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
-                                         SizeInBits, AlignInBits, AddressSpace,
-                                         StringRef(Name, NameLen)));
+    LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits,
+    uint32_t AlignInBits, unsigned AddressSpace, const char *Name,
+    size_t NameLen) {
+  return wrap(unwrap(Builder)->createPointerType(
+      unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, AddressSpace,
+      StringRef(Name, NameLen)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
-    uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags,
+    uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
     LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang,
     LLVMMetadataRef VTableHolder, const char *UniqueId, size_t UniqueIdLen) {
-  return wrap(Builder->createStructType(
+  return wrap(unwrap(Builder)->createStructType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
       fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
@@ -1126,12 +1127,12 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
-    uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags,
+    uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
     LLVMMetadataRef Discriminator, LLVMMetadataRef Elements,
     const char *UniqueId, size_t UniqueIdLen) {
-  return wrap(Builder->createVariantPart(
+  return wrap(unwrap(Builder)->createVariantPart(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
       fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
@@ -1140,36 +1141,36 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
-    uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
+    uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags,
     LLVMMetadataRef Ty) {
-  return wrap(Builder->createMemberType(
+  return wrap(unwrap(Builder)->createMemberType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits, OffsetInBits,
       fromRust(Flags), unwrapDI<DIType>(Ty)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
     uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
-    LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
+    LLVMDIFlags Flags, LLVMMetadataRef Ty) {
   llvm::ConstantInt *D = nullptr;
   if (Discriminant) {
     D = unwrap<llvm::ConstantInt>(Discriminant);
   }
-  return wrap(Builder->createVariantMemberType(
+  return wrap(unwrap(Builder)->createVariantMemberType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, D,
       fromRust(Flags), unwrapDI<DIType>(Ty)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
-    LLVMRustDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) {
-  return wrap(Builder->createStaticMemberType(
+    LLVMDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) {
+  return wrap(unwrap(Builder)->createStaticMemberType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), fromRust(Flags),
       unwrap<llvm::ConstantInt>(val), llvm::dwarf::DW_TAG_member, AlignInBits));
@@ -1183,21 +1184,21 @@ LLVMRustDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag,
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateLexicalBlock(LLVMRustDIBuilderRef Builder,
+LLVMRustDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Builder,
                                     LLVMMetadataRef Scope, LLVMMetadataRef File,
                                     unsigned Line, unsigned Col) {
-  return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
-                                          unwrapDI<DIFile>(File), Line, Col));
+  return wrap(unwrap(Builder)->createLexicalBlock(
+      unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Col));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) {
-  return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
-                                              unwrapDI<DIFile>(File)));
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) {
+  return wrap(unwrap(Builder)->createLexicalBlockFile(
+      unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
     size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
     LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
     bool IsLocalToUnit, LLVMValueRef V, LLVMMetadataRef Decl = nullptr,
@@ -1206,16 +1207,16 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
 
   llvm::DIExpression *InitExpr = nullptr;
   if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
-    InitExpr = Builder->createConstantValueExpression(
+    InitExpr = unwrap(Builder)->createConstantValueExpression(
         IntVal->getValue().getSExtValue());
   } else if (llvm::ConstantFP *FPVal =
                  llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
-    InitExpr = Builder->createConstantValueExpression(
+    InitExpr = unwrap(Builder)->createConstantValueExpression(
         FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
   }
 
   llvm::DIGlobalVariableExpression *VarExpr =
-      Builder->createGlobalVariableExpression(
+      unwrap(Builder)->createGlobalVariableExpression(
           unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
           StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File),
           LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
@@ -1228,17 +1229,17 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
-    LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
+    LLVMDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
     const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
-    LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
-    unsigned ArgNo, uint32_t AlignInBits) {
+    LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMDIFlags Flags, unsigned ArgNo,
+    uint32_t AlignInBits) {
   if (Tag == 0x100) { // DW_TAG_auto_variable
-    return wrap(Builder->createAutoVariable(
+    return wrap(unwrap(Builder)->createAutoVariable(
         unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
         unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve,
         fromRust(Flags), AlignInBits));
   } else {
-    return wrap(Builder->createParameterVariable(
+    return wrap(unwrap(Builder)->createParameterVariable(
         unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
         unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve,
         fromRust(Flags)));
@@ -1246,53 +1247,56 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
+LLVMRustDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size,
                                  uint32_t AlignInBits, LLVMMetadataRef Ty,
                                  LLVMMetadataRef Subscripts) {
-  return wrap(
-      Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
-                               DINodeArray(unwrapDI<MDTuple>(Subscripts))));
+  return wrap(unwrap(Builder)->createArrayType(
+      Size, AlignInBits, unwrapDI<DIType>(Ty),
+      DINodeArray(unwrapDI<MDTuple>(Subscripts))));
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
+LLVMRustDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder, int64_t Lo,
                                      int64_t Count) {
-  return wrap(Builder->getOrCreateSubrange(Lo, Count));
+  return wrap(unwrap(Builder)->getOrCreateSubrange(Lo, Count));
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
+LLVMRustDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder,
                                   LLVMMetadataRef *Ptr, unsigned Count) {
   Metadata **DataValue = unwrap(Ptr);
-  return wrap(
-      Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
+  return wrap(unwrap(Builder)
+                  ->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count))
+                  .get());
 }
 
-extern "C" void LLVMRustDIBuilderInsertDeclareAtEnd(
-    LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
-    uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
-    LLVMBasicBlockRef InsertAtEnd) {
-  Builder->insertDeclare(unwrap(V), unwrap<DILocalVariable>(VarInfo),
-                         Builder->createExpression(
-                             llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
-                         DebugLoc(cast<MDNode>(unwrap(DL))),
-                         unwrap(InsertAtEnd));
+extern "C" void
+LLVMRustDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef V,
+                                    LLVMMetadataRef VarInfo, uint64_t *AddrOps,
+                                    unsigned AddrOpsCount, LLVMMetadataRef DL,
+                                    LLVMBasicBlockRef InsertAtEnd) {
+  unwrap(Builder)->insertDeclare(
+      unwrap(V), unwrap<DILocalVariable>(VarInfo),
+      unwrap(Builder)->createExpression(
+          llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
+      DebugLoc(cast<MDNode>(unwrap(DL))), unwrap(InsertAtEnd));
 }
 
-extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
-    LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
-    const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) {
-  return wrap(Builder->createEnumerator(
+extern "C" LLVMMetadataRef
+LLVMRustDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, const char *Name,
+                                  size_t NameLen, const uint64_t Value[2],
+                                  unsigned SizeInBits, bool IsUnsigned) {
+  return wrap(unwrap(Builder)->createEnumerator(
       StringRef(Name, NameLen),
       APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
     uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef Elements,
     LLVMMetadataRef ClassTy, bool IsScoped) {
-  return wrap(Builder->createEnumerationType(
+  return wrap(unwrap(Builder)->createEnumerationType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
       DINodeArray(unwrapDI<MDTuple>(Elements)), unwrapDI<DIType>(ClassTy),
@@ -1300,12 +1304,12 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
-    uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags,
+    uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
     LLVMMetadataRef Elements, unsigned RunTimeLang, const char *UniqueId,
     size_t UniqueIdLen) {
-  return wrap(Builder->createUnionType(
+  return wrap(unwrap(Builder)->createUnionType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
       fromRust(Flags), DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
@@ -1313,28 +1317,28 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
     size_t NameLen, LLVMMetadataRef Ty) {
   bool IsDefault = false; // FIXME: should we ever set this true?
-  return wrap(Builder->createTemplateTypeParameter(
+  return wrap(unwrap(Builder)->createTemplateTypeParameter(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIType>(Ty), IsDefault));
 }
 
 extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
+LLVMRustDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder,
                                  LLVMMetadataRef Scope, const char *Name,
                                  size_t NameLen, bool ExportSymbols) {
-  return wrap(Builder->createNameSpace(
+  return wrap(unwrap(Builder)->createNameSpace(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols));
 }
 
 extern "C" void LLVMRustDICompositeTypeReplaceArrays(
-    LLVMRustDIBuilderRef Builder, LLVMMetadataRef CompositeTy,
+    LLVMDIBuilderRef Builder, LLVMMetadataRef CompositeTy,
     LLVMMetadataRef Elements, LLVMMetadataRef Params) {
   DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
-  Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
-                         DINodeArray(unwrap<MDTuple>(Params)));
+  unwrap(Builder)->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
+                                 DINodeArray(unwrap<MDTuple>(Params)));
 }
 
 extern "C" LLVMMetadataRef
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 904409dd777..43372154b2c 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::sync::{Lrc, join, par_for_each_in};
 use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_data_structures::thousands::format_with_underscores;
 use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
@@ -22,7 +23,6 @@ use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, TreatParams};
 use rustc_middle::ty::{AssocItemContainer, SymbolName};
-use rustc_middle::util::common::to_readable_str;
 use rustc_middle::{bug, span_bug};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
 use rustc_session::config::{CrateType, OptLevel};
@@ -782,7 +782,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     "{} {:<23}{:>10} ({:4.1}%)",
                     prefix,
                     label,
-                    to_readable_str(size),
+                    format_with_underscores(size),
                     perc(size)
                 );
             }
@@ -791,7 +791,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
                 prefix,
                 "Total",
-                to_readable_str(total_bytes),
+                format_with_underscores(total_bytes),
                 perc(zero_bytes)
             );
             eprintln!("{prefix}");
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 8dc529b4d7a..ded1c580572 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -17,6 +17,9 @@ middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further itera
 middle_assert_misaligned_ptr_deref =
     misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
 
+middle_assert_null_ptr_deref =
+    null pointer dereference occurred
+
 middle_assert_op_overflow =
     attempt to compute `{$left} {$op} {$right}`, which would overflow
 
@@ -32,6 +35,8 @@ middle_assert_shl_overflow =
 middle_assert_shr_overflow =
     attempt to shift right by `{$val}`, which would overflow
 
+middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} is unsafe
+
 middle_bounds_check =
     index out of bounds: the length is {$len} but the index is {$index}
 
@@ -107,6 +112,8 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$
 middle_unknown_layout =
     the type `{$ty}` has an unknown layout
 
+middle_unsupported_union = we don't support unions yet: '{$ty_name}'
+
 middle_values_too_big =
     values of the type `{$ty}` are too big for the target architecture
 
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 750531b638e..eaccd8c360e 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -87,6 +87,7 @@ macro_rules! arena_types {
             [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
             [decode] attribute: rustc_hir::Attribute,
             [] name_set: rustc_data_structures::unord::UnordSet<rustc_span::Symbol>,
+            [] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem,
             [] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>,
             [] pats: rustc_middle::ty::PatternKind<'tcx>,
 
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index b0187a1848c..b30d3a950c6 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -37,6 +37,20 @@ pub struct OpaqueHiddenTypeMismatch<'tcx> {
     pub sub: TypeMismatchReason,
 }
 
+#[derive(Diagnostic)]
+#[diag(middle_unsupported_union)]
+pub struct UnsupportedUnion {
+    pub ty_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(middle_autodiff_unsafe_inner_const_ref)]
+pub struct AutodiffUnsafeInnerConstRef {
+    #[primary_span]
+    pub span: Span,
+    pub ty: String,
+}
+
 #[derive(Subdiagnostic)]
 pub enum TypeMismatchReason {
     #[label(middle_conflict_types)]
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index 92fa64b0987..2be242364c1 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -1,7 +1,7 @@
-//! "Hooks" provide a way for `tcx` functionality to be provided by some downstream crate without
-//! everything in rustc having to depend on that crate. This is somewhat similar to queries, but
-//! queries come with a lot of machinery for caching and incremental compilation, whereas hooks are
-//! just plain function pointers without any of the query magic.
+//! "Hooks" let you write `tcx` methods in downstream crates and call them in this crate, reducing
+//! the amount of code that needs to be in this crate (which is already very big). This is somewhat
+//! similar to queries, but queries come with a lot of machinery for caching and incremental
+//! compilation, whereas hooks are just plain function pointers without any of the query magic.
 
 use rustc_hir::def_id::{DefId, DefPathHash};
 use rustc_session::StableCrateId;
@@ -75,12 +75,6 @@ declare_hooks! {
     /// (Eligible functions might nevertheless be skipped for other reasons.)
     hook is_eligible_for_coverage(key: LocalDefId) -> bool;
 
-    /// Create the MIR for a given `DefId` - this includes
-    /// unreachable code.
-    /// You do not want to call this yourself, instead use the cached version
-    /// via `mir_built`
-    hook build_mir(key: LocalDefId) -> mir::Body<'tcx>;
-
     /// Imports all `SourceFile`s from the given crate into the current session.
     /// This normally happens automatically when we decode a `Span` from
     /// that crate's metadata - however, the incr comp cache needs
@@ -99,14 +93,11 @@ declare_hooks! {
     /// Will fetch a DefId from a DefPathHash for a foreign crate.
     hook def_path_hash_to_def_id_extern(hash: DefPathHash, stable_crate_id: StableCrateId) -> DefId;
 
-    /// Create a THIR tree for debugging.
-    hook thir_tree(key: LocalDefId) -> String;
-
-    /// Create a list-like THIR representation for debugging.
-    hook thir_flat(key: LocalDefId) -> String;
-
     /// 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.
+    ///
+    /// Note: this hook isn't called within `rustc_middle` but #127779 suggests it's a hook instead
+    /// of a normal function because external tools might want to override it.
     hook should_codegen_locally(instance: crate::ty::Instance<'tcx>) -> bool;
 
     hook alloc_self_profile_query_strings() -> ();
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 39816c17b98..b3064d8fe25 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -4,8 +4,8 @@
 ///
 /// If you have a span available, you should use [`span_bug`] instead.
 ///
-/// If the bug should only be emitted when compilation didn't fail, [`DiagCtxtHandle::span_delayed_bug`]
-/// may be useful.
+/// If the bug should only be emitted when compilation didn't fail,
+/// [`DiagCtxtHandle::span_delayed_bug`] may be useful.
 ///
 /// [`DiagCtxtHandle::span_delayed_bug`]: rustc_errors::DiagCtxtHandle::span_delayed_bug
 /// [`span_bug`]: crate::span_bug
@@ -14,14 +14,8 @@ macro_rules! bug {
     () => (
         $crate::bug!("impossible case reached")
     );
-    ($msg:expr) => (
-        $crate::util::bug::bug_fmt(::std::format_args!($msg))
-    );
-    ($msg:expr,) => (
-        $crate::bug!($msg)
-    );
-    ($fmt:expr, $($arg:tt)+) => (
-        $crate::util::bug::bug_fmt(::std::format_args!($fmt, $($arg)+))
+    ($($arg:tt)+) => (
+        $crate::util::bug::bug_fmt(::std::format_args!($($arg)+))
     );
 }
 
@@ -30,20 +24,14 @@ macro_rules! bug {
 /// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
 /// ICEs.
 ///
-/// If the bug should only be emitted when compilation didn't fail, [`DiagCtxtHandle::span_delayed_bug`]
-/// may be useful.
+/// If the bug should only be emitted when compilation didn't fail,
+/// [`DiagCtxtHandle::span_delayed_bug`] may be useful.
 ///
 /// [`DiagCtxtHandle::span_delayed_bug`]: rustc_errors::DiagCtxtHandle::span_delayed_bug
 #[macro_export]
 macro_rules! span_bug {
-    ($span:expr, $msg:expr) => (
-        $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg))
-    );
-    ($span:expr, $msg:expr,) => (
-        $crate::span_bug!($span, $msg)
-    );
-    ($span:expr, $fmt:expr, $($arg:tt)+) => (
-        $crate::util::bug::span_bug_fmt($span, ::std::format_args!($fmt, $($arg)+))
+    ($span:expr, $($arg:tt)+) => (
+        $crate::util::bug::span_bug_fmt($span, ::std::format_args!($($arg)+))
     );
 }
 
@@ -53,7 +41,6 @@ macro_rules! span_bug {
 // When possible, use one of these (relatively) convenient macros to write
 // the impls for you.
 
-#[macro_export]
 macro_rules! TrivialLiftImpls {
     ($($ty:ty),+ $(,)?) => {
         $(
@@ -69,7 +56,6 @@ macro_rules! TrivialLiftImpls {
 
 /// Used for types that are `Copy` and which **do not care about arena
 /// allocated data** (i.e., don't need to be folded).
-#[macro_export]
 macro_rules! TrivialTypeTraversalImpls {
     ($($ty:ty),+ $(,)?) => {
         $(
@@ -104,7 +90,6 @@ macro_rules! TrivialTypeTraversalImpls {
     };
 }
 
-#[macro_export]
 macro_rules! TrivialTypeTraversalAndLiftImpls {
     ($($t:tt)*) => {
         TrivialTypeTraversalImpls! { $($t)* }
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index cc980f6e62a..1784665bcae 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -1,4 +1,5 @@
 use rustc_abi::Align;
+use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
 use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::Symbol;
@@ -52,6 +53,8 @@ pub struct CodegenFnAttrs {
     /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
     /// the function entry.
     pub patchable_function_entry: Option<PatchableFunctionEntry>,
+    /// For the `#[autodiff]` macros.
+    pub autodiff_item: Option<AutoDiffAttrs>,
 }
 
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -160,6 +163,7 @@ impl CodegenFnAttrs {
             instruction_set: None,
             alignment: None,
             patchable_function_entry: None,
+            autodiff_item: None,
         }
     }
 
diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index 111ac990bc7..51a079e8bc1 100644
--- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -45,15 +45,22 @@ pub enum ObjectLifetimeDefault {
     Param(DefId),
 }
 
-/// Maps the id of each lifetime reference to the lifetime decl
+/// Maps the id of each bound variable reference to the variable decl
 /// that it corresponds to.
-#[derive(HashStable, Debug)]
+#[derive(Debug, Default, HashStable)]
 pub struct ResolveBoundVars {
-    /// Maps from every use of a named (not anonymous) lifetime to a
-    /// `Region` describing how that region is bound
+    // Maps from every use of a named (not anonymous) bound var to a
+    // `ResolvedArg` describing how that variable is bound.
     pub defs: SortedMap<ItemLocalId, ResolvedArg>,
 
+    // Maps relevant hir items to the bound vars on them. These include:
+    // - function defs
+    // - function pointers
+    // - closures
+    // - trait refs
+    // - bound types (like `T` in `for<'a> T<'a>: Foo`)
     pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
 
+    // List captured variables for each opaque type.
     pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0f3fca434ee..cfb78e5dddf 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -27,7 +27,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisit
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Span, Symbol};
-use tracing::trace;
+use tracing::{debug, trace};
 
 pub use self::query::*;
 use self::visit::TyContext;
@@ -1796,6 +1796,47 @@ impl DefLocation {
     }
 }
 
+/// Checks if the specified `local` is used as the `self` parameter of a method call
+/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
+/// returned.
+pub fn find_self_call<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &Body<'tcx>,
+    local: Local,
+    block: BasicBlock,
+) -> Option<(DefId, GenericArgsRef<'tcx>)> {
+    debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
+    if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
+        &body[block].terminator
+        && let Operand::Constant(box ConstOperand { const_, .. }) = func
+        && let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
+        && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
+            tcx.opt_associated_item(def_id)
+        && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
+            **args
+    {
+        if self_place.as_local() == Some(local) {
+            return Some((def_id, fn_args));
+        }
+
+        // Handle the case where `self_place` gets reborrowed.
+        // This happens when the receiver is `&T`.
+        for stmt in &body[block].statements {
+            if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
+                && let Some(reborrow_local) = place.as_local()
+                && self_place.as_local() == Some(reborrow_local)
+                && let Rvalue::Ref(_, _, deref_place) = rvalue
+                && let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
+                    deref_place.as_ref()
+                && deref_local == local
+            {
+                return Some((def_id, fn_args));
+            }
+        }
+    }
+    None
+}
+
 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(target_pointer_width = "64")]
 mod size_asserts {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 6fa3fa2432d..e49fc376a13 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,6 +1,7 @@
 use std::fmt;
 use std::hash::Hash;
 
+use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
 use rustc_attr_parsing::InlineAttr;
 use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -246,6 +247,7 @@ impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> {
 pub struct MonoItemPartitions<'tcx> {
     pub codegen_units: &'tcx [CodegenUnit<'tcx>],
     pub all_mono_items: &'tcx DefIdSet,
+    pub autodiff_items: &'tcx [AutoDiffItem],
 }
 
 #[derive(Debug, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 5868b64f6b5..90a2f175bc9 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1076,6 +1076,7 @@ pub enum AssertKind<O> {
     ResumedAfterReturn(CoroutineKind),
     ResumedAfterPanic(CoroutineKind),
     MisalignedPointerDereference { required: O, found: O },
+    NullPointerDereference,
 }
 
 #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index c04a8251fbc..2fe116212eb 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -206,6 +206,7 @@ impl<O> AssertKind<O> {
             ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
                 LangItem::PanicGenFnNonePanic
             }
+            NullPointerDereference => LangItem::PanicNullPointerDereference,
 
             BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
                 bug!("Unexpected AssertKind")
@@ -271,6 +272,7 @@ impl<O> AssertKind<O> {
                     "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}"
                 )
             }
+            NullPointerDereference => write!(f, "\"null pointer dereference occured\""),
             ResumedAfterReturn(CoroutineKind::Coroutine(_)) => {
                 write!(f, "\"coroutine resumed after completion\"")
             }
@@ -341,7 +343,7 @@ impl<O> AssertKind<O> {
             ResumedAfterPanic(CoroutineKind::Coroutine(_)) => {
                 middle_assert_coroutine_resume_after_panic
             }
-
+            NullPointerDereference => middle_assert_null_ptr_deref,
             MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
         }
     }
@@ -374,7 +376,7 @@ impl<O> AssertKind<O> {
                 add!("left", format!("{left:#?}"));
                 add!("right", format!("{right:#?}"));
             }
-            ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
+            ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {}
             MisalignedPointerDereference { required, found } => {
                 add!("required", format!("{required:#?}"));
                 add!("found", format!("{found:#?}"));
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 95de08ce9c8..6319a7e65b9 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -636,7 +636,7 @@ macro_rules! make_mir_visitor {
                     OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
                         self.visit_operand(op, location);
                     }
-                    ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
+                    ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {
                         // Nothing to visit
                     }
                     MisalignedPointerDereference { required, found } => {
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index f7090fa69e2..949d8303385 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -95,7 +95,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
     }
 }
 
-impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
+impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
     type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 560e3bf3ade..41e9858030c 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1437,9 +1437,9 @@ rustc_queries! {
         desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) }
     }
 
-    query vtable_entries(key: ty::PolyTraitRef<'tcx>)
+    query vtable_entries(key: ty::TraitRef<'tcx>)
                         -> &'tcx [ty::VtblEntry<'tcx>] {
-        desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) }
+        desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) }
     }
 
     query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize {
@@ -1451,7 +1451,7 @@ rustc_queries! {
             key.1, key.0 }
     }
 
-    query vtable_allocation(key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
+    query vtable_allocation(key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
         desc { |tcx| "vtable const allocation for <{} as {}>",
             key.0,
             key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned())
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 8a9110f842a..28a6eba75aa 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -428,7 +428,7 @@ pub enum IsConstable {
     Ctor,
 }
 
-crate::TrivialTypeTraversalAndLiftImpls! {
+TrivialTypeTraversalAndLiftImpls! {
     IsConstable,
 }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index b212992bd2d..3ced64b5b80 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -858,7 +858,12 @@ where
                     }
 
                     let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
-                        let min_count = ty::vtable_min_entries(tcx, principal);
+                        let min_count = ty::vtable_min_entries(
+                            tcx,
+                            principal.map(|principal| {
+                                tcx.instantiate_bound_regions_with_erased(principal)
+                            }),
+                        );
                         Ty::new_imm_ref(
                             tcx,
                             tcx.lifetimes.re_static,
diff --git a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs
index cbc02097d82..568e504b940 100644
--- a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs
+++ b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs
@@ -4,7 +4,7 @@ use crate::ty::{self, ExistentialPredicateStableCmpExt, TyCtxt};
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Given a `def_id` of a trait or impl method, compute whether that method needs to
-    /// have an RPITIT shim applied to it for it to be object safe. If so, return the
+    /// have an RPITIT shim applied to it for it to be dyn compatible. If so, return the
     /// `def_id` of the RPITIT, and also the args of trait method that returns the RPITIT.
     ///
     /// NOTE that these args are not, in general, the same as than the RPITIT's args. They
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 455bd16ff8c..6c9e0e7c0eb 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -7,7 +7,7 @@ use rustc_type_ir::elaborate;
 use crate::mir::interpret::{
     AllocId, AllocInit, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range,
 };
-use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
+use crate::ty::{self, Instance, TraitRef, Ty, TyCtxt};
 
 #[derive(Clone, Copy, PartialEq, HashStable)]
 pub enum VtblEntry<'tcx> {
@@ -22,7 +22,7 @@ pub enum VtblEntry<'tcx> {
     /// dispatchable associated function
     Method(Instance<'tcx>),
     /// pointer to a separate supertrait vtable, can be used by trait upcasting coercion
-    TraitVPtr(PolyTraitRef<'tcx>),
+    TraitVPtr(TraitRef<'tcx>),
 }
 
 impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
@@ -59,7 +59,7 @@ pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;
 // function is an accurate approximation. We verify this when actually computing the vtable below.
 pub(crate) fn vtable_min_entries<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+    trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
 ) -> usize {
     let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len();
     let Some(trait_ref) = trait_ref else {
@@ -67,7 +67,7 @@ pub(crate) fn vtable_min_entries<'tcx>(
     };
 
     // This includes self in supertraits.
-    for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id()) {
+    for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id) {
         count += tcx.own_existential_vtable_entries(def_id).len();
     }
 
@@ -83,7 +83,7 @@ pub(crate) fn vtable_min_entries<'tcx>(
 /// initial contents.)
 pub(super) fn vtable_allocation_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
-    key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
+    key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>),
 ) -> AllocId {
     let (ty, poly_trait_ref) = key;
 
@@ -118,7 +118,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
 
     for (idx, entry) in vtable_entries.iter().enumerate() {
         let idx: u64 = u64::try_from(idx).unwrap();
-        let scalar = match entry {
+        let scalar = match *entry {
             VtblEntry::MetadataDropInPlace => {
                 if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
                     let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
@@ -134,13 +134,12 @@ pub(super) fn vtable_allocation_provider<'tcx>(
             VtblEntry::Vacant => continue,
             VtblEntry::Method(instance) => {
                 // Prepare the fn ptr we write into the vtable.
-                let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT);
+                let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
                 let fn_ptr = Pointer::from(fn_alloc_id);
                 Scalar::from_pointer(fn_ptr, &tcx)
             }
             VtblEntry::TraitVPtr(trait_ref) => {
-                let super_trait_ref = trait_ref
-                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+                let super_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref);
                 let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref)));
                 let vptr = Pointer::from(supertrait_alloc_id);
                 Scalar::from_pointer(vptr, &tcx)
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index b99336c2c85..7dda68b8393 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -1,4 +1,4 @@
-// These functions are used by macro expansion for bug! and span_bug!
+// These functions are used by macro expansion for `bug!` and `span_bug!`.
 
 use std::fmt;
 use std::panic::{Location, panic_any};
@@ -8,15 +8,15 @@ use rustc_span::Span;
 
 use crate::ty::{TyCtxt, tls};
 
+// This wrapper makes for more compact code at callsites than calling `opt_span_buf_fmt` directly.
 #[cold]
 #[inline(never)]
 #[track_caller]
 pub fn bug_fmt(args: fmt::Arguments<'_>) -> ! {
-    // this wrapper mostly exists so I don't have to write a fully
-    // qualified path of None::<Span> inside the bug!() macro definition
     opt_span_bug_fmt(None::<Span>, args, Location::caller());
 }
 
+// This wrapper makes for more compact code at callsites than calling `opt_span_buf_fmt` directly.
 #[cold]
 #[inline(never)]
 #[track_caller]
diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs
deleted file mode 100644
index 223b2b3bfe4..00000000000
--- a/compiler/rustc_middle/src/util/common.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#[cfg(test)]
-mod tests;
-
-pub fn to_readable_str(mut val: usize) -> String {
-    let mut groups = vec![];
-    loop {
-        let group = val % 1000;
-
-        val /= 1000;
-
-        if val == 0 {
-            groups.push(group.to_string());
-            break;
-        } else {
-            groups.push(format!("{group:03}"));
-        }
-    }
-
-    groups.reverse();
-
-    groups.join("_")
-}
diff --git a/compiler/rustc_middle/src/util/common/tests.rs b/compiler/rustc_middle/src/util/common/tests.rs
deleted file mode 100644
index 9a9fb203c62..00000000000
--- a/compiler/rustc_middle/src/util/common/tests.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use super::*;
-
-#[test]
-fn test_to_readable_str() {
-    assert_eq!("0", to_readable_str(0));
-    assert_eq!("1", to_readable_str(1));
-    assert_eq!("99", to_readable_str(99));
-    assert_eq!("999", to_readable_str(999));
-    assert_eq!("1_000", to_readable_str(1_000));
-    assert_eq!("1_001", to_readable_str(1_001));
-    assert_eq!("999_999", to_readable_str(999_999));
-    assert_eq!("1_000_000", to_readable_str(1_000_000));
-    assert_eq!("1_234_567", to_readable_str(1_234_567));
-}
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
deleted file mode 100644
index 0fdd3520738..00000000000
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use rustc_span::def_id::DefId;
-use rustc_span::source_map::Spanned;
-use tracing::debug;
-
-use crate::mir::*;
-use crate::ty::{self, GenericArgsRef, TyCtxt};
-
-/// Checks if the specified `local` is used as the `self` parameter of a method call
-/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
-/// returned.
-pub fn find_self_call<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    local: Local,
-    block: BasicBlock,
-) -> Option<(DefId, GenericArgsRef<'tcx>)> {
-    debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
-    if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
-        &body[block].terminator
-        && let Operand::Constant(box ConstOperand { const_, .. }) = func
-        && let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
-        && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
-            tcx.opt_associated_item(def_id)
-        && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
-            **args
-    {
-        if self_place.as_local() == Some(local) {
-            return Some((def_id, fn_args));
-        }
-
-        // Handle the case where `self_place` gets reborrowed.
-        // This happens when the receiver is `&T`.
-        for stmt in &body[block].statements {
-            if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
-                && let Some(reborrow_local) = place.as_local()
-                && self_place.as_local() == Some(reborrow_local)
-                && let Rvalue::Ref(_, _, deref_place) = rvalue
-                && let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
-                    deref_place.as_ref()
-                && deref_local == local
-            {
-                return Some((def_id, fn_args));
-            }
-        }
-    }
-    None
-}
diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs
index 097a868191c..8c875007b7f 100644
--- a/compiler/rustc_middle/src/util/mod.rs
+++ b/compiler/rustc_middle/src/util/mod.rs
@@ -1,8 +1,4 @@
 pub mod bug;
-pub mod common;
-pub mod find_self_call;
-
-pub use find_self_call::find_self_call;
 
 #[derive(Default, Copy, Clone)]
 pub struct Providers {
diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs
index ca2e1dd7a1a..bfc16816e2e 100644
--- a/compiler/rustc_mir_build/src/builder/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs
@@ -6,7 +6,7 @@
 //! present, and if so we branch off into this module, which implements the attribute by
 //! implementing a custom lowering from THIR to MIR.
 //!
-//! The result of this lowering is returned "normally" from the `build_mir` hook, with the only
+//! The result of this lowering is returned "normally" from `build_mir`, with the only
 //! notable difference being that the `injected` field in the body is set. Various components of the
 //! MIR pipeline, like borrowck and the pass manager will then consult this field (via
 //! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index 9fa431f7d5f..93fb9873e80 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -20,7 +20,6 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
-use rustc_middle::query::TyCtxtAt;
 use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
@@ -45,9 +44,9 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
         .collect()
 }
 
-/// Construct the MIR for a given `DefId`.
-pub(crate) fn build_mir<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
-    let tcx = tcx.tcx;
+/// Create the MIR for a given `DefId`, including unreachable code. Do not call
+/// this directly; instead use the cached version via `mir_built`.
+pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
     tcx.ensure_with_value().thir_abstract_const(def);
     if let Err(e) = tcx.check_match(def) {
         return construct_error(tcx, def, e);
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 8e786733ee0..fa5db32d913 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -14,11 +14,11 @@
 // The `builder` module used to be named `build`, but that was causing GitHub's
 // "Go to file" feature to silently ignore all files in the module, probably
 // because it assumes that "build" is a build-output directory. See #134365.
-mod builder;
+pub mod builder;
 mod check_tail_calls;
 mod check_unsafety;
 mod errors;
-mod thir;
+pub mod thir;
 
 use rustc_middle::util::Providers;
 
@@ -27,12 +27,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 pub fn provide(providers: &mut Providers) {
     providers.check_match = thir::pattern::check_match;
     providers.lit_to_const = thir::constant::lit_to_const;
-    providers.hooks.build_mir = builder::build_mir;
     providers.closure_saved_names_of_captured_variables =
         builder::closure_saved_names_of_captured_variables;
     providers.check_unsafety = check_unsafety::check_unsafety;
     providers.check_tail_calls = check_tail_calls::check_tail_calls;
     providers.thir_body = thir::cx::thir_body;
-    providers.hooks.thir_tree = thir::print::thir_tree;
-    providers.hooks.thir_flat = thir::print::thir_flat;
 }
diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs
index ca26cc13b5e..c7c88801d4d 100644
--- a/compiler/rustc_mir_build/src/thir/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/mod.rs
@@ -7,5 +7,5 @@
 pub(crate) mod constant;
 pub(crate) mod cx;
 pub(crate) mod pattern;
-pub(crate) mod print;
+pub mod print;
 mod util;
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 2bcdb67c58a..228a64c2c70 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -1,12 +1,13 @@
 use std::fmt::{self, Write};
 
-use rustc_middle::query::TyCtxtAt;
 use rustc_middle::thir::*;
 use rustc_middle::ty;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::LocalDefId;
 
-pub(crate) fn thir_tree(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
-    match super::cx::thir_body(*tcx, owner_def) {
+/// Create a THIR tree for debugging.
+pub fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
+    match super::cx::thir_body(tcx, owner_def) {
         Ok((thir, _)) => {
             let thir = thir.steal();
             let mut printer = ThirPrinter::new(&thir);
@@ -17,8 +18,9 @@ pub(crate) fn thir_tree(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
     }
 }
 
-pub(crate) fn thir_flat(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
-    match super::cx::thir_body(*tcx, owner_def) {
+/// Create a list-like THIR representation for debugging.
+pub fn thir_flat(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
+    match super::cx::thir_body(tcx, owner_def) {
         Ok((thir, _)) => format!("{:#?}", thir.steal()),
         Err(_) => "error".into(),
     }
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index d7e22c12394..ca5564e447a 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,11 +1,10 @@
-use rustc_hir::lang_items::LangItem;
 use rustc_index::IndexVec;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_session::Session;
-use tracing::{debug, trace};
+
+use crate::check_pointers::{BorrowCheckMode, PointerCheck, check_pointers};
 
 pub(super) struct CheckAlignment;
 
@@ -19,46 +18,19 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        // This pass emits new panics. If for whatever reason we do not have a panic
-        // implementation, running this pass may cause otherwise-valid code to not compile.
-        if tcx.lang_items().get(LangItem::PanicImpl).is_none() {
-            return;
-        }
-
-        let typing_env = body.typing_env(tcx);
-        let basic_blocks = body.basic_blocks.as_mut();
-        let local_decls = &mut body.local_decls;
-
-        // This pass inserts new blocks. Each insertion changes the Location for all
-        // statements/blocks after. Iterating or visiting the MIR in order would require updating
-        // our current location after every insertion. By iterating backwards, we dodge this issue:
-        // The only Locations that an insertion changes have already been handled.
-        for block in (0..basic_blocks.len()).rev() {
-            let block = block.into();
-            for statement_index in (0..basic_blocks[block].statements.len()).rev() {
-                let location = Location { block, statement_index };
-                let statement = &basic_blocks[block].statements[statement_index];
-                let source_info = statement.source_info;
-
-                let mut finder =
-                    PointerFinder { tcx, local_decls, typing_env, pointers: Vec::new() };
-                finder.visit_statement(statement, location);
-
-                for (local, ty) in finder.pointers {
-                    debug!("Inserting alignment check for {:?}", ty);
-                    let new_block = split_block(basic_blocks, location);
-                    insert_alignment_check(
-                        tcx,
-                        local_decls,
-                        &mut basic_blocks[block],
-                        local,
-                        ty,
-                        source_info,
-                        new_block,
-                    );
-                }
-            }
-        }
+        // Skip trivially aligned place types.
+        let excluded_pointees = [tcx.types.bool, tcx.types.i8, tcx.types.u8];
+
+        // We have to exclude borrows here: in `&x.field`, the exact
+        // requirement is that the final reference must be aligned, but
+        // `check_pointers` would check that `x` is aligned, which would be wrong.
+        check_pointers(
+            tcx,
+            body,
+            &excluded_pointees,
+            insert_alignment_check,
+            BorrowCheckMode::ExcludeBorrows,
+        );
     }
 
     fn is_required(&self) -> bool {
@@ -66,119 +38,33 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
     }
 }
 
-struct PointerFinder<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    local_decls: &'a mut LocalDecls<'tcx>,
-    typing_env: ty::TypingEnv<'tcx>,
-    pointers: Vec<(Place<'tcx>, Ty<'tcx>)>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> {
-    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
-        // We want to only check reads and writes to Places, so we specifically exclude
-        // Borrow and RawBorrow.
-        match context {
-            PlaceContext::MutatingUse(
-                MutatingUseContext::Store
-                | MutatingUseContext::AsmOutput
-                | MutatingUseContext::Call
-                | MutatingUseContext::Yield
-                | MutatingUseContext::Drop,
-            ) => {}
-            PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
-            ) => {}
-            _ => {
-                return;
-            }
-        }
-
-        if !place.is_indirect() {
-            return;
-        }
-
-        // Since Deref projections must come first and only once, the pointer for an indirect place
-        // is the Local that the Place is based on.
-        let pointer = Place::from(place.local);
-        let pointer_ty = self.local_decls[place.local].ty;
-
-        // We only want to check places based on unsafe pointers
-        if !pointer_ty.is_unsafe_ptr() {
-            trace!("Indirect, but not based on an unsafe ptr, not checking {:?}", place);
-            return;
-        }
-
-        let pointee_ty =
-            pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer");
-        // Ideally we'd support this in the future, but for now we are limited to sized types.
-        if !pointee_ty.is_sized(self.tcx, self.typing_env) {
-            debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty);
-            return;
-        }
-
-        // Try to detect types we are sure have an alignment of 1 and skip the check
-        // We don't need to look for str and slices, we already rejected unsized types above
-        let element_ty = match pointee_ty.kind() {
-            ty::Array(ty, _) => *ty,
-            _ => pointee_ty,
-        };
-        if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8].contains(&element_ty) {
-            debug!("Trivially aligned place type: {:?}", pointee_ty);
-            return;
-        }
-
-        // Ensure that this place is based on an aligned pointer.
-        self.pointers.push((pointer, pointee_ty));
-
-        self.super_place(place, context, location);
-    }
-}
-
-fn split_block(
-    basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>,
-    location: Location,
-) -> BasicBlock {
-    let block_data = &mut basic_blocks[location.block];
-
-    // Drain every statement after this one and move the current terminator to a new basic block
-    let new_block = BasicBlockData {
-        statements: block_data.statements.split_off(location.statement_index),
-        terminator: block_data.terminator.take(),
-        is_cleanup: block_data.is_cleanup,
-    };
-
-    basic_blocks.push(new_block)
-}
-
+/// Inserts the actual alignment check's logic. Returns a
+/// [AssertKind::MisalignedPointerDereference] on failure.
 fn insert_alignment_check<'tcx>(
     tcx: TyCtxt<'tcx>,
-    local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
-    block_data: &mut BasicBlockData<'tcx>,
     pointer: Place<'tcx>,
     pointee_ty: Ty<'tcx>,
+    local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
+    stmts: &mut Vec<Statement<'tcx>>,
     source_info: SourceInfo,
-    new_block: BasicBlock,
-) {
-    // Cast the pointer to a *const ()
+) -> PointerCheck<'tcx> {
+    // Cast the pointer to a *const ().
     let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit);
     let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr);
     let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into();
-    block_data
-        .statements
+    stmts
         .push(Statement { source_info, kind: StatementKind::Assign(Box::new((thin_ptr, rvalue))) });
 
-    // Transmute the pointer to a usize (equivalent to `ptr.addr()`)
+    // Transmute the pointer to a usize (equivalent to `ptr.addr()`).
     let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize);
     let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
-    block_data
-        .statements
-        .push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) });
+    stmts.push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) });
 
     // Get the alignment of the pointee
     let alignment =
         local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
     let rvalue = Rvalue::NullaryOp(NullOp::AlignOf, pointee_ty);
-    block_data.statements.push(Statement {
+    stmts.push(Statement {
         source_info,
         kind: StatementKind::Assign(Box::new((alignment, rvalue))),
     });
@@ -191,7 +77,7 @@ fn insert_alignment_check<'tcx>(
         user_ty: None,
         const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize),
     }));
-    block_data.statements.push(Statement {
+    stmts.push(Statement {
         source_info,
         kind: StatementKind::Assign(Box::new((
             alignment_mask,
@@ -202,7 +88,7 @@ fn insert_alignment_check<'tcx>(
     // BitAnd the alignment mask with the pointer
     let alignment_bits =
         local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
-    block_data.statements.push(Statement {
+    stmts.push(Statement {
         source_info,
         kind: StatementKind::Assign(Box::new((
             alignment_bits,
@@ -220,7 +106,7 @@ fn insert_alignment_check<'tcx>(
         user_ty: None,
         const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize),
     }));
-    block_data.statements.push(Statement {
+    stmts.push(Statement {
         source_info,
         kind: StatementKind::Assign(Box::new((
             is_ok,
@@ -228,21 +114,13 @@ fn insert_alignment_check<'tcx>(
         ))),
     });
 
-    // Set this block's terminator to our assert, continuing to new_block if we pass
-    block_data.terminator = Some(Terminator {
-        source_info,
-        kind: TerminatorKind::Assert {
-            cond: Operand::Copy(is_ok),
-            expected: true,
-            target: new_block,
-            msg: Box::new(AssertKind::MisalignedPointerDereference {
-                required: Operand::Copy(alignment),
-                found: Operand::Copy(addr),
-            }),
-            // This calls panic_misaligned_pointer_dereference, which is #[rustc_nounwind].
-            // We never want to insert an unwind into unsafe code, because unwinding could
-            // make a failing UB check turn into much worse UB when we start unwinding.
-            unwind: UnwindAction::Unreachable,
-        },
-    });
+    // Emit a check that asserts on the alignment and otherwise triggers a
+    // AssertKind::MisalignedPointerDereference.
+    PointerCheck {
+        cond: Operand::Copy(is_ok),
+        assert_kind: Box::new(AssertKind::MisalignedPointerDereference {
+            required: Operand::Copy(alignment),
+            found: Operand::Copy(addr),
+        }),
+    }
 }
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index 7968b666dff..3affe4abbfa 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
                 // the `self` parameter of a method call (as the terminator of our current
                 // BasicBlock). If so, we emit a more specific lint.
                 let method_did = self.target_local.and_then(|target_local| {
-                    rustc_middle::util::find_self_call(self.tcx, self.body, target_local, loc.block)
+                    find_self_call(self.tcx, self.body, target_local, loc.block)
                 });
                 let lint_loc =
                     if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs
new file mode 100644
index 00000000000..0b6c0ceaac1
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/check_null.rs
@@ -0,0 +1,110 @@
+use rustc_index::IndexVec;
+use rustc_middle::mir::interpret::Scalar;
+use rustc_middle::mir::*;
+use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_session::Session;
+
+use crate::check_pointers::{BorrowCheckMode, PointerCheck, check_pointers};
+
+pub(super) struct CheckNull;
+
+impl<'tcx> crate::MirPass<'tcx> for CheckNull {
+    fn is_enabled(&self, sess: &Session) -> bool {
+        sess.ub_checks()
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        check_pointers(tcx, body, &[], insert_null_check, BorrowCheckMode::IncludeBorrows);
+    }
+
+    fn is_required(&self) -> bool {
+        true
+    }
+}
+
+fn insert_null_check<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    pointer: Place<'tcx>,
+    pointee_ty: Ty<'tcx>,
+    local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
+    stmts: &mut Vec<Statement<'tcx>>,
+    source_info: SourceInfo,
+) -> PointerCheck<'tcx> {
+    // Cast the pointer to a *const ().
+    let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit);
+    let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr);
+    let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into();
+    stmts
+        .push(Statement { source_info, kind: StatementKind::Assign(Box::new((thin_ptr, rvalue))) });
+
+    // Transmute the pointer to a usize (equivalent to `ptr.addr()`).
+    let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize);
+    let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
+    stmts.push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) });
+
+    // Get size of the pointee (zero-sized reads and writes are allowed).
+    let rvalue = Rvalue::NullaryOp(NullOp::SizeOf, pointee_ty);
+    let sizeof_pointee =
+        local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
+    stmts.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((sizeof_pointee, rvalue))),
+    });
+
+    // Check that the pointee is not a ZST.
+    let zero = Operand::Constant(Box::new(ConstOperand {
+        span: source_info.span,
+        user_ty: None,
+        const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize),
+    }));
+    let is_pointee_no_zst =
+        local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
+    stmts.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            is_pointee_no_zst,
+            Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Copy(sizeof_pointee), zero.clone()))),
+        ))),
+    });
+
+    // Check whether the pointer is null.
+    let is_null = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
+    stmts.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            is_null,
+            Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(addr), zero))),
+        ))),
+    });
+
+    // We want to throw an exception if the pointer is null and doesn't point to a ZST.
+    let should_throw_exception =
+        local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
+    stmts.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            should_throw_exception,
+            Rvalue::BinaryOp(
+                BinOp::BitAnd,
+                Box::new((Operand::Copy(is_null), Operand::Copy(is_pointee_no_zst))),
+            ),
+        ))),
+    });
+
+    // The final condition whether this pointer usage is ok or not.
+    let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
+    stmts.push(Statement {
+        source_info,
+        kind: StatementKind::Assign(Box::new((
+            is_ok,
+            Rvalue::UnaryOp(UnOp::Not, Operand::Copy(should_throw_exception)),
+        ))),
+    });
+
+    // Emit a PointerCheck that asserts on the condition and otherwise triggers
+    // a AssertKind::NullPointerDereference.
+    PointerCheck {
+        cond: Operand::Copy(is_ok),
+        assert_kind: Box::new(AssertKind::NullPointerDereference),
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/check_pointers.rs b/compiler/rustc_mir_transform/src/check_pointers.rs
new file mode 100644
index 00000000000..72460542f87
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/check_pointers.rs
@@ -0,0 +1,234 @@
+use rustc_hir::lang_items::LangItem;
+use rustc_index::IndexVec;
+use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::*;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use tracing::{debug, trace};
+
+/// Details of a pointer check, the condition on which we decide whether to
+/// fail the assert and an [AssertKind] that defines the behavior on failure.
+pub(crate) struct PointerCheck<'tcx> {
+    pub(crate) cond: Operand<'tcx>,
+    pub(crate) assert_kind: Box<AssertKind<Operand<'tcx>>>,
+}
+
+/// Indicates whether we insert the checks for borrow places of a raw pointer.
+/// Concretely places with [MutatingUseContext::Borrow] or
+/// [NonMutatingUseContext::SharedBorrow].
+#[derive(Copy, Clone)]
+pub(crate) enum BorrowCheckMode {
+    IncludeBorrows,
+    ExcludeBorrows,
+}
+
+/// Utility for adding a check for read/write on every sized, raw pointer.
+///
+/// Visits every read/write access to a [Sized], raw pointer and inserts a
+/// new basic block directly before the pointer access. (Read/write accesses
+/// are determined by the `PlaceContext` of the MIR visitor.) Then calls
+/// `on_finding` to insert the actual logic for a pointer check (e.g. check for
+/// alignment). A check can choose to be inserted for (mutable) borrows of
+/// raw pointers via the `borrow_check_mode` parameter.
+///
+/// This utility takes care of the right order of blocks, the only thing a
+/// caller must do in `on_finding` is:
+/// - Append [Statement]s to `stmts`.
+/// - Append [LocalDecl]s to `local_decls`.
+/// - Return a [PointerCheck] that contains the condition and an [AssertKind].
+///   The AssertKind must be a panic with `#[rustc_nounwind]`. The condition
+///   should always return the boolean `is_ok`, so evaluate to true in case of
+///   success and fail the check otherwise.
+/// This utility will insert a terminator block that asserts on the condition
+/// and panics on failure.
+pub(crate) fn check_pointers<'a, 'tcx, F>(
+    tcx: TyCtxt<'tcx>,
+    body: &mut Body<'tcx>,
+    excluded_pointees: &'a [Ty<'tcx>],
+    on_finding: F,
+    borrow_check_mode: BorrowCheckMode,
+) where
+    F: Fn(
+        /* tcx: */ TyCtxt<'tcx>,
+        /* pointer: */ Place<'tcx>,
+        /* pointee_ty: */ Ty<'tcx>,
+        /* local_decls: */ &mut IndexVec<Local, LocalDecl<'tcx>>,
+        /* stmts: */ &mut Vec<Statement<'tcx>>,
+        /* source_info: */ SourceInfo,
+    ) -> PointerCheck<'tcx>,
+{
+    // This pass emits new panics. If for whatever reason we do not have a panic
+    // implementation, running this pass may cause otherwise-valid code to not compile.
+    if tcx.lang_items().get(LangItem::PanicImpl).is_none() {
+        return;
+    }
+
+    let typing_env = body.typing_env(tcx);
+    let basic_blocks = body.basic_blocks.as_mut();
+    let local_decls = &mut body.local_decls;
+
+    // This operation inserts new blocks. Each insertion changes the Location for all
+    // statements/blocks after. Iterating or visiting the MIR in order would require updating
+    // our current location after every insertion. By iterating backwards, we dodge this issue:
+    // The only Locations that an insertion changes have already been handled.
+    for block in (0..basic_blocks.len()).rev() {
+        let block = block.into();
+        for statement_index in (0..basic_blocks[block].statements.len()).rev() {
+            let location = Location { block, statement_index };
+            let statement = &basic_blocks[block].statements[statement_index];
+            let source_info = statement.source_info;
+
+            let mut finder = PointerFinder::new(
+                tcx,
+                local_decls,
+                typing_env,
+                excluded_pointees,
+                borrow_check_mode,
+            );
+            finder.visit_statement(statement, location);
+
+            for (local, ty) in finder.into_found_pointers() {
+                debug!("Inserting check for {:?}", ty);
+                let new_block = split_block(basic_blocks, location);
+
+                // Invoke `on_finding` which appends to `local_decls` and the
+                // blocks statements. It returns information about the assert
+                // we're performing in the Terminator.
+                let block_data = &mut basic_blocks[block];
+                let pointer_check = on_finding(
+                    tcx,
+                    local,
+                    ty,
+                    local_decls,
+                    &mut block_data.statements,
+                    source_info,
+                );
+                block_data.terminator = Some(Terminator {
+                    source_info,
+                    kind: TerminatorKind::Assert {
+                        cond: pointer_check.cond,
+                        expected: true,
+                        target: new_block,
+                        msg: pointer_check.assert_kind,
+                        // This calls a panic function associated with the pointer check, which
+                        // is #[rustc_nounwind]. We never want to insert an unwind into unsafe
+                        // code, because unwinding could make a failing UB check turn into much
+                        // worse UB when we start unwinding.
+                        unwind: UnwindAction::Unreachable,
+                    },
+                });
+            }
+        }
+    }
+}
+
+struct PointerFinder<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    local_decls: &'a mut LocalDecls<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
+    pointers: Vec<(Place<'tcx>, Ty<'tcx>)>,
+    excluded_pointees: &'a [Ty<'tcx>],
+    borrow_check_mode: BorrowCheckMode,
+}
+
+impl<'a, 'tcx> PointerFinder<'a, 'tcx> {
+    fn new(
+        tcx: TyCtxt<'tcx>,
+        local_decls: &'a mut LocalDecls<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+        excluded_pointees: &'a [Ty<'tcx>],
+        borrow_check_mode: BorrowCheckMode,
+    ) -> Self {
+        PointerFinder {
+            tcx,
+            local_decls,
+            typing_env,
+            excluded_pointees,
+            pointers: Vec::new(),
+            borrow_check_mode,
+        }
+    }
+
+    fn into_found_pointers(self) -> Vec<(Place<'tcx>, Ty<'tcx>)> {
+        self.pointers
+    }
+
+    /// Whether or not we should visit a [Place] with [PlaceContext].
+    ///
+    /// We generally only visit Reads/Writes to a place and only Borrows if
+    /// requested.
+    fn should_visit_place(&self, context: PlaceContext) -> bool {
+        match context {
+            PlaceContext::MutatingUse(
+                MutatingUseContext::Store
+                | MutatingUseContext::Call
+                | MutatingUseContext::Yield
+                | MutatingUseContext::Drop,
+            ) => true,
+            PlaceContext::NonMutatingUse(
+                NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
+            ) => true,
+            PlaceContext::MutatingUse(MutatingUseContext::Borrow)
+            | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) => {
+                matches!(self.borrow_check_mode, BorrowCheckMode::IncludeBorrows)
+            }
+            _ => false,
+        }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> {
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
+        if !self.should_visit_place(context) || !place.is_indirect() {
+            return;
+        }
+
+        // Since Deref projections must come first and only once, the pointer for an indirect place
+        // is the Local that the Place is based on.
+        let pointer = Place::from(place.local);
+        let pointer_ty = self.local_decls[place.local].ty;
+
+        // We only want to check places based on raw pointers
+        if !pointer_ty.is_unsafe_ptr() {
+            trace!("Indirect, but not based on an raw ptr, not checking {:?}", place);
+            return;
+        }
+
+        let pointee_ty =
+            pointer_ty.builtin_deref(true).expect("no builtin_deref for an raw pointer");
+        // Ideally we'd support this in the future, but for now we are limited to sized types.
+        if !pointee_ty.is_sized(self.tcx, self.typing_env) {
+            trace!("Raw pointer, but pointee is not known to be sized: {:?}", pointer_ty);
+            return;
+        }
+
+        // We don't need to look for slices, we already rejected unsized types above.
+        let element_ty = match pointee_ty.kind() {
+            ty::Array(ty, _) => *ty,
+            _ => pointee_ty,
+        };
+        if self.excluded_pointees.contains(&element_ty) {
+            trace!("Skipping pointer for type: {:?}", pointee_ty);
+            return;
+        }
+
+        self.pointers.push((pointer, pointee_ty));
+
+        self.super_place(place, context, location);
+    }
+}
+
+fn split_block(
+    basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>,
+    location: Location,
+) -> BasicBlock {
+    let block_data = &mut basic_blocks[location.block];
+
+    // Drain every statement after this one and move the current terminator to a new basic block.
+    let new_block = BasicBlockData {
+        statements: block_data.statements.split_off(location.statement_index),
+        terminator: block_data.terminator.take(),
+        is_cleanup: block_data.is_cleanup,
+    };
+
+    basic_blocks.push(new_block)
+}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 2dc55e3614e..4af9a111bdf 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -33,6 +33,7 @@ use rustc_middle::mir::{
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_middle::util::Providers;
 use rustc_middle::{bug, query, span_bug};
+use rustc_mir_build::builder::build_mir;
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, sym};
 use tracing::debug;
@@ -44,6 +45,7 @@ use std::sync::LazyLock;
 
 use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel};
 
+mod check_pointers;
 mod cost_checker;
 mod cross_crate_inline;
 mod deduce_param_attrs;
@@ -118,6 +120,7 @@ declare_passes! {
     mod check_call_recursion : CheckCallRecursion, CheckDropRecursion;
     mod check_alignment : CheckAlignment;
     mod check_const_item_mutation : CheckConstItemMutation;
+    mod check_null : CheckNull;
     mod check_packed_ref : CheckPackedRef;
     mod check_undefined_transmutes : CheckUndefinedTransmutes;
     // This pass is public to allow external drivers to perform MIR cleanup
@@ -368,7 +371,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
 }
 
 fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
-    let mut body = tcx.build_mir(def);
+    let mut body = build_mir(tcx, def);
 
     pass_manager::dump_mir_for_phase_change(tcx, &body);
 
@@ -642,6 +645,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         &[
             // Add some UB checks before any UB gets optimized away.
             &check_alignment::CheckAlignment,
+            &check_null::CheckNull,
             // Before inlining: trim down MIR with passes to reduce inlining work.
 
             // Has to be done before inlining, otherwise actual call will be almost always inlined.
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 9bdaeb015cd..5462105e5e8 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 rustc_abi = { path = "../rustc_abi" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
@@ -15,6 +16,7 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
+rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_target = { path = "../rustc_target" }
 serde = "1"
 serde_json = "1"
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index d53848f7461..246faed50e3 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -257,7 +257,7 @@ struct SharedState<'tcx> {
 
 pub(crate) struct UsageMap<'tcx> {
     // Maps every mono item to the mono items used by it.
-    used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
+    pub used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
 
     // Maps every mono item to the mono items that use it.
     user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
@@ -814,6 +814,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 mir::AssertKind::MisalignedPointerDereference { .. } => {
                     push_mono_lang_item(self, LangItem::PanicMisalignedPointerDereference);
                 }
+                mir::AssertKind::NullPointerDereference => {
+                    push_mono_lang_item(self, LangItem::PanicNullPointerDereference);
+                }
                 _ => {
                     push_mono_lang_item(self, msg.panic_function());
                 }
@@ -1138,11 +1141,12 @@ fn create_mono_items_for_vtable_methods<'tcx>(
         bug!("create_mono_items_for_vtable_methods: {trait_ty:?} not a trait type");
     };
     if let Some(principal) = trait_ty.principal() {
-        let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
-        assert!(!poly_trait_ref.has_escaping_bound_vars());
+        let trait_ref =
+            tcx.instantiate_bound_regions_with_erased(principal.with_self_ty(tcx, impl_ty));
+        assert!(!trait_ref.has_escaping_bound_vars());
 
         // Walk all methods of the trait, including those of its supertraits
-        let entries = tcx.vtable_entries(poly_trait_ref);
+        let entries = tcx.vtable_entries(trait_ref);
         debug!(?entries);
         let methods = entries
             .iter()
@@ -1197,7 +1201,12 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
             }
         }
         GlobalAlloc::VTable(ty, dyn_ty) => {
-            let alloc_id = tcx.vtable_allocation((ty, dyn_ty.principal()));
+            let alloc_id = tcx.vtable_allocation((
+                ty,
+                dyn_ty
+                    .principal()
+                    .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
+            ));
             collect_alloc(tcx, alloc_id, output)
         }
     }
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index e08c348a64d..c985ea04278 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -92,6 +92,8 @@
 //! source-level module, functions from the same module will be available for
 //! inlining, even when they are not marked `#[inline]`.
 
+mod autodiff;
+
 use std::cmp;
 use std::collections::hash_map::Entry;
 use std::fs::{self, File};
@@ -251,7 +253,17 @@ where
             can_export_generics,
             always_export_generics,
         );
-        if visibility == Visibility::Hidden && can_be_internalized {
+
+        // We can't differentiate something that got inlined.
+        let autodiff_active = cfg!(llvm_enzyme)
+            && cx
+                .tcx
+                .codegen_fn_attrs(mono_item.def_id())
+                .autodiff_item
+                .as_ref()
+                .is_some_and(|ad| ad.is_active());
+
+        if !autodiff_active && visibility == Visibility::Hidden && can_be_internalized {
             internalization_candidates.insert(mono_item);
         }
         let size_estimate = mono_item.size_estimate(cx.tcx);
@@ -1176,6 +1188,18 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio
         })
         .collect();
 
+    let autodiff_mono_items: Vec<_> = items
+        .iter()
+        .filter_map(|item| match *item {
+            MonoItem::Fn(ref instance) => Some((item, instance)),
+            _ => None,
+        })
+        .collect();
+
+    let autodiff_items =
+        autodiff::find_autodiff_source_functions(tcx, &usage_map, autodiff_mono_items);
+    let autodiff_items = tcx.arena.alloc_from_iter(autodiff_items);
+
     // Output monomorphization stats per def_id
     if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
         if let Err(err) =
@@ -1236,7 +1260,11 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio
         }
     }
 
-    MonoItemPartitions { all_mono_items: tcx.arena.alloc(mono_items), codegen_units }
+    MonoItemPartitions {
+        all_mono_items: tcx.arena.alloc(mono_items),
+        codegen_units,
+        autodiff_items,
+    }
 }
 
 /// Outputs stats about instantiation counts and estimated size, per `MonoItem`'s
diff --git a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
new file mode 100644
index 00000000000..bce31bf0748
--- /dev/null
+++ b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
@@ -0,0 +1,121 @@
+use rustc_ast::expand::autodiff_attrs::{AutoDiffItem, DiffActivity};
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_middle::bug;
+use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_symbol_mangling::symbol_name_for_instance_in_crate;
+use tracing::{debug, trace};
+
+use crate::partitioning::UsageMap;
+
+fn adjust_activity_to_abi<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<DiffActivity>) {
+    if !matches!(fn_ty.kind(), ty::FnDef(..)) {
+        bug!("expected fn def for autodiff, got {:?}", fn_ty);
+    }
+    let fnc_binder: ty::Binder<'_, ty::FnSig<'_>> = fn_ty.fn_sig(tcx);
+
+    // If rustc compiles the unmodified primal, we know that this copy of the function
+    // also has correct lifetimes. We know that Enzyme won't free the shadow too early
+    // (or actually at all), so let's strip lifetimes when computing the layout.
+    let x = tcx.instantiate_bound_regions_with_erased(fnc_binder);
+    let mut new_activities = vec![];
+    let mut new_positions = vec![];
+    for (i, ty) in x.inputs().iter().enumerate() {
+        if let Some(inner_ty) = ty.builtin_deref(true) {
+            if ty.is_fn_ptr() {
+                // FIXME(ZuseZ4): add a nicer error, or just figure out how to support them,
+                // since Enzyme itself can handle them.
+                tcx.dcx().err("function pointers are currently not supported in autodiff");
+            }
+            if inner_ty.is_slice() {
+                // We know that the length will be passed as extra arg.
+                if !da.is_empty() {
+                    // We are looking at a slice. The length of that slice will become an
+                    // extra integer on llvm level. Integers are always const.
+                    // However, if the slice get's duplicated, we want to know to later check the
+                    // size. So we mark the new size argument as FakeActivitySize.
+                    let activity = match da[i] {
+                        DiffActivity::DualOnly
+                        | DiffActivity::Dual
+                        | DiffActivity::DuplicatedOnly
+                        | DiffActivity::Duplicated => DiffActivity::FakeActivitySize,
+                        DiffActivity::Const => DiffActivity::Const,
+                        _ => bug!("unexpected activity for ptr/ref"),
+                    };
+                    new_activities.push(activity);
+                    new_positions.push(i + 1);
+                }
+                continue;
+            }
+        }
+    }
+    // now add the extra activities coming from slices
+    // Reverse order to not invalidate the indices
+    for _ in 0..new_activities.len() {
+        let pos = new_positions.pop().unwrap();
+        let activity = new_activities.pop().unwrap();
+        da.insert(pos, activity);
+    }
+}
+
+pub(crate) fn find_autodiff_source_functions<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    usage_map: &UsageMap<'tcx>,
+    autodiff_mono_items: Vec<(&MonoItem<'tcx>, &Instance<'tcx>)>,
+) -> Vec<AutoDiffItem> {
+    let mut autodiff_items: Vec<AutoDiffItem> = vec![];
+    for (item, instance) in autodiff_mono_items {
+        let target_id = instance.def_id();
+        let cg_fn_attr = tcx.codegen_fn_attrs(target_id).autodiff_item.clone();
+        let Some(target_attrs) = cg_fn_attr else {
+            continue;
+        };
+        let mut input_activities: Vec<DiffActivity> = target_attrs.input_activity.clone();
+        if target_attrs.is_source() {
+            trace!("source found: {:?}", target_id);
+        }
+        if !target_attrs.apply_autodiff() {
+            continue;
+        }
+
+        let target_symbol = symbol_name_for_instance_in_crate(tcx, instance.clone(), LOCAL_CRATE);
+
+        let source =
+            usage_map.used_map.get(&item).unwrap().into_iter().find_map(|item| match *item {
+                MonoItem::Fn(ref instance_s) => {
+                    let source_id = instance_s.def_id();
+                    if let Some(ad) = &tcx.codegen_fn_attrs(source_id).autodiff_item
+                        && ad.is_active()
+                    {
+                        return Some(instance_s);
+                    }
+                    None
+                }
+                _ => None,
+            });
+        let inst = match source {
+            Some(source) => source,
+            None => continue,
+        };
+
+        debug!("source_id: {:?}", inst.def_id());
+        let fn_ty = inst.ty(tcx, ty::TypingEnv::fully_monomorphized());
+        assert!(fn_ty.is_fn());
+        adjust_activity_to_abi(tcx, fn_ty, &mut input_activities);
+        let symb = symbol_name_for_instance_in_crate(tcx, inst.clone(), LOCAL_CRATE);
+
+        let mut new_target_attrs = target_attrs.clone();
+        new_target_attrs.input_activity = input_activities;
+        let itm = new_target_attrs.into_item(symb, target_symbol);
+        autodiff_items.push(itm);
+    }
+
+    if !autodiff_items.is_empty() {
+        trace!("AUTODIFF ITEMS EXIST");
+        for item in &mut *autodiff_items {
+            trace!("{}", &item);
+        }
+    }
+
+    autodiff_items
+}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e19819a22b4..837da6e7724 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2471,6 +2471,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 }))),
                 terr,
                 false,
+                None,
             );
             diag.emit();
             self.abort.set(true);
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 75b62a40ff9..6d9c70177a4 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -5,10 +5,10 @@
 use rustc_ast::visit::BoundKind;
 use rustc_ast::{self as ast, NodeId, visit as ast_visit};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::thousands::format_with_underscores;
 use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::TyCtxt;
-use rustc_middle::util::common::to_readable_str;
 use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 
@@ -144,10 +144,10 @@ impl<'k> StatCollector<'k> {
                 "{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}",
                 prefix,
                 label,
-                to_readable_str(size),
+                format_with_underscores(size),
                 percent(size, total_size),
-                to_readable_str(node.stats.count),
-                to_readable_str(node.stats.size)
+                format_with_underscores(node.stats.count),
+                format_with_underscores(node.stats.size)
             );
             if !node.subnodes.is_empty() {
                 // We will soon sort, so the initial order does not matter.
@@ -163,9 +163,9 @@ impl<'k> StatCollector<'k> {
                         "{} - {:<18}{:>10} ({:4.1}%){:>14}",
                         prefix,
                         label,
-                        to_readable_str(size),
+                        format_with_underscores(size),
                         percent(size, total_size),
-                        to_readable_str(subnode.count),
+                        format_with_underscores(subnode.count),
                     );
                 }
             }
@@ -175,8 +175,8 @@ impl<'k> StatCollector<'k> {
             "{} {:<18}{:>10}        {:>14}",
             prefix,
             "Total",
-            to_readable_str(total_size),
-            to_readable_str(total_count),
+            format_with_underscores(total_size),
+            format_with_underscores(total_count),
         );
         eprintln!("{prefix}");
     }
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index f3c21992784..b4597ae2515 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -1,10 +1,9 @@
 use std::cmp;
 
 use rustc_abi::{Align, Size};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lock;
 use rustc_span::Symbol;
-use rustc_span::def_id::DefId;
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct VariantInfo {
@@ -71,29 +70,9 @@ pub struct TypeSizeInfo {
     pub variants: Vec<VariantInfo>,
 }
 
-pub struct VTableSizeInfo {
-    pub trait_name: String,
-
-    /// Number of entries in a vtable with the current algorithm
-    /// (i.e. with upcasting).
-    pub entries: usize,
-
-    /// Number of entries in a vtable, as-if we did not have trait upcasting.
-    pub entries_ignoring_upcasting: usize,
-
-    /// Number of entries in a vtable needed solely for upcasting
-    /// (i.e. `entries - entries_ignoring_upcasting`).
-    pub entries_for_upcasting: usize,
-
-    /// Cost of having upcasting in % relative to the number of entries without
-    /// upcasting (i.e. `entries_for_upcasting / entries_ignoring_upcasting * 100%`).
-    pub upcasting_cost_percent: f64,
-}
-
 #[derive(Default)]
 pub struct CodeStats {
     type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
-    vtable_sizes: Lock<FxHashMap<DefId, VTableSizeInfo>>,
 }
 
 impl CodeStats {
@@ -127,14 +106,6 @@ impl CodeStats {
         self.type_sizes.borrow_mut().insert(info);
     }
 
-    pub fn record_vtable_size(&self, trait_did: DefId, trait_name: &str, info: VTableSizeInfo) {
-        let prev = self.vtable_sizes.lock().insert(trait_did, info);
-        assert!(
-            prev.is_none(),
-            "size of vtable for `{trait_name}` ({trait_did:?}) is already recorded"
-        );
-    }
-
     pub fn print_type_sizes(&self) {
         let type_sizes = self.type_sizes.borrow();
         // We will soon sort, so the initial order does not matter.
@@ -238,33 +209,4 @@ impl CodeStats {
             }
         }
     }
-
-    pub fn print_vtable_sizes(&self, crate_name: Symbol) {
-        // We will soon sort, so the initial order does not matter.
-        #[allow(rustc::potential_query_instability)]
-        let mut infos =
-            std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>();
-
-        // Primary sort: cost % in reverse order (from largest to smallest)
-        // Secondary sort: trait_name
-        infos.sort_by(|a, b| {
-            a.upcasting_cost_percent
-                .total_cmp(&b.upcasting_cost_percent)
-                .reverse()
-                .then_with(|| a.trait_name.cmp(&b.trait_name))
-        });
-
-        for VTableSizeInfo {
-            trait_name,
-            entries,
-            entries_ignoring_upcasting,
-            entries_for_upcasting,
-            upcasting_cost_percent,
-        } in infos
-        {
-            println!(
-                r#"print-vtable-sizes {{ "crate_name": "{crate_name}", "trait_name": "{trait_name}", "entries": "{entries}", "entries_ignoring_upcasting": "{entries_ignoring_upcasting}", "entries_for_upcasting": "{entries_for_upcasting}", "upcasting_cost_percent": "{upcasting_cost_percent}" }}"#
-            );
-        }
-    }
 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 97bd2670aa6..c8a811985d5 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -189,6 +189,39 @@ pub enum CoverageLevel {
     Mcdc,
 }
 
+/// The different settings that the `-Z autodiff` flag can have.
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum AutoDiff {
+    /// Print TypeAnalysis information
+    PrintTA,
+    /// Print ActivityAnalysis Information
+    PrintAA,
+    /// Print Performance Warnings from Enzyme
+    PrintPerf,
+    /// Combines the three print flags above.
+    Print,
+    /// Print the whole module, before running opts.
+    PrintModBefore,
+    /// Print the whole module just before we pass it to Enzyme.
+    /// For Debug purpose, prefer the OPT flag below
+    PrintModAfterOpts,
+    /// Print the module after Enzyme differentiated everything.
+    PrintModAfterEnzyme,
+
+    /// Enzyme's loose type debug helper (can cause incorrect gradients)
+    LooseTypes,
+
+    /// More flags
+    NoModOptAfter,
+    /// Tell Enzyme to run LLVM Opts on each function it generated. By default off,
+    /// since we already optimize the whole module after Enzyme is done.
+    EnableFncOpt,
+    NoVecUnroll,
+    RuntimeActivity,
+    /// Runs Enzyme specific Inlining
+    Inline,
+}
+
 /// Settings for `-Z instrument-xray` flag.
 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
 pub struct InstrumentXRay {
@@ -2902,7 +2935,7 @@ pub(crate) mod dep_tracking {
     };
 
     use super::{
-        BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
+        AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
         CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
         InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
         LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName,
@@ -2950,6 +2983,7 @@ pub(crate) mod dep_tracking {
     }
 
     impl_dep_tracking_hash_via_hash!(
+        AutoDiff,
         bool,
         usize,
         NonZero<usize>,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c7af40a8ad4..cc86c85f3f0 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -398,6 +398,7 @@ mod desc {
     pub(crate) const parse_list: &str = "a space-separated list of strings";
     pub(crate) const parse_list_with_polarity: &str =
         "a comma-separated list of strings, with elements beginning with + or -";
+    pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Print`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfterOpts`, `PrintModAfterEnzyme`, `LooseTypes`, `NoModOptAfter`, `EnableFncOpt`, `NoVecUnroll`, `Inline`";
     pub(crate) const parse_comma_list: &str = "a comma-separated list of strings";
     pub(crate) const parse_opt_comma_list: &str = parse_comma_list;
     pub(crate) const parse_number: &str = "a number";
@@ -1029,6 +1030,38 @@ pub mod parse {
         }
     }
 
+    pub(crate) fn parse_autodiff(slot: &mut Vec<AutoDiff>, v: Option<&str>) -> bool {
+        let Some(v) = v else {
+            *slot = vec![];
+            return true;
+        };
+        let mut v: Vec<&str> = v.split(",").collect();
+        v.sort_unstable();
+        for &val in v.iter() {
+            let variant = match val {
+                "PrintTA" => AutoDiff::PrintTA,
+                "PrintAA" => AutoDiff::PrintAA,
+                "PrintPerf" => AutoDiff::PrintPerf,
+                "Print" => AutoDiff::Print,
+                "PrintModBefore" => AutoDiff::PrintModBefore,
+                "PrintModAfterOpts" => AutoDiff::PrintModAfterOpts,
+                "PrintModAfterEnzyme" => AutoDiff::PrintModAfterEnzyme,
+                "LooseTypes" => AutoDiff::LooseTypes,
+                "NoModOptAfter" => AutoDiff::NoModOptAfter,
+                "EnableFncOpt" => AutoDiff::EnableFncOpt,
+                "NoVecUnroll" => AutoDiff::NoVecUnroll,
+                "Inline" => AutoDiff::Inline,
+                _ => {
+                    // FIXME(ZuseZ4): print an error saying which value is not recognized
+                    return false;
+                }
+            };
+            slot.push(variant);
+        }
+
+        true
+    }
+
     pub(crate) fn parse_instrument_coverage(
         slot: &mut InstrumentCoverage,
         v: Option<&str>,
@@ -1736,6 +1769,22 @@ options! {
          either `loaded` or `not-loaded`."),
     assume_incomplete_release: bool = (false, parse_bool, [TRACKED],
         "make cfg(version) treat the current version as incomplete (default: no)"),
+    autodiff: Vec<crate::config::AutoDiff> = (Vec::new(), parse_autodiff, [TRACKED],
+        "a list of optional autodiff flags to enable
+         Optional extra settings:
+         `=PrintTA`
+         `=PrintAA`
+         `=PrintPerf`
+         `=Print`
+         `=PrintModBefore`
+         `=PrintModAfterOpts`
+         `=PrintModAfterEnzyme`
+         `=LooseTypes`
+         `=NoModOptAfter`
+         `=EnableFncOpt`
+         `=NoVecUnroll`
+         `=Inline`
+         Multiple options can be combined with commas."),
     #[rustc_lint_opt_deny_field_access("use `Session::binary_dep_depinfo` instead of this field")]
     binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
         "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \
@@ -2034,8 +2083,6 @@ options! {
          Note that this overwrites the effect `-Clink-dead-code` has on collection!"),
     print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
         "print layout information for each type encountered (default: no)"),
-    print_vtable_sizes: bool = (false, parse_bool, [UNTRACKED],
-        "print size comparison between old and new vtable layouts (default: no)"),
     proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
          "show backtraces for panics during proc-macro execution (default: no)"),
     proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 8d4e55dc036..cdc56782a26 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -747,7 +747,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         let alloc_id = tables.tcx.vtable_allocation((
             ty.internal(&mut *tables, tcx),
-            trait_ref.internal(&mut *tables, tcx),
+            trait_ref
+                .internal(&mut *tables, tcx)
+                .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
         ));
         Some(alloc_id.stable(&mut *tables))
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index aee98d7d410..150ec02b7db 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -496,6 +496,9 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
                     found: found.stable(tables),
                 }
             }
+            AssertKind::NullPointerDereference => {
+                stable_mir::mir::AssertMessage::NullPointerDereference
+            }
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6f1d3a74a81..7f7b460cf57 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -502,7 +502,6 @@ symbols! {
         augmented_assignments,
         auto_traits,
         autodiff,
-        autodiff_fallback,
         automatically_derived,
         avx,
         avx512_target_feature,
@@ -568,7 +567,6 @@ symbols! {
         cfg_accessible,
         cfg_attr,
         cfg_attr_multi,
-        cfg_autodiff_fallback,
         cfg_boolean_literals,
         cfg_doctest,
         cfg_emscripten_wasm_eh,
@@ -1476,6 +1474,7 @@ symbols! {
         panic_location,
         panic_misaligned_pointer_dereference,
         panic_nounwind,
+        panic_null_pointer_dereference,
         panic_runtime,
         panic_str_2015,
         panic_unwind,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 5c5ab435dbd..4312c82815c 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -151,7 +151,7 @@ fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty
 
 pub fn typeid_for_trait_ref<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+    trait_ref: ty::ExistentialTraitRef<'tcx>,
 ) -> String {
     v0::mangle_typeid_for_trait_ref(tcx, trait_ref)
 }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 5b3272feecd..7b040a8b2c4 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -72,7 +72,7 @@ pub(super) fn mangle<'tcx>(
 
 pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+    trait_ref: ty::ExistentialTraitRef<'tcx>,
 ) -> String {
     // FIXME(flip1995): See comment in `mangle_typeid_for_fnabi`.
     let mut cx = SymbolMangler {
@@ -84,7 +84,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
         binders: vec![],
         out: String::new(),
     };
-    cx.print_def_path(trait_ref.def_id(), &[]).unwrap();
+    cx.print_def_path(trait_ref.def_id, &[]).unwrap();
     std::mem::take(&mut cx.out)
 }
 
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 1292f46f0c9..f17452b3ba0 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -934,6 +934,7 @@ pub enum InlineAsmClobberAbi {
     LoongArch,
     PowerPC,
     S390x,
+    Bpf,
     Msp430,
 }
 
@@ -1003,6 +1004,10 @@ impl InlineAsmClobberAbi {
                 "C" | "system" => Ok(InlineAsmClobberAbi::S390x),
                 _ => Err(&["C", "system"]),
             },
+            InlineAsmArch::Bpf => match name {
+                "C" | "system" => Ok(InlineAsmClobberAbi::Bpf),
+                _ => Err(&["C", "system"]),
+            },
             InlineAsmArch::Msp430 => match name {
                 "C" | "system" => Ok(InlineAsmClobberAbi::Msp430),
                 _ => Err(&["C", "system"]),
@@ -1278,6 +1283,14 @@ impl InlineAsmClobberAbi {
                     a8, a9, a10, a11, a12, a13, a14, a15,
                 }
             },
+            InlineAsmClobberAbi::Bpf => clobbered_regs! {
+                Bpf BpfInlineAsmReg {
+                    // Refs: Section 1.1 "Registers and calling convention" in BPF ABI Recommended Conventions and Guidelines v1.0
+                    // https://www.kernel.org/doc/html/latest/bpf/standardization/abi.html#registers-and-calling-convention
+
+                    r0, r1, r2, r3, r4, r5,
+                }
+            },
             InlineAsmClobberAbi::Msp430 => clobbered_regs! {
                 Msp430 Msp430InlineAsmReg {
                     r11, r12, r13, r14, r15,
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 7c72318b4d7..055a3edcc32 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -148,8 +148,6 @@ trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement
 trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
 trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement
 
-trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
-
 trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
     .label = empty on-clause here
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 117b6a76425..db4a14356cc 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1392,9 +1392,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         mut values: Option<ty::ParamEnvAnd<'tcx, ValuePairs<'tcx>>>,
         terr: TypeError<'tcx>,
         prefer_label: bool,
+        override_span: Option<Span>,
     ) {
-        let span = cause.span;
-
+        // We use `override_span` when we want the error to point at a `Span` other than
+        // `cause.span`. This is used in E0271, when a closure is passed in where the return type
+        // isn't what was expected. We want to point at the closure's return type (or expression),
+        // instead of the expression where the closure is passed as call argument.
+        let span = override_span.unwrap_or(cause.span);
         // For some types of errors, expected-found does not make
         // sense, so just ignore the values we were given.
         if let TypeError::CyclicTy(_) = terr {
@@ -2057,6 +2061,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             Some(param_env.and(trace.values)),
             terr,
             false,
+            None,
         );
         diag
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 6d39cbce3b7..6416c539f26 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -708,6 +708,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     None,
                     TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),
                     false,
+                    None,
                 );
                 diag
             }
@@ -931,14 +932,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
         }
         let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
-        let body_id = match self.tcx.hir_node(hir_id) {
-            hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Fn { body: body_id, .. }, ..
-            }) => body_id,
-            _ => return false,
-        };
-        let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span })
-            .visit_body(self.tcx.hir().body(*body_id))
+        let Some(body_id) = self.tcx.hir_node(hir_id).body_id() else { return false };
+        let ControlFlow::Break(expr) =
+            (FindMethodSubexprOfTry { search_span: span }).visit_body(self.tcx.hir().body(body_id))
         else {
             return false;
         };
@@ -1385,9 +1381,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 _ => (None, error.err),
             };
 
-            let msg = values
+            let (msg, span, closure_span) = values
                 .and_then(|(predicate, normalized_term, expected_term)| {
-                    self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
+                    self.maybe_detailed_projection_msg(
+                        obligation.cause.span,
+                        predicate,
+                        normalized_term,
+                        expected_term,
+                    )
                 })
                 .unwrap_or_else(|| {
                     let mut cx = FmtPrinter::new_with_limit(
@@ -1395,12 +1396,39 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         Namespace::TypeNS,
                         rustc_session::Limit(10),
                     );
-                    with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
-                        self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
-                        cx.into_buffer()
-                    }))
+                    (
+                        with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
+                            self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
+                            cx.into_buffer()
+                        })),
+                        obligation.cause.span,
+                        None,
+                    )
                 });
-            let mut diag = struct_span_code_err!(self.dcx(), obligation.cause.span, E0271, "{msg}");
+            let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");
+            if let Some(span) = closure_span {
+                // Mark the closure decl so that it is seen even if we are pointing at the return
+                // type or expression.
+                //
+                // error[E0271]: expected `{closure@foo.rs:41:16}` to be a closure that returns
+                //               `Unit3`, but it returns `Unit4`
+                //   --> $DIR/foo.rs:43:17
+                //    |
+                // LL |     let v = Unit2.m(
+                //    |                   - required by a bound introduced by this call
+                // ...
+                // LL |             f: |x| {
+                //    |                --- /* this span */
+                // LL |                 drop(x);
+                // LL |                 Unit4
+                //    |                 ^^^^^ expected `Unit3`, found `Unit4`
+                //    |
+                diag.span_label(span, "this closure");
+                if !span.overlaps(obligation.cause.span) {
+                    // Point at the binding corresponding to the closure where it is used.
+                    diag.span_label(obligation.cause.span, "closure used here");
+                }
+            }
 
             let secondary_span = (|| {
                 let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
@@ -1471,6 +1499,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }),
                 err,
                 false,
+                Some(span),
             );
             self.note_obligation_cause(&mut diag, obligation);
             diag.emit()
@@ -1479,34 +1508,66 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
     fn maybe_detailed_projection_msg(
         &self,
+        mut span: Span,
         projection_term: ty::AliasTerm<'tcx>,
         normalized_ty: ty::Term<'tcx>,
         expected_ty: ty::Term<'tcx>,
-    ) -> Option<String> {
+    ) -> Option<(String, Span, Option<Span>)> {
         let trait_def_id = projection_term.trait_def_id(self.tcx);
         let self_ty = projection_term.self_ty();
 
         with_forced_trimmed_paths! {
             if self.tcx.is_lang_item(projection_term.def_id, LangItem::FnOnceOutput) {
                 let fn_kind = self_ty.prefix_string(self.tcx);
+                let (span, closure_span) = if let ty::Closure(def_id, _) = self_ty.kind() {
+                    let def_span = self.tcx.def_span(def_id);
+                    if let Some(local_def_id) = def_id.as_local()
+                        && let node = self.tcx.hir_node_by_def_id(local_def_id)
+                        && let Some(fn_decl) = node.fn_decl()
+                        && let Some(id) = node.body_id()
+                    {
+                        span = match fn_decl.output {
+                            hir::FnRetTy::Return(ty) => ty.span,
+                            hir::FnRetTy::DefaultReturn(_) => {
+                                let body = self.tcx.hir().body(id);
+                                match body.value.kind {
+                                    hir::ExprKind::Block(
+                                        hir::Block { expr: Some(expr), .. },
+                                        _,
+                                    ) => expr.span,
+                                    hir::ExprKind::Block(
+                                        hir::Block {
+                                            expr: None, stmts: [.., last], ..
+                                        },
+                                        _,
+                                    ) => last.span,
+                                    _ => body.value.span,
+                                }
+                            }
+                        };
+                    }
+                    (span, Some(def_span))
+                } else {
+                    (span, None)
+                };
                 let item = match self_ty.kind() {
                     ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
                     _ => self_ty.to_string(),
                 };
-                Some(format!(
+                Some((format!(
                     "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
                      returns `{normalized_ty}`",
-                ))
+                ), span, closure_span))
             } else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) {
-                Some(format!(
+                Some((format!(
                     "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
                      resolves to `{normalized_ty}`"
-                ))
+                ), span, None))
             } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
-                Some(format!(
+                Some((format!(
                     "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
                      yields `{normalized_ty}`"
-                ))
+                ), span, None))
             } else {
                 None
             }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 8111983c539..b4e5cc6185c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -482,11 +482,10 @@ pub fn report_dyn_incompatibility<'tcx>(
     for (span, msg) in iter::zip(multi_span, messages) {
         note_span.push_span_label(span, msg);
     }
-    // FIXME(dyn_compat_renaming): Update the URL.
     err.span_note(
         note_span,
         "for a trait to be dyn compatible it needs to allow building a vtable\n\
-        for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
+        for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>",
     );
 
     // Only provide the help if its a local trait, otherwise it's not actionable.
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index c8672b9dbd2..c5ab8a71c78 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
 use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
-use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
+use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
 use rustc_span::{BytePos, Ident, Span, Symbol, kw};
 
 use crate::error_reporting::infer::ObligationCauseAsDiagArg;
@@ -23,15 +23,6 @@ use crate::fluent_generated as fluent;
 pub mod note_and_explain;
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_dump_vtable_entries)]
-pub struct DumpVTableEntries<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub trait_ref: PolyTraitRef<'a>,
-    pub entries: String,
-}
-
-#[derive(Diagnostic)]
 #[diag(trait_selection_unable_to_construct_constant_value)]
 pub struct UnableToConstructConstantValue<'a> {
     #[primary_span]
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index 66491d9abe1..baa94ead9d4 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -64,7 +64,7 @@ fn is_dyn_compatible(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
 }
 
 /// We say a method is *vtable safe* if it can be invoked on a trait
-/// object. Note that object-safe traits can have some
+/// object. Note that dyn-compatible traits can have some
 /// non-vtable-safe methods, so long as they require `Self: Sized` or
 /// otherwise ensure that they cannot be used when `Self = Trait`.
 pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
@@ -421,7 +421,7 @@ fn virtual_call_violations_for_method<'tcx>(
     let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
 
     // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
-    // However, this is already considered object-safe. We allow it as a special case here.
+    // However, this is already considered dyn compatible. We allow it as a special case here.
     // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
     // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
     if receiver_ty != tcx.types.self_param {
@@ -631,7 +631,7 @@ fn object_ty_for_trait<'tcx>(
 /// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
 ///
 /// The only case where the receiver is not dispatchable, but is still a valid receiver
-/// type (just not object-safe), is when there is more than one level of pointer indirection.
+/// type (just not dyn compatible), is when there is more than one level of pointer indirection.
 /// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
 /// is no way, or at least no inexpensive way, to coerce the receiver from the version where
 /// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index c9fb2a757e1..d30363ec158 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -25,7 +25,7 @@ use tracing::debug;
 /// trait Bar {}
 /// trait Foo = Bar + Bar;
 ///
-/// let not_object_safe: dyn Foo; // bad, two `Bar` principals.
+/// let dyn_incompatible: dyn Foo; // bad, two `Bar` principals.
 /// ```
 pub fn expand_trait_aliases<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index b5bc8364c7b..000e6a765d3 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -2,26 +2,22 @@ use std::fmt::Debug;
 use std::ops::ControlFlow;
 
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::util::PredicateSet;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry,
 };
-use rustc_span::{DUMMY_SP, Span, sym};
+use rustc_span::DUMMY_SP;
 use smallvec::{SmallVec, smallvec};
 use tracing::debug;
 
-use crate::errors::DumpVTableEntries;
-use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method};
+use crate::traits::{impossible_predicates, is_vtable_safe_method};
 
 #[derive(Clone, Debug)]
 pub enum VtblSegment<'tcx> {
     MetadataDSA,
-    TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
+    TraitOwnEntries { trait_ref: ty::TraitRef<'tcx>, emit_vptr: bool },
 }
 
 /// Prepare the segments for a vtable
@@ -29,7 +25,7 @@ pub enum VtblSegment<'tcx> {
 // about our `Self` type here.
 pub fn prepare_vtable_segments<'tcx, T>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
     segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
 ) -> Option<T> {
     prepare_vtable_segments_inner(tcx, trait_ref, segment_visitor).break_value()
@@ -39,7 +35,7 @@ pub fn prepare_vtable_segments<'tcx, T>(
 /// such that we can use `?` in the body.
 fn prepare_vtable_segments_inner<'tcx, T>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
     mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
 ) -> ControlFlow<T> {
     // The following constraints holds for the final arrangement.
@@ -92,7 +88,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
     let mut emit_vptr_on_new_entry = false;
     let mut visited = PredicateSet::new(tcx);
     let predicate = trait_ref.upcast(tcx);
-    let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
+    let mut stack: SmallVec<[(ty::TraitRef<'tcx>, _, _); 5]> =
         smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))];
     visited.insert(predicate);
 
@@ -125,10 +121,18 @@ fn prepare_vtable_segments_inner<'tcx, T>(
             let &(inner_most_trait_ref, _, _) = stack.last().unwrap();
 
             let mut direct_super_traits_iter = tcx
-                .explicit_super_predicates_of(inner_most_trait_ref.def_id())
+                .explicit_super_predicates_of(inner_most_trait_ref.def_id)
                 .iter_identity_copied()
                 .filter_map(move |(pred, _)| {
-                    pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause()
+                    pred.instantiate_supertrait(tcx, ty::Binder::dummy(inner_most_trait_ref))
+                        .as_trait_clause()
+                })
+                .map(move |pred| {
+                    tcx.normalize_erasing_late_bound_regions(
+                        ty::TypingEnv::fully_monomorphized(),
+                        pred,
+                    )
+                    .trait_ref
                 });
 
             // Find an unvisited supertrait
@@ -136,16 +140,11 @@ fn prepare_vtable_segments_inner<'tcx, T>(
                 .find(|&super_trait| visited.insert(super_trait.upcast(tcx)))
             {
                 // Push it to the stack for the next iteration of 'diving_in to pick up
-                Some(unvisited_super_trait) => {
-                    // We're throwing away potential constness of super traits here.
-                    // FIXME: handle ~const super traits
-                    let next_super_trait = unvisited_super_trait.map_bound(|t| t.trait_ref);
-                    stack.push((
-                        next_super_trait,
-                        emit_vptr_on_new_entry,
-                        maybe_iter(Some(direct_super_traits_iter)),
-                    ))
-                }
+                Some(next_super_trait) => stack.push((
+                    next_super_trait,
+                    emit_vptr_on_new_entry,
+                    maybe_iter(Some(direct_super_traits_iter)),
+                )),
 
                 // There are no more unvisited direct super traits, dive-in finished
                 None => break 'diving_in,
@@ -154,8 +153,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
 
         // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
         while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
-            let has_entries =
-                has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id());
+            let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id);
 
             segment_visitor(VtblSegment::TraitOwnEntries {
                 trait_ref: inner_most_trait_ref,
@@ -169,11 +167,6 @@ fn prepare_vtable_segments_inner<'tcx, T>(
             if let Some(next_inner_most_trait_ref) =
                 siblings.find(|&sibling| visited.insert(sibling.upcast(tcx)))
             {
-                // We're throwing away potential constness of super traits here.
-                // FIXME: handle ~const super traits
-                let next_inner_most_trait_ref =
-                    next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
-
                 stack.push((next_inner_most_trait_ref, emit_vptr_on_new_entry, siblings));
 
                 // just pushed a new trait onto the stack, so we need to go through its super traits
@@ -192,15 +185,6 @@ fn maybe_iter<I: Iterator>(i: Option<I>) -> impl Iterator<Item = I::Item> {
     i.into_iter().flatten()
 }
 
-fn dump_vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    sp: Span,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    entries: &[VtblEntry<'tcx>],
-) {
-    tcx.dcx().emit_err(DumpVTableEntries { span: sp, trait_ref, entries: format!("{entries:#?}") });
-}
-
 fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
     own_existential_vtable_entries_iter(tcx, trait_def_id).next().is_some()
 }
@@ -239,8 +223,15 @@ fn own_existential_vtable_entries_iter(
 /// that come from `trait_ref`, including its supertraits.
 fn vtable_entries<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
 ) -> &'tcx [VtblEntry<'tcx>] {
+    debug_assert!(!trait_ref.has_non_region_infer() && !trait_ref.has_non_region_param());
+    debug_assert_eq!(
+        tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref),
+        trait_ref,
+        "vtable trait ref should be normalized"
+    );
+
     debug!("vtable_entries({:?})", trait_ref);
 
     let mut entries = vec![];
@@ -251,33 +242,26 @@ fn vtable_entries<'tcx>(
                 entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
             }
             VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                let existential_trait_ref = trait_ref
-                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+                let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref);
 
                 // Lookup the shape of vtable for the trait.
                 let own_existential_entries =
-                    tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
+                    tcx.own_existential_vtable_entries(existential_trait_ref.def_id);
 
                 let own_entries = own_existential_entries.iter().copied().map(|def_id| {
                     debug!("vtable_entries: trait_method={:?}", def_id);
 
                     // The method may have some early-bound lifetimes; add regions for those.
-                    let args = trait_ref.map_bound(|trait_ref| {
+                    // FIXME: Is this normalize needed?
+                    let args = tcx.normalize_erasing_regions(
+                        ty::TypingEnv::fully_monomorphized(),
                         GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
                             GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
                             GenericParamDefKind::Type { .. }
                             | GenericParamDefKind::Const { .. } => {
                                 trait_ref.args[param.index as usize]
                             }
-                        })
-                    });
-
-                    // The trait type may have higher-ranked lifetimes in it;
-                    // erase them if they appear, so that we get the type
-                    // at some particular call site.
-                    let args = tcx.normalize_erasing_late_bound_regions(
-                        ty::TypingEnv::fully_monomorphized(),
-                        args,
+                        }),
                     );
 
                     // It's possible that the method relies on where-clauses that
@@ -317,11 +301,6 @@ fn vtable_entries<'tcx>(
 
     let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
 
-    if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
-        let sp = tcx.def_span(trait_ref.def_id());
-        dump_vtable_entries(tcx, sp, trait_ref, &entries);
-    }
-
     tcx.arena.alloc_from_iter(entries)
 }
 
@@ -329,14 +308,20 @@ fn vtable_entries<'tcx>(
 // for `Supertrait`'s methods in the vtable of `Subtrait`.
 pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRef<'tcx>) -> usize {
     debug_assert!(!key.has_non_region_infer() && !key.has_non_region_param());
+    debug_assert_eq!(
+        tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), key),
+        key,
+        "vtable trait ref should be normalized"
+    );
 
     let ty::Dynamic(source, _, _) = *key.self_ty().kind() else {
         bug!();
     };
-    let source_principal =
-        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self);
+    let source_principal = tcx.instantiate_bound_regions_with_erased(
+        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self),
+    );
 
-    let target_principal = ty::Binder::dummy(ty::ExistentialTraitRef::erase_self_ty(tcx, key));
+    let target_principal = ty::ExistentialTraitRef::erase_self_ty(tcx, key);
 
     let vtable_segment_callback = {
         let mut vptr_offset = 0;
@@ -346,17 +331,14 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
                     vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
                 }
                 VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => {
-                    if trait_refs_are_compatible(
-                        tcx,
-                        vtable_principal
-                            .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)),
-                        target_principal,
-                    ) {
+                    if ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal)
+                        == target_principal
+                    {
                         return ControlFlow::Break(vptr_offset);
                     }
 
                     vptr_offset +=
-                        tcx.own_existential_vtable_entries(vtable_principal.def_id()).len();
+                        tcx.own_existential_vtable_entries(vtable_principal.def_id).len();
 
                     if emit_vptr {
                         vptr_offset += 1;
@@ -382,20 +364,27 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     ),
 ) -> Option<usize> {
     debug_assert!(!key.has_non_region_infer() && !key.has_non_region_param());
+    debug_assert_eq!(
+        tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), key),
+        key,
+        "upcasting trait refs should be normalized"
+    );
+
     let (source, target) = key;
 
     // If the target principal is `None`, we can just return `None`.
     let ty::Dynamic(target, _, _) = *target.kind() else {
         bug!();
     };
-    let target_principal = target.principal()?;
+    let target_principal = tcx.instantiate_bound_regions_with_erased(target.principal()?);
 
     // Given that we have a target principal, it is a bug for there not to be a source principal.
     let ty::Dynamic(source, _, _) = *source.kind() else {
         bug!();
     };
-    let source_principal =
-        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self);
+    let source_principal = tcx.instantiate_bound_regions_with_erased(
+        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self),
+    );
 
     let vtable_segment_callback = {
         let mut vptr_offset = 0;
@@ -406,13 +395,10 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
                 }
                 VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => {
                     vptr_offset +=
-                        tcx.own_existential_vtable_entries(vtable_principal.def_id()).len();
-                    if trait_refs_are_compatible(
-                        tcx,
-                        vtable_principal
-                            .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)),
-                        target_principal,
-                    ) {
+                        tcx.own_existential_vtable_entries(vtable_principal.def_id).len();
+                    if ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal)
+                        == target_principal
+                    {
                         if emit_vptr {
                             return ControlFlow::Break(Some(vptr_offset));
                         } else {
@@ -432,41 +418,6 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap()
 }
 
-fn trait_refs_are_compatible<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    hr_vtable_principal: ty::PolyExistentialTraitRef<'tcx>,
-    hr_target_principal: ty::PolyExistentialTraitRef<'tcx>,
-) -> bool {
-    if hr_vtable_principal.def_id() != hr_target_principal.def_id() {
-        return false;
-    }
-
-    let (infcx, param_env) =
-        tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
-    let ocx = ObligationCtxt::new(&infcx);
-    let hr_source_principal =
-        ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal);
-    let hr_target_principal =
-        ocx.normalize(&ObligationCause::dummy(), param_env, hr_target_principal);
-    infcx.enter_forall(hr_target_principal, |target_principal| {
-        let source_principal = infcx.instantiate_binder_with_fresh_vars(
-            DUMMY_SP,
-            BoundRegionConversionTime::HigherRankedType,
-            hr_source_principal,
-        );
-        let Ok(()) = ocx.eq_trace(
-            &ObligationCause::dummy(),
-            param_env,
-            ToTrace::to_trace(&ObligationCause::dummy(), hr_target_principal, hr_source_principal),
-            target_principal,
-            source_principal,
-        ) else {
-            return false;
-        };
-        ocx.select_all_or_error().is_empty()
-    })
-}
-
 pub(super) fn provide(providers: &mut Providers) {
     *providers = Providers {
         own_existential_vtable_entries,
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 8686169c15d..eec6cd8d49b 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -251,6 +251,7 @@ pub enum AssertMessage {
     ResumedAfterReturn(CoroutineKind),
     ResumedAfterPanic(CoroutineKind),
     MisalignedPointerDereference { required: Operand, found: Operand },
+    NullPointerDereference,
 }
 
 impl AssertMessage {
@@ -306,6 +307,7 @@ impl AssertMessage {
             AssertMessage::MisalignedPointerDereference { .. } => {
                 Ok("misaligned pointer dereference")
             }
+            AssertMessage::NullPointerDereference => Ok("null pointer dereference occured"),
         }
     }
 }
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 81981bce202..6638f93e555 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -298,6 +298,9 @@ fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::R
                 "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}"
             )
         }
+        AssertMessage::NullPointerDereference => {
+            write!(writer, "\"null pointer dereference occured.\"")
+        }
         AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
             write!(writer, "{}", msg.description().unwrap())
         }
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index 79efb83cebd..d985a98fcbf 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -426,7 +426,10 @@ pub trait MirVisitor {
             | AssertMessage::RemainderByZero(op) => {
                 self.visit_operand(op, location);
             }
-            AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => { //nothing to visit
+            AssertMessage::ResumedAfterReturn(_)
+            | AssertMessage::ResumedAfterPanic(_)
+            | AssertMessage::NullPointerDereference => {
+                //nothing to visit
             }
             AssertMessage::MisalignedPointerDereference { required, found } => {
                 self.visit_operand(required, location);
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 80f6e32b6b2..e5c1a64c12e 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -468,9 +468,11 @@ pub fn spin_loop() {
 /// // No assumptions can be made about either operand, so the multiplication is not optimized out.
 /// let y = black_box(5) * black_box(10);
 /// ```
+///
+/// During constant evaluation, `black_box` is treated as a no-op.
 #[inline]
 #[stable(feature = "bench_black_box", since = "1.66.0")]
-#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
+#[rustc_const_stable(feature = "const_black_box", since = "CURRENT_RUSTC_VERSION")]
 pub const fn black_box<T>(dummy: T) -> T {
     crate::intrinsics::black_box(dummy)
 }
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 41b2ffad668..c0d435f99c0 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3725,6 +3725,7 @@ pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: u
 #[rustc_nounwind]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
+#[rustc_intrinsic_const_stable_indirect]
 pub const fn black_box<T>(_dummy: T) -> T {
     unimplemented!()
 }
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 53e2b238bae..a89de12c02b 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -291,6 +291,22 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
     )
 }
 
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[track_caller]
+#[cfg_attr(not(bootstrap), lang = "panic_null_pointer_dereference")] // needed by codegen for panic on null pointer deref
+#[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind
+fn panic_null_pointer_dereference() -> ! {
+    if cfg!(feature = "panic_immediate_abort") {
+        super::intrinsics::abort()
+    }
+
+    panic_nounwind_fmt(
+        format_args!("null pointer dereference occured"),
+        /* force_no_backtrace */ false,
+    )
+}
+
 /// Panics because we cannot unwind out of a function.
 ///
 /// This is a separate function to avoid the codesize impact of each crate containing the string to
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 0061e33f986..73180bde54a 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -716,6 +716,12 @@ impl AtomicBool {
     /// AcqRel   | AcqRel  | Acquire
     /// SeqCst   | SeqCst  | SeqCst
     ///
+    /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
+    /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
+    /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
+    /// rather than to infer success vs failure based on the value that was read.
+    ///
+    /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
     /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
     /// which allows the compiler to generate better assembly code when the compare and swap
     /// is used in a loop.
@@ -1651,6 +1657,12 @@ impl<T> AtomicPtr<T> {
     /// AcqRel   | AcqRel  | Acquire
     /// SeqCst   | SeqCst  | SeqCst
     ///
+    /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
+    /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
+    /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
+    /// rather than to infer success vs failure based on the value that was read.
+    ///
+    /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
     /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
     /// which allows the compiler to generate better assembly code when the compare and swap
     /// is used in a loop.
@@ -2771,6 +2783,12 @@ macro_rules! atomic_int {
             /// AcqRel   | AcqRel  | Acquire
             /// SeqCst   | SeqCst  | SeqCst
             ///
+            /// `compare_and_swap` and `compare_exchange` also differ in their return type. You can use
+            /// `compare_exchange(...).unwrap_or_else(|x| x)` to recover the behavior of `compare_and_swap`,
+            /// but in most cases it is more idiomatic to check whether the return value is `Ok` or `Err`
+            /// rather than to infer success vs failure based on the value that was read.
+            ///
+            /// During migration, consider whether it makes sense to use `compare_exchange_weak` instead.
             /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds,
             /// which allows the compiler to generate better assembly code when the compare and swap
             /// is used in a loop.
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 0607d508a48..7fe72862608 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -14,7 +14,6 @@
 #![feature(bstr)]
 #![feature(cell_update)]
 #![feature(clone_to_uninit)]
-#![feature(const_black_box)]
 #![feature(const_eval_select)]
 #![feature(const_swap_nonoverlapping)]
 #![feature(const_trait_impl)]
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index fd9bf47234c..f447d186a52 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1049,9 +1049,12 @@ pub fn rustc_cargo(
     // <https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Internal.20lint.20for.20raw.20.60print!.60.20and.20.60println!.60.3F>.
     cargo.rustflag("-Zon-broken-pipe=kill");
 
-    if builder.config.llvm_enzyme {
-        cargo.rustflag("-l").rustflag("Enzyme-19");
-    }
+    // We temporarily disable linking here as part of some refactoring.
+    // This way, people can manually use -Z llvm-plugins and -C passes=enzyme for now.
+    // In a follow-up PR, we will re-enable linking here and load the pass for them.
+    //if builder.config.llvm_enzyme {
+    //    cargo.rustflag("-l").rustflag("Enzyme-19");
+    //}
 
     // Building with protected visibility reduces the number of dynamic relocations needed, giving
     // us a faster startup time. However GNU ld < 2.40 will error if we try to link a shared object
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index c6bc19f9e6c..9af88709625 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -43,6 +43,10 @@ runners:
     os: windows-2022-8core-32gb
     <<: *base-job
 
+  - &job-windows-25-8c
+    os: windows-2025-8core-32gb
+    <<: *base-job
+
   - &job-aarch64-linux
     # Free some disk space to avoid running out of space during the build.
     free_disk: true
@@ -524,7 +528,7 @@ auto:
       # We are intentionally allowing an old toolchain on this builder (and that's
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
-    <<: *job-windows-8c
+    <<: *job-windows-25-8c
 
   # x86_64-mingw is split into two jobs to run tests in parallel.
   - name: x86_64-mingw-1
diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md
index 1d9fa1b52d5..cd215277e69 100644
--- a/src/doc/rustc-dev-guide/src/building/new-target.md
+++ b/src/doc/rustc-dev-guide/src/building/new-target.md
@@ -4,8 +4,13 @@ These are a set of steps to add support for a new target. There are
 numerous end states and paths to get there, so not all sections may be
 relevant to your desired goal.
 
+See also the associated documentation in the
+[target tier policy][target_tier_policy_add].
+
 <!-- toc -->
 
+[target_tier_policy_add]: https://doc.rust-lang.org/rustc/target-tier-policy.html#adding-a-new-target
+
 ## Specifying a new LLVM
 
 For very new targets, you may need to use a different fork of LLVM
diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md
index a2a6c8085df..e2097b26e5c 100644
--- a/src/doc/rustc-dev-guide/src/compiler-debugging.md
+++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md
@@ -275,7 +275,7 @@ Here are some notable ones:
 | `rustc_dump_def_parents` | Dumps the chain of `DefId` parents of certain definitions. |
 | `rustc_dump_item_bounds` | Dumps the [`item_bounds`] of an item. |
 | `rustc_dump_predicates` | Dumps the [`predicates_of`] an item. |
-| `rustc_dump_vtable` |  |
+| `rustc_dump_vtable` | Dumps the vtable layout of an impl, or a type alias of a dyn type. |
 | `rustc_hidden_type_of_opaques` | Dumps the [hidden type of each opaque types][opaq] in the crate. |
 | `rustc_layout` | [See this section](#debugging-type-layouts). |
 | `rustc_object_lifetime_default` | Dumps the [object lifetime defaults] of an item. |
diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md
index 4010e90821f..0e624a4566d 100644
--- a/src/doc/rustc-dev-guide/src/conventions.md
+++ b/src/doc/rustc-dev-guide/src/conventions.md
@@ -43,7 +43,7 @@ environment.
 
 ## Formatting and linting Python code
 
-The Rust repository contains quite a lof of Python code. We try to keep
+The Rust repository contains quite a lot of Python code. We try to keep
 it both linted and formatted by the [ruff][ruff] tool.
 
 When modifying Python code, use this command to format it:
diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index 38b655b7542..4050494793a 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -3,7 +3,7 @@
 `rustc` supports doing profile-guided optimization (PGO).
 This chapter describes what PGO is, what it is good for, and how it can be used.
 
-## What Is Profiled-Guided Optimization?
+## What Is Profile-Guided Optimization?
 
 The basic concept of PGO is to collect data about the typical execution of
 a program (e.g. which branches it is likely to take) and then use this data
diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md
index bdcf2c0b07e..a0acfdf0e4a 100644
--- a/src/doc/rustc/src/target-tier-policy.md
+++ b/src/doc/rustc/src/target-tier-policy.md
@@ -122,12 +122,23 @@ To propose addition of a new target, open a pull request on [`rust-lang/rust`]:
   r? compiler
   ```
 
+See also the documentation in the `rustc-dev-guide` on [adding a new target to
+`rustc`][rustc_dev_guide_add_target].
+
+Note that adding a new target that wants to support `std` would transitively
+require `cc` and `libc` support. However, these would like to know about the
+target from `rustc` as well. To break this cycle, you are strongly encouraged
+to add a _minimal_ `#![no_core]` target spec first to teach `rustc` about the
+target's existence, and add `std` support as a follow-up once you've added
+support for the target in `cc` and `libc`.
+
 [tier3example]: https://github.com/rust-lang/rust/pull/94872
 [platform_template]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support/TEMPLATE.md
 [summary]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/SUMMARY.md
 [platformsupport]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support.md
 [rust_compiler_team]: https://www.rust-lang.org/governance/teams/compiler
 [`rust-lang/rust`]: https://github.com/rust-lang/rust
+[rustc_dev_guide_add_target]: https://rustc-dev-guide.rust-lang.org/building/new-target.html
 
 ## Tier 3 target policy
 
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index d1d42e47322..7eb1b8df233 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -524,6 +524,8 @@ use `-o -`.
 
 ## `-w`/`--output-format`: output format
 
+### json
+
 `--output-format json` emits documentation in the experimental
 [JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect,
 and is also accepted on stable toolchains.
@@ -542,6 +544,68 @@ It can also be used with `--show-coverage`. Take a look at its
 [documentation](#--show-coverage-calculate-the-percentage-of-items-with-documentation) for more
 information.
 
+### doctest
+
+`--output-format doctest` emits JSON on stdout which gives you information about doctests in the
+provided crate.
+
+Tracking issue: [#134529](https://github.com/rust-lang/rust/issues/134529)
+
+You can use this option like this:
+
+```bash
+rustdoc -Zunstable-options --output-format=doctest src/lib.rs
+```
+
+For this rust code:
+
+```rust
+/// ```
+/// let x = 12;
+/// ```
+pub trait Trait {}
+```
+
+The generated output (formatted) will look like this:
+
+```json
+{
+  "format_version": 1,
+  "doctests": [
+    {
+      "file": "foo.rs",
+      "line": 1,
+      "doctest_attributes": {
+        "original": "",
+        "should_panic": false,
+        "no_run": false,
+        "ignore": "None",
+        "rust": true,
+        "test_harness": false,
+        "compile_fail": false,
+        "standalone_crate": false,
+        "error_codes": [],
+        "edition": null,
+        "added_css_classes": [],
+        "unknown": []
+      },
+      "original_code": "let x = 12;",
+      "doctest_code": "#![allow(unused)]\nfn main() {\nlet x = 12;\n}",
+      "name": "foo.rs - Trait (line 1)"
+    }
+  ]
+}
+```
+
+ * `format_version` gives you the current version of the generated JSON. If we change the output in any way, the number will increase.
+ * `doctests` contains the list of doctests present in the crate.
+   * `file` is the file path where the doctest is located.
+   * `line` is the line where the doctest starts (so where the \`\`\` is located in the current code).
+   * `doctest_attributes` contains computed information about the attributes used on the doctests. For more information about doctest attributes, take a look [here](write-documentation/documentation-tests.html#attributes).
+   * `original_code` is the code as written in the source code before rustdoc modifies it.
+   * `doctest_code` is the code modified by rustdoc that will be run. If there is a fatal syntax error, this field will not be present.
+   * `name` is the name generated by rustdoc which represents this doctest.
+
 ## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
 
  * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md
index b9a89c20cee..19e62c4867c 100644
--- a/src/doc/style-guide/src/editions.md
+++ b/src/doc/style-guide/src/editions.md
@@ -36,10 +36,6 @@ For a full history of changes in the Rust 2024 style edition, see the git
 history of the style guide. Notable changes in the Rust 2024 style edition
 include:
 
-- [#114764](https://github.com/rust-lang/rust/pull/114764) As the last member
-  of a delimited expression, delimited expressions are generally combinable,
-  regardless of the number of members. Previously only applied with exactly
-  one member (except for closures with explicit blocks).
 - Miscellaneous `rustfmt` bugfixes.
 - Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order).
 - Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase".
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 171a24cd89d..12037b5992e 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -818,11 +818,11 @@ E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.
 
 ## Combinable expressions
 
-When the last argument in a function call is formatted across
-multiple-lines, format the outer call as if it were a single-line call,
+Where a function call has a single argument, and that argument is formatted
+across multiple-lines, format the outer call as if it were a single-line call,
 if the result fits. Apply the same combining behaviour to any similar
 expressions which have multi-line, block-indented lists of sub-expressions
-delimited by parentheses, brackets, or braces. E.g.,
+delimited by parentheses (e.g., macros or tuple struct literals). E.g.,
 
 ```rust
 foo(bar(
@@ -848,61 +848,20 @@ let arr = [combinable(
     an_expr,
     another_expr,
 )];
-
-let x = Thing(an_expr, another_expr, match cond {
-    A => 1,
-    B => 2,
-});
-
-let x = format!("Stuff: {}", [
-    an_expr,
-    another_expr,
-]);
-
-let x = func(an_expr, another_expr, SomeStruct {
-    field: this_is_long,
-    another_field: 123,
-});
 ```
 
 Apply this behavior recursively.
 
-If the last argument is a multi-line closure with an explicit block,
-only apply the combining behavior if there are no other closure arguments.
+For a function with multiple arguments, if the last argument is a multi-line
+closure with an explicit block, there are no other closure arguments, and all
+the arguments and the first line of the closure fit on the first line, use the
+same combining behavior:
 
 ```rust
-// Combinable
 foo(first_arg, x, |param| {
     action();
     foo(param)
 })
-// Not combinable, because the closure is not the last argument
-foo(
-    first_arg,
-    |param| {
-        action();
-        foo(param)
-    },
-    whatever,
-)
-// Not combinable, because the first line of the closure does not fit
-foo(
-    first_arg,
-    x,
-    move |very_long_param_causing_line_to_overflow| -> Bar {
-        action();
-        foo(param)
-    },
-)
-// Not combinable, because there is more than one closure argument
-foo(
-    first_arg,
-    |x| x.bar(),
-    |param| {
-        action();
-        foo(param)
-    },
-)
 ```
 
 ## Ranges
diff --git a/src/doc/unstable-book/src/compiler-flags/autodiff.md b/src/doc/unstable-book/src/compiler-flags/autodiff.md
new file mode 100644
index 00000000000..4e55be0ad95
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/autodiff.md
@@ -0,0 +1,23 @@
+# `autodiff`
+
+The tracking issue for this feature is: [#124509](https://github.com/rust-lang/rust/issues/124509).
+
+------------------------
+
+This feature allows you to differentiate functions using automatic differentiation.
+Set the `-Zautodiff=<options>` compiler flag to adjust the behaviour of the autodiff feature.
+Multiple options can be separated with a comma. Valid options are:
+
+`PrintTA` - print Type Analysis Information
+`PrintAA` - print Activity Analysis Information
+`PrintPerf` - print Performance Warnings from Enzyme
+`Print` - prints all intermediate transformations
+`PrintModBefore` - print the whole module, before running opts
+`PrintModAfterOpts` - print the whole module just before we pass it to Enzyme
+`PrintModAfterEnzyme` - print the module after Enzyme differentiated everything
+`LooseTypes` - Enzyme's loose type debug helper (can cause incorrect gradients)
+`Inline` - runs Enzyme specific Inlining
+`NoModOptAfter` - do not optimize the module after Enzyme is done
+`EnableFncOpt` - tell Enzyme to run LLVM Opts on each function it generated
+`NoVecUnroll` - do not unroll vectorized loops
+`RuntimeActivity` - allow specifying activity at runtime
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 80bc6cebd2a..cfba7895208 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -33,6 +33,7 @@ pub(crate) enum OutputFormat {
     Json,
     #[default]
     Html,
+    Doctest,
 }
 
 impl OutputFormat {
@@ -48,6 +49,7 @@ impl TryFrom<&str> for OutputFormat {
         match value {
             "json" => Ok(OutputFormat::Json),
             "html" => Ok(OutputFormat::Html),
+            "doctest" => Ok(OutputFormat::Doctest),
             _ => Err(format!("unknown output format `{value}`")),
         }
     }
@@ -445,14 +447,42 @@ impl Options {
             }
         }
 
+        let show_coverage = matches.opt_present("show-coverage");
+        let output_format_s = matches.opt_str("output-format");
+        let output_format = match output_format_s {
+            Some(ref s) => match OutputFormat::try_from(s.as_str()) {
+                Ok(out_fmt) => out_fmt,
+                Err(e) => dcx.fatal(e),
+            },
+            None => OutputFormat::default(),
+        };
+
         // check for `--output-format=json`
-        if !matches!(matches.opt_str("output-format").as_deref(), None | Some("html"))
-            && !matches.opt_present("show-coverage")
-            && !nightly_options::is_unstable_enabled(matches)
-        {
-            dcx.fatal(
-                "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)",
-            );
+        match (
+            output_format_s.as_ref().map(|_| output_format),
+            show_coverage,
+            nightly_options::is_unstable_enabled(matches),
+        ) {
+            (None | Some(OutputFormat::Json), true, _) => {}
+            (_, true, _) => {
+                dcx.fatal(format!(
+                    "`--output-format={}` is not supported for the `--show-coverage` option",
+                    output_format_s.unwrap_or_default(),
+                ));
+            }
+            // If `-Zunstable-options` is used, nothing to check after this point.
+            (_, false, true) => {}
+            (None | Some(OutputFormat::Html), false, _) => {}
+            (Some(OutputFormat::Json), false, false) => {
+                dcx.fatal(
+                    "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)",
+                );
+            }
+            (Some(OutputFormat::Doctest), false, false) => {
+                dcx.fatal(
+                    "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/134529)",
+                );
+            }
         }
 
         let to_check = matches.opt_strs("check-theme");
@@ -704,8 +734,6 @@ impl Options {
             })
             .collect();
 
-        let show_coverage = matches.opt_present("show-coverage");
-
         let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
             Ok(types) => types,
             Err(e) => {
@@ -713,20 +741,6 @@ impl Options {
             }
         };
 
-        let output_format = match matches.opt_str("output-format") {
-            Some(s) => match OutputFormat::try_from(s.as_str()) {
-                Ok(out_fmt) => {
-                    if !out_fmt.is_json() && show_coverage {
-                        dcx.fatal(
-                            "html output format isn't supported for the --show-coverage option",
-                        );
-                    }
-                    out_fmt
-                }
-                Err(e) => dcx.fatal(e),
-            },
-            None => OutputFormat::default(),
-        };
         let crate_name = matches.opt_str("crate-name");
         let bin_crate = crate_types.contains(&CrateType::Executable);
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 8c3e28ecec3..8b522e614b8 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1,3 +1,4 @@
+mod extracted;
 mod make;
 mod markdown;
 mod runner;
@@ -30,7 +31,7 @@ use tempfile::{Builder as TempFileBuilder, TempDir};
 use tracing::debug;
 
 use self::rust::HirCollector;
-use crate::config::Options as RustdocOptions;
+use crate::config::{Options as RustdocOptions, OutputFormat};
 use crate::html::markdown::{ErrorCodes, Ignore, LangString, MdRelLine};
 use crate::lint::init_lints;
 
@@ -209,15 +210,8 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
     let args_path = temp_dir.path().join("rustdoc-cfgs");
     crate::wrap_return(dcx, generate_args_file(&args_path, &options));
 
-    let CreateRunnableDocTests {
-        standalone_tests,
-        mergeable_tests,
-        rustdoc_options,
-        opts,
-        unused_extern_reports,
-        compiling_test_count,
-        ..
-    } = interface::run_compiler(config, |compiler| {
+    let extract_doctests = options.output_format == OutputFormat::Doctest;
+    let result = interface::run_compiler(config, |compiler| {
         let krate = rustc_interface::passes::parse(&compiler.sess);
 
         let collector = rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| {
@@ -226,22 +220,53 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
             let opts = scrape_test_config(crate_name, crate_attrs, args_path);
             let enable_per_target_ignores = options.enable_per_target_ignores;
 
-            let mut collector = CreateRunnableDocTests::new(options, opts);
             let hir_collector = HirCollector::new(
                 ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()),
                 enable_per_target_ignores,
                 tcx,
             );
             let tests = hir_collector.collect_crate();
-            tests.into_iter().for_each(|t| collector.add_test(t));
+            if extract_doctests {
+                let mut collector = extracted::ExtractedDocTests::new();
+                tests.into_iter().for_each(|t| collector.add_test(t, &opts, &options));
+
+                let stdout = std::io::stdout();
+                let mut stdout = stdout.lock();
+                if let Err(error) = serde_json::ser::to_writer(&mut stdout, &collector) {
+                    eprintln!();
+                    Err(format!("Failed to generate JSON output for doctests: {error:?}"))
+                } else {
+                    Ok(None)
+                }
+            } else {
+                let mut collector = CreateRunnableDocTests::new(options, opts);
+                tests.into_iter().for_each(|t| collector.add_test(t));
 
-            collector
+                Ok(Some(collector))
+            }
         });
         compiler.sess.dcx().abort_if_errors();
 
         collector
     });
 
+    let CreateRunnableDocTests {
+        standalone_tests,
+        mergeable_tests,
+        rustdoc_options,
+        opts,
+        unused_extern_reports,
+        compiling_test_count,
+        ..
+    } = match result {
+        Ok(Some(collector)) => collector,
+        Ok(None) => return,
+        Err(error) => {
+            eprintln!("{error}");
+            std::process::exit(1);
+        }
+    };
+
     run_tests(opts, &rustdoc_options, &unused_extern_reports, standalone_tests, mergeable_tests);
 
     let compiling_test_count = compiling_test_count.load(Ordering::SeqCst);
diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs
new file mode 100644
index 00000000000..03c8814a4c9
--- /dev/null
+++ b/src/librustdoc/doctest/extracted.rs
@@ -0,0 +1,141 @@
+//! Rustdoc's doctest extraction.
+//!
+//! This module contains the logic to extract doctests and output a JSON containing this
+//! information.
+
+use serde::Serialize;
+
+use super::{DocTestBuilder, ScrapedDocTest};
+use crate::config::Options as RustdocOptions;
+use crate::html::markdown;
+
+/// The version of JSON output that this code generates.
+///
+/// This integer is incremented with every breaking change to the API,
+/// and is returned along with the JSON blob into the `format_version` root field.
+/// Consuming code should assert that this value matches the format version(s) that it supports.
+const FORMAT_VERSION: u32 = 1;
+
+#[derive(Serialize)]
+pub(crate) struct ExtractedDocTests {
+    format_version: u32,
+    doctests: Vec<ExtractedDocTest>,
+}
+
+impl ExtractedDocTests {
+    pub(crate) fn new() -> Self {
+        Self { format_version: FORMAT_VERSION, doctests: Vec::new() }
+    }
+
+    pub(crate) fn add_test(
+        &mut self,
+        scraped_test: ScrapedDocTest,
+        opts: &super::GlobalTestOptions,
+        options: &RustdocOptions,
+    ) {
+        let edition = scraped_test.edition(&options);
+
+        let ScrapedDocTest { filename, line, langstr, text, name } = scraped_test;
+
+        let doctest = DocTestBuilder::new(
+            &text,
+            Some(&opts.crate_name),
+            edition,
+            false,
+            None,
+            Some(&langstr),
+        );
+        let (full_test_code, size) = doctest.generate_unique_doctest(
+            &text,
+            langstr.test_harness,
+            &opts,
+            Some(&opts.crate_name),
+        );
+        self.doctests.push(ExtractedDocTest {
+            file: filename.prefer_remapped_unconditionaly().to_string(),
+            line,
+            doctest_attributes: langstr.into(),
+            doctest_code: if size != 0 { Some(full_test_code) } else { None },
+            original_code: text,
+            name,
+        });
+    }
+}
+
+#[derive(Serialize)]
+pub(crate) struct ExtractedDocTest {
+    file: String,
+    line: usize,
+    doctest_attributes: LangString,
+    original_code: String,
+    /// `None` if the code syntax is invalid.
+    doctest_code: Option<String>,
+    name: String,
+}
+
+#[derive(Serialize)]
+pub(crate) enum Ignore {
+    All,
+    None,
+    Some(Vec<String>),
+}
+
+impl From<markdown::Ignore> for Ignore {
+    fn from(original: markdown::Ignore) -> Self {
+        match original {
+            markdown::Ignore::All => Self::All,
+            markdown::Ignore::None => Self::None,
+            markdown::Ignore::Some(values) => Self::Some(values),
+        }
+    }
+}
+
+#[derive(Serialize)]
+struct LangString {
+    pub(crate) original: String,
+    pub(crate) should_panic: bool,
+    pub(crate) no_run: bool,
+    pub(crate) ignore: Ignore,
+    pub(crate) rust: bool,
+    pub(crate) test_harness: bool,
+    pub(crate) compile_fail: bool,
+    pub(crate) standalone_crate: bool,
+    pub(crate) error_codes: Vec<String>,
+    pub(crate) edition: Option<String>,
+    pub(crate) added_css_classes: Vec<String>,
+    pub(crate) unknown: Vec<String>,
+}
+
+impl From<markdown::LangString> for LangString {
+    fn from(original: markdown::LangString) -> Self {
+        let markdown::LangString {
+            original,
+            should_panic,
+            no_run,
+            ignore,
+            rust,
+            test_harness,
+            compile_fail,
+            standalone_crate,
+            error_codes,
+            edition,
+            added_classes,
+            unknown,
+        } = original;
+
+        Self {
+            original,
+            should_panic,
+            no_run,
+            ignore: ignore.into(),
+            rust,
+            test_harness,
+            compile_fail,
+            standalone_crate,
+            error_codes,
+            edition: edition.map(|edition| edition.to_string()),
+            added_css_classes: added_classes,
+            unknown,
+        }
+    }
+}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index bb954a31891..44adf92ff0e 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -814,7 +814,12 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
         }
     };
 
-    match (options.should_test, config::markdown_input(&input)) {
+    let output_format = options.output_format;
+
+    match (
+        options.should_test || output_format == config::OutputFormat::Doctest,
+        config::markdown_input(&input),
+    ) {
         (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)),
         (true, None) => return doctest::run(dcx, input, options),
         (false, Some(md_input)) => {
@@ -849,7 +854,6 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
     // plug/cleaning passes.
     let crate_version = options.crate_version.clone();
 
-    let output_format = options.output_format;
     let scrape_examples_options = options.scrape_examples_options.clone();
     let bin_crate = options.bin_crate;
 
@@ -899,6 +903,8 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
                 config::OutputFormat::Json => sess.time("render_json", || {
                     run_renderer::<json::JsonRenderer<'_>>(krate, render_opts, cache, tcx)
                 }),
+                // Already handled above with doctest runners.
+                config::OutputFormat::Doctest => unreachable!(),
             }
         })
     })
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 8201f332d33..c548f262a92 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -166,6 +166,8 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
         // MIR passes can be enabled / disabled separately, we should figure out, what passes to
         // use for Clippy.
         config.opts.unstable_opts.mir_opt_level = Some(0);
+        config.opts.unstable_opts.mir_enable_passes =
+            vec![("CheckNull".to_owned(), false), ("CheckAlignment".to_owned(), false)];
 
         // Disable flattening and inlining of format_args!(), so the HIR matches with the AST.
         config.opts.unstable_opts.flatten_format_args = false;
diff --git a/src/tools/enzyme b/src/tools/enzyme
-Subproject 2fe5164a2423dd67ef25e2c4fb204fd06362494
+Subproject 0e5fa4a3d475f4dece489c9e06b11164f83789f
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 0be981f70b0..86928a6e6e8 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-6c1d960d88dd3755548b3818630acb63fa98187e
+9709af79014a150df7807671e6250ed940c488eb
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 2c4cb4bfce7..18a5a0612bb 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -904,10 +904,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 new_perm: NewPermission,
             ) -> InterpResult<'tcx> {
                 let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
-                let val = self.ecx.sb_retag_reference(&val, new_perm, RetagInfo {
-                    cause: self.retag_cause,
-                    in_field: self.in_field,
-                })?;
+                let val = self.ecx.sb_retag_reference(
+                    &val,
+                    new_perm,
+                    RetagInfo { cause: self.retag_cause, in_field: self.in_field },
+                )?;
                 self.ecx.write_immediate(*val, place)?;
                 interp_ok(())
             }
@@ -996,10 +997,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             access: Some(AccessKind::Write),
             protector: Some(ProtectorKind::StrongProtector),
         };
-        this.sb_retag_place(place, new_perm, RetagInfo {
-            cause: RetagCause::InPlaceFnPassing,
-            in_field: false,
-        })
+        this.sb_retag_place(
+            place,
+            new_perm,
+            RetagInfo { cause: RetagCause::InPlaceFnPassing, in_field: false },
+        )
     }
 
     /// Mark the given tag as exposed. It was found on a pointer with the given AllocId.
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
index 5d7c3d8c219..5c12ce39d10 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
@@ -379,14 +379,18 @@ pub mod diagnostics {
     use super::*;
     impl fmt::Display for PermissionPriv {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            write!(f, "{}", match self {
-                ReservedFrz { conflicted: false } => "Reserved",
-                ReservedFrz { conflicted: true } => "Reserved (conflicted)",
-                ReservedIM => "Reserved (interior mutable)",
-                Active => "Active",
-                Frozen => "Frozen",
-                Disabled => "Disabled",
-            })
+            write!(
+                f,
+                "{}",
+                match self {
+                    ReservedFrz { conflicted: false } => "Reserved",
+                    ReservedFrz { conflicted: true } => "Reserved (conflicted)",
+                    ReservedIM => "Reserved (interior mutable)",
+                    Active => "Active",
+                    Frozen => "Frozen",
+                    Disabled => "Disabled",
+                }
+            )
         }
     }
 
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index fd69278f20a..3389b1c602c 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -581,15 +581,18 @@ impl Tree {
             let mut debug_info = NodeDebugInfo::new(root_tag, root_default_perm, span);
             // name the root so that all allocations contain one named pointer
             debug_info.add_name("root of the allocation");
-            nodes.insert(root_idx, Node {
-                tag: root_tag,
-                parent: None,
-                children: SmallVec::default(),
-                default_initial_perm: root_default_perm,
-                // The root may never be skipped, all accesses will be local.
-                default_initial_idempotent_foreign_access: IdempotentForeignAccess::None,
-                debug_info,
-            });
+            nodes.insert(
+                root_idx,
+                Node {
+                    tag: root_tag,
+                    parent: None,
+                    children: SmallVec::default(),
+                    default_initial_perm: root_default_perm,
+                    // The root may never be skipped, all accesses will be local.
+                    default_initial_idempotent_foreign_access: IdempotentForeignAccess::None,
+                    debug_info,
+                },
+            );
             nodes
         };
         let rperms = {
@@ -624,14 +627,17 @@ impl<'tcx> Tree {
         let parent_idx = self.tag_mapping.get(&parent_tag).unwrap();
         let strongest_idempotent = default_initial_perm.strongest_idempotent_foreign_access(prot);
         // Create the node
-        self.nodes.insert(idx, Node {
-            tag: new_tag,
-            parent: Some(parent_idx),
-            children: SmallVec::default(),
-            default_initial_perm,
-            default_initial_idempotent_foreign_access: strongest_idempotent,
-            debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span),
-        });
+        self.nodes.insert(
+            idx,
+            Node {
+                tag: new_tag,
+                parent: Some(parent_idx),
+                children: SmallVec::default(),
+                default_initial_perm,
+                default_initial_idempotent_foreign_access: strongest_idempotent,
+                debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span),
+            },
+        );
         // Register new_tag as a child of parent_tag
         self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
         // Initialize perms
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index aeadba0d46e..5d3204a527f 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -169,7 +169,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
     "-Zmir-emit-retag",
     "-Zmir-keep-place-mention",
     "-Zmir-opt-level=0",
-    "-Zmir-enable-passes=-CheckAlignment",
+    "-Zmir-enable-passes=-CheckAlignment,-CheckNull",
     // Deduplicating diagnostics means we miss events when tracking what happens during an
     // execution. Let's not do that.
     "-Zdeduplicate-diagnostics=no",
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 845ba484326..5cb6640bf89 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1111,10 +1111,13 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         // Call the lang item.
         let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap();
         let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
-        ecx.call_function(panic, ExternAbi::Rust, &[], None, StackPopCleanup::Goto {
-            ret: None,
-            unwind: mir::UnwindAction::Unreachable,
-        })?;
+        ecx.call_function(
+            panic,
+            ExternAbi::Rust,
+            &[],
+            None,
+            StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
+        )?;
         interp_ok(())
     }
 
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
index f0aebfe1693..20dd3c8db2a 100644
--- a/src/tools/miri/src/shims/extern_static.rs
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -60,10 +60,10 @@ impl<'tcx> MiriMachine<'tcx> {
 
         match ecx.tcx.sess.target.os.as_ref() {
             "linux" => {
-                Self::null_ptr_extern_statics(ecx, &[
-                    "__cxa_thread_atexit_impl",
-                    "__clock_gettime64",
-                ])?;
+                Self::null_ptr_extern_statics(
+                    ecx,
+                    &["__cxa_thread_atexit_impl", "__clock_gettime64"],
+                )?;
                 Self::weak_symbol_extern_statics(ecx, &["getrandom", "statx"])?;
             }
             "freebsd" => {
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 93479540009..83f331bb173 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -247,10 +247,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Call the lang item associated with this message.
                 let fn_item = this.tcx.require_lang_item(msg.panic_function(), None);
                 let instance = ty::Instance::mono(this.tcx.tcx, fn_item);
-                this.call_function(instance, ExternAbi::Rust, &[], None, StackPopCleanup::Goto {
-                    ret: None,
-                    unwind,
-                })?;
+                this.call_function(
+                    instance,
+                    ExternAbi::Rust,
+                    &[],
+                    None,
+                    StackPopCleanup::Goto { ret: None, unwind },
+                )?;
             }
         }
         interp_ok(())
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
index 23e2122ee50..dc3ab2828fa 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs
@@ -230,10 +230,10 @@ fn test_two_same_fd_in_same_epoll_instance() {
     //Two notification should be received.
     let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
     let expected_value = 5 as u64;
-    check_epoll_wait::<8>(epfd, &[
-        (expected_event, expected_value),
-        (expected_event, expected_value),
-    ]);
+    check_epoll_wait::<8>(
+        epfd,
+        &[(expected_event, expected_value), (expected_event, expected_value)],
+    );
 }
 
 fn test_epoll_eventfd() {
@@ -290,10 +290,10 @@ fn test_epoll_socketpair_both_sides() {
     let expected_value0 = fds[0] as u64;
     let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap();
     let expected_value1 = fds[1] as u64;
-    check_epoll_wait::<8>(epfd, &[
-        (expected_event0, expected_value0),
-        (expected_event1, expected_value1),
-    ]);
+    check_epoll_wait::<8>(
+        epfd,
+        &[(expected_event0, expected_value0), (expected_event1, expected_value1)],
+    );
 
     // Read from fds[0].
     let mut buf: [u8; 5] = [0; 5];
@@ -453,10 +453,10 @@ fn test_socketpair_read() {
     let expected_value0 = fds[0] as u64;
     let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap();
     let expected_value1 = fds[1] as u64;
-    check_epoll_wait::<8>(epfd, &[
-        (expected_event0, expected_value0),
-        (expected_event1, expected_value1),
-    ]);
+    check_epoll_wait::<8>(
+        epfd,
+        &[(expected_event0, expected_value0), (expected_event1, expected_value1)],
+    );
 
     // Read 3 bytes from fds[0].
     let mut buf: [u8; 3] = [0; 3];
diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs
index 61410f7c4e0..f100c4d6a86 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.rs
+++ b/src/tools/miri/tests/pass/dyn-upcast.rs
@@ -10,6 +10,8 @@ fn main() {
     replace_vptr();
     vtable_nop_cast();
     drop_principal();
+    modulo_binder();
+    modulo_assoc();
 }
 
 fn vtable_nop_cast() {
@@ -482,3 +484,53 @@ fn drop_principal() {
     println!("before");
     drop(y);
 }
+
+// Test for <https://github.com/rust-lang/rust/issues/135316>.
+fn modulo_binder() {
+    trait Supertrait<T> {
+        fn _print_numbers(&self, mem: &[usize; 100]) {
+            println!("{mem:?}");
+        }
+    }
+    impl<T> Supertrait<T> for () {}
+
+    trait Trait<T, U>: Supertrait<T> + Supertrait<U> {
+        fn say_hello(&self, _: &usize) {
+            println!("Hello!");
+        }
+    }
+    impl<T, U> Trait<T, U> for () {}
+
+    (&() as &'static dyn for<'a> Trait<&'static (), &'a ()>
+        as &'static dyn Trait<&'static (), &'static ()>)
+        .say_hello(&0);
+}
+
+// Test for <https://github.com/rust-lang/rust/issues/135315>.
+fn modulo_assoc() {
+    trait Supertrait<T> {
+        fn _print_numbers(&self, mem: &[usize; 100]) {
+            println!("{mem:?}");
+        }
+    }
+    impl<T> Supertrait<T> for () {}
+
+    trait Identity {
+        type Selff;
+    }
+    impl<Selff> Identity for Selff {
+        type Selff = Selff;
+    }
+
+    trait Middle<T>: Supertrait<()> + Supertrait<T> {
+        fn say_hello(&self, _: &usize) {
+            println!("Hello!");
+        }
+    }
+    impl<T> Middle<T> for () {}
+
+    trait Trait: Middle<<() as Identity>::Selff> {}
+    impl Trait for () {}
+
+    (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
+}
diff --git a/src/tools/miri/tests/pass/dyn-upcast.stdout b/src/tools/miri/tests/pass/dyn-upcast.stdout
index edd99a114a1..379600db3d9 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.stdout
+++ b/src/tools/miri/tests/pass/dyn-upcast.stdout
@@ -2,3 +2,5 @@ before
 goodbye
 before
 goodbye
+Hello!
+Hello!
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index a3760d306f8..3bc953c3a5f 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -129,22 +129,25 @@ fn miri_config(
     config.comment_defaults.base().add_custom("edition", Edition("2021".into()));
 
     if let Some(WithDependencies { bless }) = with_dependencies {
-        config.comment_defaults.base().set_custom("dependencies", DependencyBuilder {
-            program: CommandBuilder {
-                // Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary.
-                // (It's a separate crate, so we don't get an env var from cargo.)
-                program: miri_path()
-                    .with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)),
-                // There is no `cargo miri build` so we just use `cargo miri run`.
-                args: ["miri", "run"].into_iter().map(Into::into).collect(),
-                // Reset `RUSTFLAGS` to work around <https://github.com/rust-lang/rust/pull/119574#issuecomment-1876878344>.
-                envs: vec![("RUSTFLAGS".into(), None)],
-                ..CommandBuilder::cargo()
+        config.comment_defaults.base().set_custom(
+            "dependencies",
+            DependencyBuilder {
+                program: CommandBuilder {
+                    // Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary.
+                    // (It's a separate crate, so we don't get an env var from cargo.)
+                    program: miri_path()
+                        .with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)),
+                    // There is no `cargo miri build` so we just use `cargo miri run`.
+                    args: ["miri", "run"].into_iter().map(Into::into).collect(),
+                    // Reset `RUSTFLAGS` to work around <https://github.com/rust-lang/rust/pull/119574#issuecomment-1876878344>.
+                    envs: vec![("RUSTFLAGS".into(), None)],
+                    ..CommandBuilder::cargo()
+                },
+                crate_manifest_path: Path::new("test_dependencies").join("Cargo.toml"),
+                build_std: None,
+                bless_lockfile: bless,
             },
-            crate_manifest_path: Path::new("test_dependencies").join("Cargo.toml"),
-            build_std: None,
-            bless_lockfile: bless,
-        });
+        );
     }
     config
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index e83ce6dc42c..38733577d1c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -411,6 +411,7 @@ language_item_table! {
     PanicLocation,           sym::panic_location,      panic_location,             Target::Struct,         GenericRequirement::None;
     PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn,             GenericRequirement::None;
     PanicCannotUnwind,       sym::panic_cannot_unwind, panic_cannot_unwind,        Target::Fn,             GenericRequirement::Exact(0);
+    PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
     /// libstd panic entry point. Necessary for const eval to be able to catch it
     BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn,             GenericRequirement::None;
 
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index 9bc78ff87b8..ae1c6efe0cb 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -363,6 +363,7 @@ define_symbols! {
     panic_location,
     panic_misaligned_pointer_dereference,
     panic_nounwind,
+    panic_null_pointer_dereference,
     panic,
     Param,
     parse,
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index 34984798ae6..28df49b9304 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/src/bin/main.rs
@@ -817,7 +817,6 @@ mod test {
         options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]);
         let config = get_config(None, Some(options));
         assert_eq!(config.style_edition(), StyleEdition::Edition2024);
-        assert_eq!(config.overflow_delimited_expr(), true);
     }
 
     #[nightly_only_test]
@@ -827,7 +826,6 @@ mod test {
         let config_file = Some(Path::new("tests/config/style-edition/just-version"));
         let config = get_config(config_file, Some(options));
         assert_eq!(config.style_edition(), StyleEdition::Edition2024);
-        assert_eq!(config.overflow_delimited_expr(), true);
     }
 
     #[nightly_only_test]
@@ -872,7 +870,6 @@ mod test {
         ]);
         let config = get_config(None, Some(options));
         assert_eq!(config.style_edition(), StyleEdition::Edition2024);
-        assert_eq!(config.overflow_delimited_expr(), true);
     }
 
     #[nightly_only_test]
@@ -938,7 +935,6 @@ mod test {
         options.style_edition = Some(StyleEdition::Edition2024);
         let config = get_config(None, Some(options));
         assert_eq!(config.style_edition(), StyleEdition::Edition2024);
-        assert_eq!(config.overflow_delimited_expr(), true);
     }
 
     #[nightly_only_test]
@@ -948,6 +944,8 @@ mod test {
         let config_file = Some(Path::new("tests/config/style-edition/overrides"));
         let config = get_config(config_file, Some(options));
         assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        // FIXME: this test doesn't really exercise anything, since
+        // `overflow_delimited_expr` is disabled by default in edition 2024.
         assert_eq!(config.overflow_delimited_expr(), false);
     }
 
@@ -959,7 +957,8 @@ mod test {
         options.inline_config =
             HashMap::from([("overflow_delimited_expr".to_owned(), "false".to_owned())]);
         let config = get_config(config_file, Some(options));
-        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        // FIXME: this test doesn't really exercise anything, since
+        // `overflow_delimited_expr` is disabled by default in edition 2024.
         assert_eq!(config.overflow_delimited_expr(), false);
     }
 }
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index 7355adc9f9d..6b63108c037 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -848,7 +848,7 @@ binop_separator = "Front"
 remove_nested_parens = true
 combine_control_expr = true
 short_array_element_width_threshold = 10
-overflow_delimited_expr = true
+overflow_delimited_expr = false
 struct_field_align_threshold = 0
 enum_discrim_align_threshold = 0
 match_arm_blocks = true
diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs
index bbc99a2dced..71865ec75ce 100644
--- a/src/tools/rustfmt/src/config/options.rs
+++ b/src/tools/rustfmt/src/config/options.rs
@@ -627,7 +627,7 @@ config_option_with_style_edition_default!(
     RemoveNestedParens, bool, _ => true;
     CombineControlExpr, bool, _ => true;
     ShortArrayElementWidthThreshold, usize, _ => 10;
-    OverflowDelimitedExpr, bool, Edition2024 => true, _ => false;
+    OverflowDelimitedExpr, bool, _ => false;
     StructFieldAlignThreshold, usize, _ => 0;
     EnumDiscrimAlignThreshold, usize, _ => 0;
     MatchArmBlocks, bool, _ => true;
@@ -644,7 +644,7 @@ config_option_with_style_edition_default!(
     BlankLinesLowerBound, usize, _ => 0;
     EditionConfig, Edition, _ => Edition::Edition2015;
     StyleEditionConfig, StyleEdition,
-        Edition2024 =>  StyleEdition::Edition2024, _ => StyleEdition::Edition2015;
+        Edition2024 => StyleEdition::Edition2024, _ => StyleEdition::Edition2015;
     VersionConfig, Version, Edition2024 => Version::Two, _ => Version::One;
     InlineAttributeWidth, usize, _ => 0;
     FormatGeneratedFiles, bool, _ => true;
diff --git a/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs
index ecd2e8ca797..1b2d12ce320 100644
--- a/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs
+++ b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs
@@ -25,10 +25,13 @@ fn combine_blocklike() {
         y: value2,
     });
 
-    do_thing(x, Bar {
-        x: value,
-        y: value2,
-    });
+    do_thing(
+        x,
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
 
     do_thing(
         x,
@@ -46,12 +49,15 @@ fn combine_blocklike() {
         value4_with_longer_name,
     ]);
 
-    do_thing(x, &[
-        value_with_longer_name,
-        value2_with_longer_name,
-        value3_with_longer_name,
-        value4_with_longer_name,
-    ]);
+    do_thing(
+        x,
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
 
     do_thing(
         x,
@@ -71,12 +77,15 @@ fn combine_blocklike() {
         value4_with_longer_name,
     ]);
 
-    do_thing(x, vec![
-        value_with_longer_name,
-        value2_with_longer_name,
-        value3_with_longer_name,
-        value4_with_longer_name,
-    ]);
+    do_thing(
+        x,
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
 
     do_thing(
         x,
@@ -99,22 +108,28 @@ fn combine_blocklike() {
 }
 
 fn combine_struct_sample() {
-    let identity = verify(&ctx, VerifyLogin {
-        type_: LoginType::Username,
-        username: args.username.clone(),
-        password: Some(args.password.clone()),
-        domain: None,
-    })?;
+    let identity = verify(
+        &ctx,
+        VerifyLogin {
+            type_: LoginType::Username,
+            username: args.username.clone(),
+            password: Some(args.password.clone()),
+            domain: None,
+        },
+    )?;
 }
 
 fn combine_macro_sample() {
     rocket::ignite()
-        .mount("/", routes![
-            http::auth::login,
-            http::auth::logout,
-            http::cors::options,
-            http::action::dance,
-            http::action::sleep,
-        ])
+        .mount(
+            "/",
+            routes![
+                http::auth::login,
+                http::auth::logout,
+                http::cors::options,
+                http::action::dance,
+                http::action::sleep,
+            ],
+        )
         .launch();
 }
diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs
index f10f01274b1..14bc4b8ab28 100644
--- a/tests/codegen/addr-of-mutate.rs
+++ b/tests/codegen/addr-of-mutate.rs
@@ -5,7 +5,7 @@
 // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
 // See <https://github.com/rust-lang/rust/issues/111502>.
 
-// CHECK: i8 @foo(ptr noalias nocapture noundef align 1 dereferenceable(128) %x)
+// CHECK: i8 @foo(ptr noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x)
 #[no_mangle]
 pub fn foo(x: [u8; 128]) -> u8 {
     let ptr = core::ptr::addr_of!(x).cast_mut();
@@ -15,7 +15,7 @@ pub fn foo(x: [u8; 128]) -> u8 {
     x[0]
 }
 
-// CHECK: i1 @second(ptr noalias nocapture noundef align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+// CHECK: i1 @second(ptr noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
 #[no_mangle]
 pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
     let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
@@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
 }
 
 // If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
-// CHECK: i1 @third(ptr noalias nocapture noundef readonly align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+// CHECK: i1 @third(ptr noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
 #[no_mangle]
 pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
     let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
diff --git a/tests/codegen/asm/bpf-clobbers.rs b/tests/codegen/asm/bpf-clobbers.rs
new file mode 100644
index 00000000000..1117549b1ec
--- /dev/null
+++ b/tests/codegen/asm/bpf-clobbers.rs
@@ -0,0 +1,31 @@
+//@ add-core-stubs
+//@ compile-flags: --target bpfel-unknown-none
+//@ needs-llvm-components: bpf
+
+#![crate_type = "rlib"]
+#![feature(no_core, asm_experimental_arch)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: @flags_clobber
+// CHECK: call void asm sideeffect "", ""()
+#[no_mangle]
+pub unsafe fn flags_clobber() {
+    asm!("", options(nostack, nomem));
+}
+
+// CHECK-LABEL: @no_clobber
+// CHECK: call void asm sideeffect "", ""()
+#[no_mangle]
+pub unsafe fn no_clobber() {
+    asm!("", options(nostack, nomem, preserves_flags));
+}
+
+// CHECK-LABEL: @clobber_abi
+// CHECK: asm sideeffect "", "={r0},={r1},={r2},={r3},={r4},={r5}"()
+#[no_mangle]
+pub unsafe fn clobber_abi() {
+    asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
+}
diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs
index db76aae3dd0..b3a35cbf3b1 100644
--- a/tests/codegen/cast-target-abi.rs
+++ b/tests/codegen/cast-target-abi.rs
@@ -392,7 +392,7 @@ pub fn call_fiveu16s() {
 }
 
 // CHECK-LABEL: @return_fiveu16s
-// CHECK-SAME: (ptr {{.+}} sret([10 x i8]) align [[RUST_ALIGN:2]] dereferenceable(10) [[RET_PTR:%.+]])
+// CHECK-SAME: (ptr {{.+}} sret([10 x i8]) align [[RUST_ALIGN:2]] {{.*}}dereferenceable(10) [[RET_PTR:%.+]])
 #[no_mangle]
 pub fn return_fiveu16s() -> FiveU16s {
     // powerpc returns this struct via sret pointer, it doesn't use the cast ABI.
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
index 503799d3ed2..1a211dfe096 100644
--- a/tests/codegen/function-arguments.rs
+++ b/tests/codegen/function-arguments.rs
@@ -135,7 +135,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {}
 #[no_mangle]
 pub fn notunpin_borrow(_: &NotUnpin) {}
 
-// CHECK: @indirect_struct(ptr noalias nocapture noundef readonly align 4 dereferenceable(32) %_1)
+// CHECK: @indirect_struct(ptr noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1)
 #[no_mangle]
 pub fn indirect_struct(_: S) {}
 
@@ -198,7 +198,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
     x
 }
 
-// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
+// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}})
 #[no_mangle]
 pub fn struct_return() -> S {
     S { _field: [0, 0, 0, 0, 0, 0, 0, 0] }
diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs
index 6b1da445c40..ac101b72513 100644
--- a/tests/codegen/i128-x86-align.rs
+++ b/tests/codegen/i128-x86-align.rs
@@ -19,8 +19,10 @@ pub struct ScalarPair {
 #[no_mangle]
 pub fn load(x: &ScalarPair) -> ScalarPair {
     // CHECK-LABEL: @load(
-    // CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0,
-    // CHECK-SAME: align 16 dereferenceable(32) %x
+    // CHECK-SAME: sret([32 x i8]) align 16
+    // CHECK-SAME: dereferenceable(32) %_0,
+    // CHECK-SAME: align 16
+    // CHECK-SAME: dereferenceable(32) %x
     // CHECK:      [[A:%.*]] = load i32, ptr %x, align 16
     // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16
     // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16
@@ -34,7 +36,8 @@ pub fn load(x: &ScalarPair) -> ScalarPair {
 #[no_mangle]
 pub fn store(x: &mut ScalarPair) {
     // CHECK-LABEL: @store(
-    // CHECK-SAME: align 16 dereferenceable(32) %x
+    // CHECK-SAME: align 16
+    // CHECK-SAME: dereferenceable(32) %x
     // CHECK:      store i32 1, ptr %x, align 16
     // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16
     // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16
@@ -55,8 +58,10 @@ pub fn alloca() {
 #[no_mangle]
 pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
     // CHECK-LABEL: @load_volatile(
-    // CHECK-SAME: sret([32 x i8]) align 16 dereferenceable(32) %_0,
-    // CHECK-SAME: align 16 dereferenceable(32) %x
+    // CHECK-SAME: sret([32 x i8]) align 16
+    // CHECK-SAME: dereferenceable(32) %_0,
+    // CHECK-SAME: align 16
+    // CHECK-SAME: dereferenceable(32) %x
     // CHECK:      [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16
     // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr %_0, align 16
     // CHECK-NEXT: ret void
@@ -66,7 +71,8 @@ pub fn load_volatile(x: &ScalarPair) -> ScalarPair {
 #[no_mangle]
 pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit<i128>, i128) {
     // CHECK-LABEL: @transmute(
-    // CHECK-SAME:  sret([32 x i8]) align 16 dereferenceable(32) %_0,
+    // CHECK-SAME:  sret([32 x i8]) align 16
+    // CHECK-SAME:  dereferenceable(32) %_0,
     // CHECK-SAME:  i32 noundef %x.0, i128 noundef %x.1
     // CHECK:       store i32 %x.0, ptr %_0, align 16
     // CHECK-NEXT:  [[GEP:%.*]] = getelementptr inbounds i8, ptr %_0, i64 16
@@ -86,7 +92,8 @@ pub struct Struct {
 #[no_mangle]
 pub fn store_struct(x: &mut Struct) {
     // CHECK-LABEL: @store_struct(
-    // CHECK-SAME: align 16 dereferenceable(32) %x
+    // CHECK-SAME: align 16
+    // CHECK-SAME: dereferenceable(32) %x
     // CHECK:      [[TMP:%.*]] = alloca [32 x i8], align 16
     // CHECK:      store i32 1, ptr [[TMP]], align 16
     // CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 4
diff --git a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
index cba1a980caa..b147d01b38e 100644
--- a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
+++ b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
@@ -259,11 +259,11 @@ pub struct IntDoubleInt {
     c: i32,
 }
 
-// CHECK: define void @f_int_double_int_s_arg(ptr noalias nocapture noundef align 8 dereferenceable(24) %a)
+// CHECK: define void @f_int_double_int_s_arg(ptr noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a)
 #[no_mangle]
 pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
 
-// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([24 x i8]) align 8 dereferenceable(24) %_0)
+// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(none\))?}} dereferenceable(24) %_0)
 #[no_mangle]
 pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
     IntDoubleInt { a: 1, b: 2., c: 3 }
diff --git a/tests/codegen/packed.rs b/tests/codegen/packed.rs
index 790d618b2ea..66df978d48c 100644
--- a/tests/codegen/packed.rs
+++ b/tests/codegen/packed.rs
@@ -52,7 +52,7 @@ pub struct BigPacked2 {
 #[no_mangle]
 pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
     // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8]
-    // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
+    // CHECK: call void %{{.*}}(ptr{{( captures(none))?}} noalias{{( nocapture)?}} noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
     // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
@@ -64,7 +64,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 #[no_mangle]
 pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
     // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8]
-    // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
+    // CHECK: call void %{{.*}}(ptr{{( captures(none))?}} noalias{{( nocapture)?}} noundef sret{{.*}} dereferenceable(32) [[ALLOCA]])
     // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
diff --git a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
index bcd9b0eae71..c14d5c01450 100644
--- a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
+++ b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
@@ -263,7 +263,7 @@ pub struct IntDoubleInt {
 #[no_mangle]
 pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
 
-// CHECK: define void @f_ret_int_double_int_s(ptr {{.*}} sret([24 x i8]) align 8 dereferenceable(24) %_0)
+// CHECK: define void @f_ret_int_double_int_s(ptr {{.*}} sret([24 x i8]) align 8 {{.*}}dereferenceable(24) %_0)
 #[no_mangle]
 pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
     IntDoubleInt { a: 1, b: 2., c: 3 }
diff --git a/tests/mir-opt/null_check_references.rs b/tests/mir-opt/null_check_references.rs
new file mode 100644
index 00000000000..85f98865646
--- /dev/null
+++ b/tests/mir-opt/null_check_references.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -C debug-assertions
+
+struct Null {
+    a: u32,
+}
+
+fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK-NOT: {{assert.*}}
+    let val: u32 = 42;
+    let val_ref: &u32 = &val;
+    let _access1: &u32 = &*val_ref;
+
+    let val = Null { a: 42 };
+    let _access2: &u32 = &val.a;
+}
diff --git a/tests/rustdoc-ui/coverage/html.stderr b/tests/rustdoc-ui/coverage/html.stderr
index adca375d4bc..764179820c5 100644
--- a/tests/rustdoc-ui/coverage/html.stderr
+++ b/tests/rustdoc-ui/coverage/html.stderr
@@ -1,2 +1,2 @@
-error: html output format isn't supported for the --show-coverage option
+error: `--output-format=html` is not supported for the `--show-coverage` option
 
diff --git a/tests/rustdoc-ui/doctest-output.rs b/tests/rustdoc-ui/doctest-output.rs
new file mode 100644
index 00000000000..720f2952980
--- /dev/null
+++ b/tests/rustdoc-ui/doctest-output.rs
@@ -0,0 +1 @@
+//@ compile-flags:-Z unstable-options --show-coverage --output-format=doctest
diff --git a/tests/rustdoc-ui/doctest-output.stderr b/tests/rustdoc-ui/doctest-output.stderr
new file mode 100644
index 00000000000..20c618dc61b
--- /dev/null
+++ b/tests/rustdoc-ui/doctest-output.stderr
@@ -0,0 +1,2 @@
+error: `--output-format=doctest` is not supported for the `--show-coverage` option
+
diff --git a/tests/rustdoc-ui/extract-doctests.rs b/tests/rustdoc-ui/extract-doctests.rs
new file mode 100644
index 00000000000..06bd35969d0
--- /dev/null
+++ b/tests/rustdoc-ui/extract-doctests.rs
@@ -0,0 +1,15 @@
+// Test to ensure that it generates expected output for `--output-format=doctest` command-line
+// flag.
+
+//@ compile-flags:-Z unstable-options --output-format=doctest
+//@ normalize-stdout: "tests/rustdoc-ui" -> "$$DIR"
+//@ check-pass
+
+//! ```ignore (checking attributes)
+//! let x = 12;
+//! let y = 14;
+//! ```
+//!
+//! ```edition2018,compile_fail
+//! let
+//! ```
diff --git a/tests/rustdoc-ui/extract-doctests.stdout b/tests/rustdoc-ui/extract-doctests.stdout
new file mode 100644
index 00000000000..fa8604cae94
--- /dev/null
+++ b/tests/rustdoc-ui/extract-doctests.stdout
@@ -0,0 +1 @@
+{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":"#![allow(unused)]\nfn main() {\nlet\n}","name":"$DIR/extract-doctests.rs - (line 13)"}]}
\ No newline at end of file
diff --git a/tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs b/tests/rustdoc-ui/intra-doc/auxiliary/issue-103463-aux.rs
index 2b8fdec1f12..2b8fdec1f12 100644
--- a/tests/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs
+++ b/tests/rustdoc-ui/intra-doc/auxiliary/issue-103463-aux.rs
diff --git a/tests/rustdoc/intra-doc/issue-104145.rs b/tests/rustdoc-ui/intra-doc/ice-extern-trait-local-impl-104145.rs
index 5690803af5a..0e403b21c8a 100644
--- a/tests/rustdoc/intra-doc/issue-104145.rs
+++ b/tests/rustdoc-ui/intra-doc/ice-extern-trait-local-impl-104145.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/104145
+//@ check-pass
+
 // Doc links in `Trait`'s methods are resolved because it has a local impl.
 
 //@ aux-build:issue-103463-aux.rs
diff --git a/tests/rustdoc/intra-doc/issue-103463.rs b/tests/rustdoc-ui/intra-doc/ice-priv-use-103463.rs
index 9b5cb67fd32..10894282e55 100644
--- a/tests/rustdoc/intra-doc/issue-103463.rs
+++ b/tests/rustdoc-ui/intra-doc/ice-priv-use-103463.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/103463
+//@ check-pass
+
 // The `Trait` is not pulled into the crate resulting in doc links in its methods being resolved.
 
 //@ aux-build:issue-103463-aux.rs
diff --git a/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr b/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr
index 180ba63927b..2c25589a553 100644
--- a/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr
+++ b/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr
@@ -99,7 +99,7 @@ LL | fn f<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
    |                    ^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/invalid_const_in_lifetime_position.rs:2:10
    |
 LL | trait X {
diff --git a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr
index 72d1a52f710..1e52b699820 100644
--- a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr
+++ b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr
@@ -301,7 +301,7 @@ LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/ice-generic-type-alias-105742.rs:15:17
    |
 LL |    pub trait SVec: Index<
diff --git a/tests/rustdoc/inline_cross/issue-28480.rs b/tests/rustdoc/inline_cross/doc-hidden-broken-link-28480.rs
index 004510fd922..e1ca7403c03 100644
--- a/tests/rustdoc/inline_cross/issue-28480.rs
+++ b/tests/rustdoc/inline_cross/doc-hidden-broken-link-28480.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/28480
+#![crate_name="foobar"]
+
 //@ aux-build:rustdoc-hidden-sig.rs
 //@ build-aux-docs
 //@ ignore-cross-compile
@@ -7,7 +10,7 @@
 //@ has -  '//a' 'u8'
 extern crate rustdoc_hidden_sig;
 
-//@ has issue_28480/struct.Bar.html
+//@ has foobar/struct.Bar.html
 //@ !has -  '//a/@title' 'Hidden'
 //@ has -  '//a' 'u8'
 pub use rustdoc_hidden_sig::Bar;
diff --git a/tests/rustdoc/inline_cross/issue-31948-1.rs b/tests/rustdoc/inline_cross/doc-reachability-impl-31948-1.rs
index e59da87c29d..baab1da9547 100644
--- a/tests/rustdoc/inline_cross/issue-31948-1.rs
+++ b/tests/rustdoc/inline_cross/doc-reachability-impl-31948-1.rs
@@ -1,27 +1,30 @@
+// https://github.com/rust-lang/rust/issues/31948
+#![crate_name="foobar"]
+
 //@ aux-build:rustdoc-nonreachable-impls.rs
 //@ build-aux-docs
 //@ ignore-cross-compile
 
 extern crate rustdoc_nonreachable_impls;
 
-//@ has issue_31948_1/struct.Wobble.html
+//@ has foobar/struct.Wobble.html
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
 //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
 //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
 pub use rustdoc_nonreachable_impls::hidden::Wobble;
 
-//@ has issue_31948_1/trait.Bark.html
+//@ has foobar/trait.Bark.html
 //@ has - '//h3[@class="code-header"]' 'for Foo'
 //@ has - '//h3[@class="code-header"]' 'for Wobble'
 //@ !has - '//h3[@class="code-header"]' 'for Wibble'
 pub use rustdoc_nonreachable_impls::Bark;
 
-//@ has issue_31948_1/trait.Woof.html
+//@ has foobar/trait.Woof.html
 //@ has - '//h3[@class="code-header"]' 'for Foo'
 //@ has - '//h3[@class="code-header"]' 'for Wobble'
 //@ !has - '//h3[@class="code-header"]' 'for Wibble'
 pub use rustdoc_nonreachable_impls::Woof;
 
-//@ !has issue_31948_1/trait.Bar.html
-//@ !has issue_31948_1/trait.Qux.html
+//@ !has foobar/trait.Bar.html
+//@ !has foobar/trait.Qux.html
diff --git a/tests/rustdoc/inline_cross/issue-31948-2.rs b/tests/rustdoc/inline_cross/doc-reachability-impl-31948-2.rs
index 34b57052883..40e9108ec62 100644
--- a/tests/rustdoc/inline_cross/issue-31948-2.rs
+++ b/tests/rustdoc/inline_cross/doc-reachability-impl-31948-2.rs
@@ -1,21 +1,24 @@
+// https://github.com/rust-lang/rust/issues/31948
+#![crate_name="foobar"]
+
 //@ aux-build:rustdoc-nonreachable-impls.rs
 //@ build-aux-docs
 //@ ignore-cross-compile
 
 extern crate rustdoc_nonreachable_impls;
 
-//@ has issue_31948_2/struct.Wobble.html
+//@ has foobar/struct.Wobble.html
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
 //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
 pub use rustdoc_nonreachable_impls::hidden::Wobble;
 
-//@ has issue_31948_2/trait.Qux.html
+//@ has foobar/trait.Qux.html
 //@ has - '//h3[@class="code-header"]' 'for Foo'
 //@ has - '//h3[@class="code-header"]' 'for Wobble'
 pub use rustdoc_nonreachable_impls::hidden::Qux;
 
-//@ !has issue_31948_2/trait.Bar.html
-//@ !has issue_31948_2/trait.Woof.html
-//@ !has issue_31948_2/trait.Bark.html
+//@ !has foobar/trait.Bar.html
+//@ !has foobar/trait.Woof.html
+//@ !has foobar/trait.Bark.html
diff --git a/tests/rustdoc/inline_cross/issue-31948.rs b/tests/rustdoc/inline_cross/doc-reachability-impl-31948.rs
index 7a43fc7b279..ab0048513c7 100644
--- a/tests/rustdoc/inline_cross/issue-31948.rs
+++ b/tests/rustdoc/inline_cross/doc-reachability-impl-31948.rs
@@ -1,29 +1,32 @@
+// https://github.com/rust-lang/rust/issues/31948
+#![crate_name="foobar"]
+
 //@ aux-build:rustdoc-nonreachable-impls.rs
 //@ build-aux-docs
 //@ ignore-cross-compile
 
 extern crate rustdoc_nonreachable_impls;
 
-//@ has issue_31948/struct.Foo.html
+//@ has foobar/struct.Foo.html
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
 //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
 //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
 //@ !has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
 pub use rustdoc_nonreachable_impls::Foo;
 
-//@ has issue_31948/trait.Bark.html
+//@ has foobar/trait.Bark.html
 //@ has - '//h3[@class="code-header"]' 'for Foo'
 //@ !has - '//h3[@class="code-header"]' 'for Wibble'
 //@ !has - '//h3[@class="code-header"]' 'for Wobble'
 pub use rustdoc_nonreachable_impls::Bark;
 
-//@ has issue_31948/trait.Woof.html
+//@ has foobar/trait.Woof.html
 //@ has - '//h3[@class="code-header"]' 'for Foo'
 //@ !has - '//h3[@class="code-header"]' 'for Wibble'
 //@ !has - '//h3[@class="code-header"]' 'for Wobble'
 pub use rustdoc_nonreachable_impls::Woof;
 
-//@ !has issue_31948/trait.Bar.html
-//@ !has issue_31948/trait.Qux.html
-//@ !has issue_31948/struct.Wibble.html
-//@ !has issue_31948/struct.Wobble.html
+//@ !has foobar/trait.Bar.html
+//@ !has foobar/trait.Qux.html
+//@ !has foobar/struct.Wibble.html
+//@ !has foobar/struct.Wobble.html
diff --git a/tests/rustdoc/inline_cross/issue-32881.rs b/tests/rustdoc/inline_cross/impl-dyn-trait-32881.rs
index d4ebf10a1ca..f7dc7414455 100644
--- a/tests/rustdoc/inline_cross/issue-32881.rs
+++ b/tests/rustdoc/inline_cross/impl-dyn-trait-32881.rs
@@ -1,10 +1,13 @@
+// https://github.com/rust-lang/rust/issues/32881
+#![crate_name="foobar"]
+
 //@ aux-build:rustdoc-trait-object-impl.rs
 //@ build-aux-docs
 //@ ignore-cross-compile
 
 extern crate rustdoc_trait_object_impl;
 
-//@ has issue_32881/trait.Bar.html
+//@ has foobar/trait.Bar.html
 //@ has - '//h3[@class="code-header"]' "impl<'a> dyn Bar"
 //@ has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar"
 
diff --git a/tests/rustdoc/inline_cross/issue-33113.rs b/tests/rustdoc/inline_cross/impl-ref-33113.rs
index 05e87d962cb..9ac4f02e00c 100644
--- a/tests/rustdoc/inline_cross/issue-33113.rs
+++ b/tests/rustdoc/inline_cross/impl-ref-33113.rs
@@ -1,10 +1,13 @@
+// https://github.com/rust-lang/rust/issues/33113
+#![crate_name="foobar"]
+
 //@ aux-build:issue-33113.rs
 //@ build-aux-docs
 //@ ignore-cross-compile
 
 extern crate bar;
 
-//@ has issue_33113/trait.Bar.html
+//@ has foobar/trait.Bar.html
 //@ has - '//h3[@class="code-header"]' "for &'a char"
 //@ has - '//h3[@class="code-header"]' "for Foo"
 pub use bar::Bar;
diff --git a/tests/rustdoc/inline_cross/issue-76736-1.rs b/tests/rustdoc/inline_cross/rustc-private-76736-1.rs
index fe52702fd6f..3ffa5e6cc06 100644
--- a/tests/rustdoc/inline_cross/issue-76736-1.rs
+++ b/tests/rustdoc/inline_cross/rustc-private-76736-1.rs
@@ -1,3 +1,5 @@
+// https://github.com/rust-lang/rust/issues/76736
+
 //@ aux-build:issue-76736-1.rs
 //@ aux-build:issue-76736-2.rs
 
diff --git a/tests/rustdoc/inline_cross/issue-76736-2.rs b/tests/rustdoc/inline_cross/rustc-private-76736-2.rs
index df376ebe9a1..843b2941602 100644
--- a/tests/rustdoc/inline_cross/issue-76736-2.rs
+++ b/tests/rustdoc/inline_cross/rustc-private-76736-2.rs
@@ -1,3 +1,5 @@
+// https://github.com/rust-lang/rust/issues/76736
+
 //@ aux-build:issue-76736-1.rs
 //@ aux-build:issue-76736-2.rs
 
diff --git a/tests/rustdoc/inline_cross/issue-76736-3.rs b/tests/rustdoc/inline_cross/rustc-private-76736-3.rs
index 1bed4621c04..f9b46caa02f 100644
--- a/tests/rustdoc/inline_cross/issue-76736-3.rs
+++ b/tests/rustdoc/inline_cross/rustc-private-76736-3.rs
@@ -1,3 +1,5 @@
+// https://github.com/rust-lang/rust/issues/76736
+
 //@ compile-flags: -Zforce-unstable-if-unmarked
 //@ aux-build:issue-76736-1.rs
 //@ aux-build:issue-76736-2.rs
diff --git a/tests/rustdoc/inline_cross/issue-76736-4.rs b/tests/rustdoc/inline_cross/rustc-private-76736-4.rs
index 487e9030108..511464f2c49 100644
--- a/tests/rustdoc/inline_cross/issue-76736-4.rs
+++ b/tests/rustdoc/inline_cross/rustc-private-76736-4.rs
@@ -1,3 +1,5 @@
+// https://github.com/rust-lang/rust/issues/76736
+
 //@ aux-build:issue-76736-1.rs
 //@ aux-build:issue-76736-2.rs
 
diff --git a/tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html b/tests/rustdoc/inline_cross/self-sized-bounds-24183.method_no_where_self_sized.html
index f3c1c045202..f3c1c045202 100644
--- a/tests/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
+++ b/tests/rustdoc/inline_cross/self-sized-bounds-24183.method_no_where_self_sized.html
diff --git a/tests/rustdoc/inline_cross/issue-24183.rs b/tests/rustdoc/inline_cross/self-sized-bounds-24183.rs
index 8299eecc575..909005532f5 100644
--- a/tests/rustdoc/inline_cross/issue-24183.rs
+++ b/tests/rustdoc/inline_cross/self-sized-bounds-24183.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/24183
 #![crate_type = "lib"]
 #![crate_name = "usr"]
 
diff --git a/tests/rustdoc/inline_local/issue-32343.rs b/tests/rustdoc/inline_local/doc-no-inline-32343.rs
index 2ec123fdc5c..ed11614a500 100644
--- a/tests/rustdoc/inline_local/issue-32343.rs
+++ b/tests/rustdoc/inline_local/doc-no-inline-32343.rs
@@ -1,12 +1,15 @@
-//@ !has issue_32343/struct.Foo.html
-//@ has issue_32343/index.html
+// https://github.com/rust-lang/rust/issues/32343
+#![crate_name="foobar"]
+
+//@ !has foobar/struct.Foo.html
+//@ has foobar/index.html
 //@ has - '//code' 'pub use foo::Foo'
 //@ !has - '//code/a' 'Foo'
 #[doc(no_inline)]
 pub use foo::Foo;
 
-//@ !has issue_32343/struct.Bar.html
-//@ has issue_32343/index.html
+//@ !has foobar/struct.Bar.html
+//@ has foobar/index.html
 //@ has - '//code' 'pub use foo::Bar'
 //@ has - '//code/a' 'Bar'
 #[doc(no_inline)]
@@ -18,6 +21,6 @@ mod foo {
 }
 
 pub mod bar {
-    //@ has issue_32343/bar/struct.Bar.html
+    //@ has foobar/bar/struct.Bar.html
     pub use ::foo::Bar;
 }
diff --git a/tests/rustdoc/inline_local/issue-28537.rs b/tests/rustdoc/inline_local/pub-re-export-28537.rs
index d5ba94d2e6c..0e9836c7cee 100644
--- a/tests/rustdoc/inline_local/issue-28537.rs
+++ b/tests/rustdoc/inline_local/pub-re-export-28537.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/28537
+#![crate_name="foo"]
+
 #[doc(hidden)]
 pub mod foo {
     pub struct Foo;
@@ -10,8 +13,8 @@ mod bar {
     }
 }
 
-//@ has issue_28537/struct.Foo.html
+//@ has foo/struct.Foo.html
 pub use foo::Foo;
 
-//@ has issue_28537/struct.Bar.html
+//@ has foo/struct.Bar.html
 pub use self::bar::Bar;
diff --git a/tests/rustdoc/intra-doc/issue-82209.rs b/tests/rustdoc/intra-doc/enum-self-82209.rs
index 46d028e535c..615115a5f8b 100644
--- a/tests/rustdoc/intra-doc/issue-82209.rs
+++ b/tests/rustdoc/intra-doc/enum-self-82209.rs
@@ -1,3 +1,5 @@
+// https://github.com/rust-lang/rust/issues/82209
+
 #![crate_name = "foo"]
 #![deny(rustdoc::broken_intra_doc_links)]
 pub enum Foo {
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/link-same-name-different-disambiguator-108459.rs
index 18424c069d3..0b339eaf6b2 100644
--- a/tests/rustdoc/intra-doc/issue-108459.rs
+++ b/tests/rustdoc/intra-doc/link-same-name-different-disambiguator-108459.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/pull/108459
+#![crate_name="foobar"]
+
 #![deny(rustdoc::broken_intra_doc_links)]
 #![allow(rustdoc::redundant_explicit_links)]
 
@@ -13,13 +16,13 @@ pub struct MyStruct1;
 // the same target but different text
 
 /// See also [crate::char] and [mod@char] and [prim@char]
-//@ has issue_108459/struct.MyStruct2.html '//*[@href="char/index.html"]' 'crate::char'
+//@ has foobar/struct.MyStruct2.html '//*[@href="char/index.html"]' 'crate::char'
 //@ has - '//*[@href="char/index.html"]' 'char'
 //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub struct MyStruct2;
 
 /// See also [mod@char] and [prim@char] and [crate::char]
-//@ has issue_108459/struct.MyStruct3.html '//*[@href="char/index.html"]' 'crate::char'
+//@ has foobar/struct.MyStruct3.html '//*[@href="char/index.html"]' 'crate::char'
 //@ has - '//*[@href="char/index.html"]' 'char'
 //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub struct MyStruct3;
@@ -28,11 +31,11 @@ pub struct MyStruct3;
 // different targets
 
 /// See also [char][mod@char] and [char][prim@char]
-//@ has issue_108459/struct.MyStruct4.html '//*[@href="char/index.html"]' 'char'
+//@ has foobar/struct.MyStruct4.html '//*[@href="char/index.html"]' 'char'
 //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub struct MyStruct4;
 
 /// See also [char][prim@char] and [char][crate::char]
-//@ has issue_108459/struct.MyStruct5.html '//*[@href="char/index.html"]' 'char'
+//@ has foobar/struct.MyStruct5.html '//*[@href="char/index.html"]' 'char'
 //@ has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub struct MyStruct5;
diff --git a/tests/rustdoc/intra-doc/issue-66159.rs b/tests/rustdoc/intra-doc/same-name-different-crates-66159.rs
index 5d50f63f299..7e3ace9355a 100644
--- a/tests/rustdoc/intra-doc/issue-66159.rs
+++ b/tests/rustdoc/intra-doc/same-name-different-crates-66159.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/66159
+#![crate_name="foobar"]
+
 //@ aux-crate:priv:pub_struct=pub-struct.rs
 //@ compile-flags:-Z unstable-options
 
@@ -6,5 +9,5 @@
 // Since we don't generate the docs for the auxiliary files, we can't actually
 // verify that the struct is linked correctly.
 
-//@ has issue_66159/index.html
+//@ has foobar/index.html
 //! [pub_struct::SomeStruct]
diff --git a/tests/ui/abi/segfault-no-out-of-stack.rs b/tests/ui/abi/segfault-no-out-of-stack.rs
index b5af13ebfb5..5e8b4e0dbf2 100644
--- a/tests/ui/abi/segfault-no-out-of-stack.rs
+++ b/tests/ui/abi/segfault-no-out-of-stack.rs
@@ -1,5 +1,6 @@
 //@ run-pass
 //@ needs-subprocess
+//@ compile-flags: -Zub-checks=no -Zmir-enable-passes=-CheckNull
 //@ ignore-fuchsia must translate zircon signal to SIGSEGV/SIGBUS, FIXME (#58590)
 
 #![feature(rustc_private)]
diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr
index 107ceeaf113..5aaa6f6be05 100644
--- a/tests/ui/associated-consts/associated-const-in-trait.stderr
+++ b/tests/ui/associated-consts/associated-const-in-trait.stderr
@@ -5,7 +5,7 @@ LL | impl dyn Trait {
    |      ^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/associated-const-in-trait.rs:4:11
    |
 LL | trait Trait {
@@ -21,7 +21,7 @@ LL |     const fn n() -> usize { Self::N }
    |                             ^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/associated-const-in-trait.rs:4:11
    |
 LL | trait Trait {
diff --git a/tests/ui/associated-item/issue-48027.stderr b/tests/ui/associated-item/issue-48027.stderr
index 1baaefd7720..513961e2bd0 100644
--- a/tests/ui/associated-item/issue-48027.stderr
+++ b/tests/ui/associated-item/issue-48027.stderr
@@ -5,7 +5,7 @@ LL | impl dyn Bar {}
    |      ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-48027.rs:2:11
    |
 LL | trait Bar {
diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr
index f9d2a669477..7d5b37bdbe7 100644
--- a/tests/ui/async-await/async-fn/dyn-pos.stderr
+++ b/tests/ui/async-await/async-fn/dyn-pos.stderr
@@ -5,7 +5,7 @@ LL | fn foo(x: &dyn AsyncFn()) {}
    |                ^^^^^^^^^ `AsyncFnMut` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
    |
    = note: the trait is not dyn compatible because it contains the generic associated type `CallRefFuture`
diff --git a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
index b60f6a08338..f478d55d10e 100644
--- a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
+++ b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
@@ -21,18 +21,14 @@ LL |         true
               found type `bool`
 
 error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to be a closure that returns `bool`, but it returns `Option<()>`
-  --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10
+  --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16
    |
-LL |       call(|| -> Option<()> {
-   |  _____----_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |         if true {
-LL | |             false
-...  |
-LL | |     })
-   | |_____^ expected `bool`, found `Option<()>`
+LL |     call(|| -> Option<()> {
+   |     ---- ------^^^^^^^^^^
+   |     |    |     |
+   |     |    |     expected `bool`, found `Option<()>`
+   |     |    this closure
+   |     required by a bound introduced by this call
    |
    = note: expected type `bool`
               found enum `Option<()>`
diff --git a/tests/ui/async-await/in-trait/dyn-compatibility.stderr b/tests/ui/async-await/in-trait/dyn-compatibility.stderr
index c6c406902f6..553bcbf89d5 100644
--- a/tests/ui/async-await/in-trait/dyn-compatibility.stderr
+++ b/tests/ui/async-await/in-trait/dyn-compatibility.stderr
@@ -5,7 +5,7 @@ LL |     let x: &dyn Foo = todo!();
    |            ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility.rs:5:14
    |
 LL | trait Foo {
diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr
index a674fc0f3a5..1fccc32470f 100644
--- a/tests/ui/async-await/inference_var_self_argument.stderr
+++ b/tests/ui/async-await/inference_var_self_argument.stderr
@@ -14,7 +14,7 @@ LL |     async fn foo(self: &dyn Foo) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/inference_var_self_argument.rs:5:14
    |
 LL | trait Foo {
diff --git a/tests/ui/closures/return-type-doesnt-match-bound.rs b/tests/ui/closures/return-type-doesnt-match-bound.rs
new file mode 100644
index 00000000000..f9098d0cb5c
--- /dev/null
+++ b/tests/ui/closures/return-type-doesnt-match-bound.rs
@@ -0,0 +1,25 @@
+use std::error::Error;
+use std::process::exit;
+
+fn foo<F>(f: F) -> ()
+where
+    F: FnOnce() -> Result<(), Box<dyn Error>>,
+{
+    f().or_else(|e| -> ! { //~ ERROR to be a closure that returns
+        eprintln!("{:?}", e);
+        exit(1)
+    });
+}
+
+fn bar<F>(f: F) -> ()
+where
+    F: FnOnce() -> Result<(), Box<dyn Error>>,
+{
+    let c = |e| -> ! { //~ ERROR to be a closure that returns
+        eprintln!("{:?}", e);
+        exit(1)
+    };
+    f().or_else(c);
+}
+
+fn main() {}
diff --git a/tests/ui/closures/return-type-doesnt-match-bound.stderr b/tests/ui/closures/return-type-doesnt-match-bound.stderr
new file mode 100644
index 00000000000..f796a5552ac
--- /dev/null
+++ b/tests/ui/closures/return-type-doesnt-match-bound.stderr
@@ -0,0 +1,37 @@
+error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:8:17}` to be a closure that returns `Result<(), _>`, but it returns `!`
+  --> $DIR/return-type-doesnt-match-bound.rs:8:24
+   |
+LL |     f().or_else(|e| -> ! {
+   |         ------- -------^
+   |         |       |      |
+   |         |       |      expected `Result<(), _>`, found `!`
+   |         |       this closure
+   |         required by a bound introduced by this call
+   |
+   = note: expected enum `Result<(), _>`
+              found type `!`
+note: required by a bound in `Result::<T, E>::or_else`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+
+error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:18:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
+  --> $DIR/return-type-doesnt-match-bound.rs:18:20
+   |
+LL |     let c = |e| -> ! {
+   |             -------^
+   |             |      |
+   |             |      expected `Result<(), _>`, found `!`
+   |             this closure
+...
+LL |     f().or_else(c);
+   |         ------- - closure used here
+   |         |
+   |         required by a bound introduced by this call
+   |
+   = note: expected enum `Result<(), _>`
+              found type `!`
+note: required by a bound in `Result::<T, E>::or_else`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr
index 20257bbaf28..033bfee226f 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr
@@ -5,7 +5,7 @@ LL | impl DynIncompatible for dyn DynIncompatible { }
    |                          ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:6:45
    |
 LL | trait DynIncompatible { fn eq(&self, other: Self); }
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr
index cd7f3a3c21d..6fa9b591ad2 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr
@@ -5,7 +5,7 @@ LL | fn foo(a: &dyn ConstParamTy_) {}
    |                ^^^^^^^^^^^^^ `ConstParamTy_` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: the trait is not dyn compatible because it uses `Self` as a type parameter
@@ -21,7 +21,7 @@ LL | fn bar(a: &dyn UnsizedConstParamTy) {}
    |                ^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: the trait is not dyn compatible because it uses `Self` as a type parameter
diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr
index 763bc626c9d..8bc6ef093d0 100644
--- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr
@@ -5,7 +5,7 @@ LL | fn use_dyn(v: &dyn Foo) {
    |                ^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility-err-ret.rs:8:8
    |
 LL | trait Foo {
@@ -24,7 +24,7 @@ LL |     v.test();
    |     ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility-err-ret.rs:8:8
    |
 LL | trait Foo {
diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr
index 56678e4e9af..f5eaaa37916 100644
--- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr
@@ -5,7 +5,7 @@ LL | fn use_dyn(v: &dyn Foo) {
    |                ^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8
    |
 LL | trait Foo {
@@ -22,7 +22,7 @@ LL |     v.test();
    |     ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8
    |
 LL | trait Foo {
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
index bd1811bd2cc..57b61006631 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
@@ -99,7 +99,7 @@ LL |     fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
    |                        ^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-102768.rs:5:10
    |
 LL | trait X {
diff --git a/tests/ui/consts/const-slice-array-deref.rs b/tests/ui/consts/const-slice-array-deref.rs
new file mode 100644
index 00000000000..9d84ed4bdb0
--- /dev/null
+++ b/tests/ui/consts/const-slice-array-deref.rs
@@ -0,0 +1,9 @@
+const ONE: [u16] = [1];
+//~^ ERROR the size for values of type `[u16]` cannot be known at compilation time
+//~| ERROR the size for values of type `[u16]` cannot be known at compilation time
+//~| ERROR mismatched types
+
+const TWO: &'static u16 = &ONE[0];
+//~^ ERROR cannot move a value of type `[u16]`
+
+fn main() {}
diff --git a/tests/ui/consts/const-slice-array-deref.stderr b/tests/ui/consts/const-slice-array-deref.stderr
new file mode 100644
index 00000000000..6e69744144e
--- /dev/null
+++ b/tests/ui/consts/const-slice-array-deref.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the size for values of type `[u16]` cannot be known at compilation time
+  --> $DIR/const-slice-array-deref.rs:1:12
+   |
+LL | const ONE: [u16] = [1];
+   |            ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u16]`
+
+error[E0308]: mismatched types
+  --> $DIR/const-slice-array-deref.rs:1:20
+   |
+LL | const ONE: [u16] = [1];
+   |                    ^^^ expected `[u16]`, found `[u16; 1]`
+
+error[E0277]: the size for values of type `[u16]` cannot be known at compilation time
+  --> $DIR/const-slice-array-deref.rs:1:20
+   |
+LL | const ONE: [u16] = [1];
+   |                    ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u16]`
+   = note: constant expressions must have a statically known size
+
+error[E0161]: cannot move a value of type `[u16]`
+  --> $DIR/const-slice-array-deref.rs:6:28
+   |
+LL | const TWO: &'static u16 = &ONE[0];
+   |                            ^^^ the size of `[u16]` cannot be statically determined
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0161, E0277, E0308.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/tests/ui/diagnostic-width/long-E0308.ascii.stderr b/tests/ui/diagnostic-width/long-E0308.ascii.stderr
index d45d6bf329b..3053e37a87a 100644
--- a/tests/ui/diagnostic-width/long-E0308.ascii.stderr
+++ b/tests/ui/diagnostic-width/long-E0308.ascii.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:46:9
+  --> $DIR/long-E0308.rs:48:9
    |
 LL |        let x: Atype<
    |  _____________-
@@ -20,11 +20,11 @@ LL |  |     ))))))))))))))))))))))))))))));
    |
    = note: expected struct `Atype<Btype<..., ...>, ...>`
                 found enum `Result<Result<..., ...>, ...>`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:59:26
+  --> $DIR/long-E0308.rs:61:26
    |
 LL |       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
    |  __________________________^
@@ -36,11 +36,11 @@ LL | |     ))))))))))))))))))))))));
    |
    = note: expected enum `Option<Result<..., ...>>`
               found enum `Result<Result<..., ...>, ...>`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:90:9
+  --> $DIR/long-E0308.rs:92:9
    |
 LL |       let x: Atype<
    |  ____________-
@@ -56,11 +56,11 @@ LL | |     > = ();
    |
    = note: expected struct `Atype<Btype<..., ...>, ...>`
            found unit type `()`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:93:17
+  --> $DIR/long-E0308.rs:95:17
    |
 LL |       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
    |  ____________--___^
@@ -74,7 +74,7 @@ LL | |     ))))))))))))))))))))))));
    |
    = note: expected unit type `()`
                    found enum `Result<Result<..., ...>, ...>`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs
index 93987226020..26383d9418d 100644
--- a/tests/ui/diagnostic-width/long-E0308.rs
+++ b/tests/ui/diagnostic-width/long-E0308.rs
@@ -1,7 +1,9 @@
 //@ revisions: ascii unicode
 //@[ascii] compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
 //@[unicode] compile-flags: -Zunstable-options --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
+
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 
 mod a {
     // Force the "short path for unique types" machinery to trip up
diff --git a/tests/ui/diagnostic-width/long-E0308.unicode.stderr b/tests/ui/diagnostic-width/long-E0308.unicode.stderr
index 3e8d881d7a6..50b386325b9 100644
--- a/tests/ui/diagnostic-width/long-E0308.unicode.stderr
+++ b/tests/ui/diagnostic-width/long-E0308.unicode.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:46:9
+   ╭▸ $DIR/long-E0308.rs:48:9

 LL │        let x: Atype<
    │ ┌─────────────┘
@@ -20,11 +20,11 @@ LL │  ┃     ))))))))))))))))))))))))))))));

    ├ note: expected struct `Atype<Btype<..., ...>, ...>`
    │            found enum `Result<Result<..., ...>, ...>`
-   ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+   ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:59:26
+   ╭▸ $DIR/long-E0308.rs:61:26

 LL │       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(…
    │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┛
@@ -36,11 +36,11 @@ LL │ ┃     ))))))))))))))))))))))));

    ├ note: expected enum `Option<Result<..., ...>>`
    │          found enum `Result<Result<..., ...>, ...>`
-   ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+   ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:90:9
+   ╭▸ $DIR/long-E0308.rs:92:9

 LL │       let x: Atype<
    │ ┌────────────┘
@@ -56,11 +56,11 @@ LL │ │     > = ();

    ├ note: expected struct `Atype<Btype<..., ...>, ...>`
    │       found unit type `()`
-   ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+   ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error[E0308]: mismatched types
-   ╭▸ $DIR/long-E0308.rs:93:17
+   ╭▸ $DIR/long-E0308.rs:95:17

 LL │       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(…
    │ ┏━━━━━━━━━━━━┬─━━━┛
@@ -74,7 +74,7 @@ LL │ ┃     ))))))))))))))))))))))));

    ├ note: expected unit type `()`
    │               found enum `Result<Result<..., ...>, ...>`
-   ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+   ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    ╰ note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.rs b/tests/ui/diagnostic-width/non-copy-type-moved.rs
index a5593ad7b2a..a220c62775e 100644
--- a/tests/ui/diagnostic-width/non-copy-type-moved.rs
+++ b/tests/ui/diagnostic-width/non-copy-type-moved.rs
@@ -1,5 +1,7 @@
 //@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+
 type A = (String, String, String, String);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.stderr b/tests/ui/diagnostic-width/non-copy-type-moved.stderr
index da9385a5b4d..889a2b3666d 100644
--- a/tests/ui/diagnostic-width/non-copy-type-moved.stderr
+++ b/tests/ui/diagnostic-width/non-copy-type-moved.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/non-copy-type-moved.rs:14:14
+  --> $DIR/non-copy-type-moved.rs:16:14
    |
 LL | fn foo(x: D) {
    |        - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait
@@ -8,7 +8,7 @@ LL |     let _a = x;
 LL |     let _b = x;
    |              ^ value used here after move
    |
-   = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/non-copy-type-moved/non-copy-type-moved.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 help: consider cloning the value if the performance cost is acceptable
    |
diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs
index 6ed600c48ac..4caa9424425 100644
--- a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs
+++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs
@@ -1,5 +1,7 @@
 //@ compile-flags: --diagnostic-width=100 -Zwrite-long-types-to-disk=yes
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr
index 1e890455156..346b112019f 100644
--- a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr
+++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/secondary-label-with-long-type.rs:9:9
+  --> $DIR/secondary-label-with-long-type.rs:11:9
    |
 LL |     let () = x;
    |         ^^   - this expression has type `((..., ..., ..., ...), ..., ..., ...)`
@@ -8,7 +8,7 @@ LL |     let () = x;
    |
    = note:  expected tuple `((..., ..., ..., ...), ..., ..., ...)`
            found unit type `()`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/secondary-label-with-long-type/secondary-label-with-long-type.long-type-hash.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
index 7994ddf11c3..4fee6cc9a22 100644
--- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
+++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
@@ -28,7 +28,7 @@ LL |     let _: &Copy + 'static;
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
-           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
index f241333f2a7..a384697ee08 100644
--- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
+++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
@@ -5,7 +5,7 @@ LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ {
    |                    ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/almost-supertrait-associated-type.rs:33:34
    |
 LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
@@ -22,7 +22,7 @@ LL |     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
    |                           ^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/almost-supertrait-associated-type.rs:33:34
    |
 LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
@@ -39,7 +39,7 @@ LL |     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
    |      ^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/almost-supertrait-associated-type.rs:33:34
    |
 LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
diff --git a/tests/ui/dyn-compatibility/associated-consts.curr.stderr b/tests/ui/dyn-compatibility/associated-consts.curr.stderr
index 45d4f795542..de243938123 100644
--- a/tests/ui/dyn-compatibility/associated-consts.curr.stderr
+++ b/tests/ui/dyn-compatibility/associated-consts.curr.stderr
@@ -5,7 +5,7 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                               ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/associated-consts.rs:9:11
    |
 LL | trait Bar {
@@ -21,7 +21,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/associated-consts.rs:9:11
    |
 LL | trait Bar {
diff --git a/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr
index 4c8c82196ed..704d833f00b 100644
--- a/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/associated-consts.rs:9:11
    |
 LL | trait Bar {
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr
index ff5e9fdb6b3..b811ef40c26 100644
--- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr
@@ -34,7 +34,7 @@ LL | fn id<F>(f: Copy) -> usize {
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
-           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 
 error[E0618]: expected function, found `(dyn Copy + 'static)`
   --> $DIR/avoid-ice-on-warning-2.rs:12:5
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr
index 92a2d340115..d8935be5609 100644
--- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr
@@ -72,7 +72,7 @@ LL | trait B { fn f(a: A) -> A; }
    |                   ^ `A` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/avoid-ice-on-warning-3.rs:14:14
    |
 LL | trait A { fn g(b: B) -> B; }
@@ -109,7 +109,7 @@ LL | trait A { fn g(b: B) -> B; }
    |                   ^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/avoid-ice-on-warning-3.rs:4:14
    |
 LL | trait B { fn f(a: A) -> A; }
diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr
index e3ec5b9c3c8..7be6cb0d03b 100644
--- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr
+++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr
@@ -23,7 +23,7 @@ LL | fn ord_prefer_dot(s: String) -> Ord {
    |                                 ^^^ `Ord` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: the trait is not dyn compatible because it uses `Self` as a type parameter
diff --git a/tests/ui/dyn-compatibility/bounds.stderr b/tests/ui/dyn-compatibility/bounds.stderr
index d45e66b1d5e..5473af388c0 100644
--- a/tests/ui/dyn-compatibility/bounds.stderr
+++ b/tests/ui/dyn-compatibility/bounds.stderr
@@ -5,7 +5,7 @@ LL | fn f() -> Box<dyn X<U = u32>> {
    |               ^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/bounds.rs:4:13
    |
 LL | trait X {
diff --git a/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr b/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr
index 04dc0b1d6f4..cfebd5d6947 100644
--- a/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr
+++ b/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr
@@ -5,7 +5,7 @@ LL | fn take_dyn(_: &dyn Child) {}
    |                     ^^^^^ `Super` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-incompatible-supertrait.rs:10:10
    |
 LL | trait Super {
diff --git a/tests/ui/dyn-compatibility/generics.curr.stderr b/tests/ui/dyn-compatibility/generics.curr.stderr
index 1607954ab70..d29d02b2ff3 100644
--- a/tests/ui/dyn-compatibility/generics.curr.stderr
+++ b/tests/ui/dyn-compatibility/generics.curr.stderr
@@ -5,7 +5,7 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                               ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
@@ -21,7 +21,7 @@ LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
    |                                        ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
@@ -37,7 +37,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
@@ -54,7 +54,7 @@ LL |     t as &dyn Bar
    |          ^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
@@ -70,7 +70,7 @@ LL |     t as &dyn Bar
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
diff --git a/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr
index 7f31b29b39c..b3565a766fe 100644
--- a/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
@@ -22,7 +22,7 @@ LL |     t as &dyn Bar
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generics.rs:10:8
    |
 LL | trait Bar {
diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
index 1ed78e1e659..bb3f7899bf1 100644
--- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
+++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
@@ -5,7 +5,7 @@ LL |     let test: &mut dyn Bar = &mut thing;
    |               ^^^^^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
    |
 LL |     fn foo<T>(&self, val: T);
@@ -23,7 +23,7 @@ LL |     let test: &mut dyn Bar = &mut thing;
    |                              ^^^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
    |
 LL |     fn foo<T>(&self, val: T);
diff --git a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr
index eba2c15dd74..cf3a7b23084 100644
--- a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr
+++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr
@@ -5,7 +5,7 @@ LL |     elements: Vec<Box<dyn Expr + 'x>>,
    |                           ^^^^ `Expr` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self-in-super-predicates.rs:5:21
    |
 LL | trait Expr: Debug + PartialEq {
@@ -20,7 +20,7 @@ LL |     let a: Box<dyn Expr> = Box::new(SExpr::new());
    |                    ^^^^ `Expr` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self-in-super-predicates.rs:5:21
    |
 LL | trait Expr: Debug + PartialEq {
@@ -35,7 +35,7 @@ LL |     let b: Box<dyn Expr> = Box::new(SExpr::new());
    |                    ^^^^ `Expr` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self-in-super-predicates.rs:5:21
    |
 LL | trait Expr: Debug + PartialEq {
diff --git a/tests/ui/dyn-compatibility/mentions-Self.curr.stderr b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr
index 90db86ffef9..2d3fe5ce636 100644
--- a/tests/ui/dyn-compatibility/mentions-Self.curr.stderr
+++ b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr
@@ -5,7 +5,7 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                               ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self.rs:11:22
    |
 LL | trait Bar {
@@ -21,7 +21,7 @@ LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    |                               ^^^^^^^ `Baz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self.rs:15:22
    |
 LL | trait Baz {
@@ -37,7 +37,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self.rs:11:22
    |
 LL | trait Bar {
@@ -54,7 +54,7 @@ LL |     t
    |     ^ `Baz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self.rs:15:22
    |
 LL | trait Baz {
diff --git a/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr
index 4a50d3f07e4..91c26a86025 100644
--- a/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self.rs:11:22
    |
 LL | trait Bar {
@@ -22,7 +22,7 @@ LL |     t
    |     ^ `Baz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/mentions-Self.rs:15:22
    |
 LL | trait Baz {
diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr
index 3f550494b33..5a7560682f2 100644
--- a/tests/ui/dyn-compatibility/missing-assoc-type.stderr
+++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr
@@ -5,7 +5,7 @@ LL | fn bar(x: &dyn Foo) {}
    |                ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/missing-assoc-type.rs:2:10
    |
 LL | trait Foo {
diff --git a/tests/ui/dyn-compatibility/no-static.curr.stderr b/tests/ui/dyn-compatibility/no-static.curr.stderr
index 867c485053d..bf9b48e7a43 100644
--- a/tests/ui/dyn-compatibility/no-static.curr.stderr
+++ b/tests/ui/dyn-compatibility/no-static.curr.stderr
@@ -5,7 +5,7 @@ LL | fn diverges() -> Box<dyn Foo> {
    |                      ^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/no-static.rs:9:8
    |
 LL | trait Foo {
@@ -29,7 +29,7 @@ LL |     let b: Box<dyn Foo> = Box::new(Bar);
    |            ^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/no-static.rs:9:8
    |
 LL | trait Foo {
@@ -53,7 +53,7 @@ LL |     let b: Box<dyn Foo> = Box::new(Bar);
    |                           ^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/no-static.rs:9:8
    |
 LL | trait Foo {
diff --git a/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr
index 65608a9cca7..d5ad4510334 100644
--- a/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL |     let b: Box<dyn Foo> = Box::new(Bar);
    |                           ^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/no-static.rs:9:8
    |
 LL | trait Foo {
diff --git a/tests/ui/dyn-compatibility/sized-2.curr.stderr b/tests/ui/dyn-compatibility/sized-2.curr.stderr
index c8fd1056237..2d262072d5d 100644
--- a/tests/ui/dyn-compatibility/sized-2.curr.stderr
+++ b/tests/ui/dyn-compatibility/sized-2.curr.stderr
@@ -5,7 +5,7 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                               ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/sized-2.rs:9:18
    |
 LL | trait Bar
@@ -20,7 +20,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/sized-2.rs:9:18
    |
 LL | trait Bar
diff --git a/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr
index 477dacdf5a1..1fbc10c0c3f 100644
--- a/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/sized-2.rs:9:18
    |
 LL | trait Bar
diff --git a/tests/ui/dyn-compatibility/sized.curr.stderr b/tests/ui/dyn-compatibility/sized.curr.stderr
index d86ea9197b9..a197d967005 100644
--- a/tests/ui/dyn-compatibility/sized.curr.stderr
+++ b/tests/ui/dyn-compatibility/sized.curr.stderr
@@ -5,7 +5,7 @@ LL | fn make_bar<T: Bar>(t: &T) -> &dyn Bar {
    |                                ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/sized.rs:8:12
    |
 LL | trait Bar: Sized {
@@ -20,7 +20,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/sized.rs:8:12
    |
 LL | trait Bar: Sized {
diff --git a/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr
index b763173594b..350c8992c6f 100644
--- a/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL |     t
    |     ^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/sized.rs:8:12
    |
 LL | trait Bar: Sized {
diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr
index f5dea256469..8e139ee6b48 100644
--- a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr
+++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr
@@ -27,7 +27,7 @@ LL |     fn c(&self) -> dyn SuperTrait<T>;
    |                    ^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/supertrait-mentions-GAT.rs:4:10
    |
 LL |     type Gat<'a>
diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr
index f9ef0c9b2e0..a763649e9c6 100644
--- a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr
+++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr
@@ -25,7 +25,7 @@ LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    |                                   ^^^ `Baz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/supertrait-mentions-Self.rs:8:13
    |
 LL | trait Baz : Bar<Self> {
diff --git a/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr b/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr
index 8442314835e..7e80a1d2e42 100644
--- a/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr
+++ b/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr
@@ -5,7 +5,7 @@ LL | static FOO: &(dyn Qux + Sync) = "desc";
    |               ^^^^^^^^^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/taint-const-eval.rs:8:8
    |
 LL | trait Qux {
@@ -28,7 +28,7 @@ LL | static FOO: &(dyn Qux + Sync) = "desc";
    |                                 ^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/taint-const-eval.rs:8:8
    |
 LL | trait Qux {
@@ -52,7 +52,7 @@ LL | static FOO: &(dyn Qux + Sync) = "desc";
    |               ^^^^^^^^^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/taint-const-eval.rs:8:8
    |
 LL | trait Qux {
diff --git a/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr
index 1c51df8501f..0bc7d0b14d3 100644
--- a/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL | static FOO: &(dyn Qux + Sync) = "desc";
    |                                 ^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/taint-const-eval.rs:8:8
    |
 LL | trait Qux {
diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
index 45a924008c7..1299167159e 100644
--- a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
+++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
@@ -8,7 +8,7 @@ LL | fn fetcher() -> Box<dyn Fetcher> {
    |                     ^^^^^^^^^^^ `Fetcher` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
    |
 LL | pub trait Fetcher: Send + Sync {
@@ -26,7 +26,7 @@ LL |     let fetcher = fetcher();
    |                   ^^^^^^^^^ `Fetcher` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
    |
 LL | pub trait Fetcher: Send + Sync {
@@ -44,7 +44,7 @@ LL |     let _ = fetcher.get();
    |             ^^^^^^^^^^^^^ `Fetcher` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
    |
 LL | pub trait Fetcher: Send + Sync {
diff --git a/tests/ui/error-codes/E0038.stderr b/tests/ui/error-codes/E0038.stderr
index 59e9f504d17..63a5249a386 100644
--- a/tests/ui/error-codes/E0038.stderr
+++ b/tests/ui/error-codes/E0038.stderr
@@ -5,7 +5,7 @@ LL | fn call_foo(x: Box<dyn Trait>) {
    |                    ^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/E0038.rs:2:22
    |
 LL | trait Trait {
@@ -21,7 +21,7 @@ LL |     let y = x.foo();
    |             ^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/E0038.rs:2:22
    |
 LL | trait Trait {
diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
index b4de6b66469..ab8c092a826 100644
--- a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
+++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
@@ -5,7 +5,7 @@ LL | async fn takes_dyn_trait(x: &dyn Foo) {
    |                              ^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
    |
 LL | trait Foo {
@@ -21,7 +21,7 @@ LL |     x.bar().await;
    |       ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
    |
 LL | trait Foo {
@@ -37,7 +37,7 @@ LL |     x.bar().await;
    |     ^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
    |
 LL | trait Foo {
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
index f8fc086c441..6634ce12118 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
@@ -8,7 +8,7 @@ LL |     Ptr(Box::new(4)) as Ptr<dyn Trait>;
    |                         ^^^^^^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18
    |
 LL | trait Trait {
@@ -27,7 +27,7 @@ LL |     Ptr(Box::new(4)) as Ptr<dyn Trait>;
    |     ^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18
    |
 LL | trait Trait {
diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr
index 10540f0219d..2c3edd6e6a5 100644
--- a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr
@@ -5,7 +5,7 @@ LL | fn takes_dyn_incompatible_ref<T>(obj: &dyn DynIncompatible1) {
    |                                        ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25
    |
 LL | trait DynIncompatible1: Sized {}
@@ -20,7 +20,7 @@ LL | fn return_dyn_incompatible_ref() -> &'static dyn DynIncompatible2 {
    |                                              ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8
    |
 LL | trait DynIncompatible2 {
@@ -43,7 +43,7 @@ LL | fn takes_dyn_incompatible_box(obj: Box<dyn DynIncompatible3>) {
    |                                        ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8
    |
 LL | trait DynIncompatible3 {
@@ -59,7 +59,7 @@ LL | fn return_dyn_incompatible_rc() -> std::rc::Rc<dyn DynIncompatible4> {
    |                                                ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22
    |
 LL | trait DynIncompatible4 {
@@ -75,7 +75,7 @@ LL | impl Trait for dyn DynIncompatible1 {}
    |                ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25
    |
 LL | trait DynIncompatible1: Sized {}
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
index 4c5a47e73c6..c9b46de5c33 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
@@ -43,7 +43,7 @@ LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:2:8
    |
 LL | trait X {
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr
index df79556c825..e57f6b48401 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -5,7 +5,7 @@ LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-in-trait-path.rs:6:10
    |
 LL | trait Foo {
@@ -21,7 +21,7 @@ LL |   f(Box::new(foo));
    |     ^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-in-trait-path.rs:6:10
    |
 LL | trait Foo {
@@ -37,7 +37,7 @@ LL |   f(Box::new(foo));
    |     ^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-in-trait-path.rs:6:10
    |
 LL | trait Foo {
diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
index 499ce8e4a32..52fed354edf 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -130,7 +130,7 @@ LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |                     ^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-trait-path-parenthesised-args.rs:2:8
    |
 LL | trait X {
@@ -196,7 +196,7 @@ LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
    |                     ^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/gat-trait-path-parenthesised-args.rs:2:8
    |
 LL | trait X {
diff --git a/tests/ui/generic-associated-types/issue-67510-pass.stderr b/tests/ui/generic-associated-types/issue-67510-pass.stderr
index f6846f833fe..4b56c4ef35f 100644
--- a/tests/ui/generic-associated-types/issue-67510-pass.stderr
+++ b/tests/ui/generic-associated-types/issue-67510-pass.stderr
@@ -5,7 +5,7 @@ LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
    |                       ^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-67510-pass.rs:4:10
    |
 LL | trait X {
diff --git a/tests/ui/generic-associated-types/issue-67510.stderr b/tests/ui/generic-associated-types/issue-67510.stderr
index e8555a7aa1f..f5c494788ea 100644
--- a/tests/ui/generic-associated-types/issue-67510.stderr
+++ b/tests/ui/generic-associated-types/issue-67510.stderr
@@ -36,7 +36,7 @@ LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
    |             ^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-67510.rs:2:10
    |
 LL | trait X {
diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr
index a78151384d4..56439f6dfea 100644
--- a/tests/ui/generic-associated-types/issue-71176.stderr
+++ b/tests/ui/generic-associated-types/issue-71176.stderr
@@ -55,7 +55,7 @@ LL |   inner: Box<dyn Provider<A = B>>,
    |              ^^^^^^^^^^^^^^^^^^^ `Provider` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-71176.rs:2:10
    |
 LL | trait Provider {
@@ -72,7 +72,7 @@ LL |         inner: Box::new(()),
    |                ^^^^^^^^^^^^ `Provider` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-71176.rs:2:10
    |
 LL | trait Provider {
@@ -89,7 +89,7 @@ LL |         inner: Box::new(()),
    |                ^^^^^^^^^^^^ `Provider` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-71176.rs:2:10
    |
 LL | trait Provider {
diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr
index 6b7c3bfe731..b828234afa1 100644
--- a/tests/ui/generic-associated-types/issue-76535.stderr
+++ b/tests/ui/generic-associated-types/issue-76535.stderr
@@ -21,7 +21,7 @@ LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruc
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-76535.rs:4:10
    |
 LL | pub trait SuperTrait {
@@ -39,7 +39,7 @@ LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruc
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-76535.rs:4:10
    |
 LL | pub trait SuperTrait {
diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr
index c85e97067cb..c6da137672d 100644
--- a/tests/ui/generic-associated-types/issue-78671.stderr
+++ b/tests/ui/generic-associated-types/issue-78671.stderr
@@ -21,7 +21,7 @@ LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-78671.rs:2:10
    |
 LL | trait CollectionFamily {
diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr
index a81217e96c3..6311e4de272 100644
--- a/tests/ui/generic-associated-types/issue-79422.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.stderr
@@ -21,7 +21,7 @@ LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-79422.rs:18:10
    |
 LL | trait MapLike<K, V> {
@@ -37,7 +37,7 @@ LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-79422.rs:18:10
    |
 LL | trait MapLike<K, V> {
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.rs b/tests/ui/generic-associated-types/issue-90014-tait2.rs
index ef54a89aaae..3f7a9ff63c3 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait2.rs
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.rs
@@ -3,8 +3,6 @@
 //! Unfortunately we don't even reach opaque type collection, as we ICE in typeck before that.
 //! See #109281 for the original report.
 //@ edition:2018
-//@ error-pattern: expected generic lifetime parameter, found `'a`
-
 #![feature(type_alias_impl_trait)]
 
 use std::future::Future;
@@ -24,6 +22,7 @@ impl<'x, T: 'x> Trait<'x> for (T,) {
 impl Foo<'_> {
     fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> {
         Box::new((async { () },))
+        //~^ ERROR expected generic lifetime parameter, found `'a`
     }
 }
 
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
index be6f4272ce1..aa427d42649 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/issue-90014-tait2.rs:26:9
+  --> $DIR/issue-90014-tait2.rs:24:9
    |
 LL | type Fut<'a> = impl Future<Output = ()>;
    |          -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr
index 6b8df5cc12f..7b6888817f4 100644
--- a/tests/ui/generic-associated-types/missing_lifetime_args.stderr
+++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr
@@ -55,7 +55,7 @@ LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {}
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/missing_lifetime_args.rs:2:10
    |
 LL | trait X {
diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
index 5c9e9dbe3d7..45bca1a7628 100644
--- a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
+++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
@@ -99,7 +99,7 @@ LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
    |                       ^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/trait-path-type-error-once-implemented.rs:2:10
    |
 LL | trait X {
diff --git a/tests/ui/generic-associated-types/trait-objects.stderr b/tests/ui/generic-associated-types/trait-objects.stderr
index 56a1cb1906f..7d95718ec87 100644
--- a/tests/ui/generic-associated-types/trait-objects.stderr
+++ b/tests/ui/generic-associated-types/trait-objects.stderr
@@ -5,7 +5,7 @@ LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> u
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/trait-objects.rs:2:10
    |
 LL | trait StreamingIterator {
@@ -21,7 +21,7 @@ LL |     x.size_hint().0
    |       ^^^^^^^^^ `StreamingIterator` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/trait-objects.rs:2:10
    |
 LL | trait StreamingIterator {
@@ -37,7 +37,7 @@ LL |     x.size_hint().0
    |     ^^^^^^^^^^^^^ `StreamingIterator` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/trait-objects.rs:2:10
    |
 LL | trait StreamingIterator {
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs
index e70f6fc3430..f2b73d69261 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs
@@ -36,12 +36,10 @@ trait Ty<'a> {
 
 fn main() {
     let v = Unit2.m(
-        L {
-            //~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4`
-            //~| ERROR type mismatch
+        L { //~ ERROR type mismatch
             f: |x| {
                 drop(x);
-                Unit4
+                Unit4 //~ ERROR to be a closure that returns `Unit3`, but it returns `Unit4`
             },
         },
     );
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr
index 74610b55dc3..d0675d5020c 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr
@@ -1,16 +1,15 @@
-error[E0271]: type mismatch resolving `<L<{closure@issue-62203-hrtb-ice.rs:42:16}> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
+error[E0271]: type mismatch resolving `<L<{closure@issue-62203-hrtb-ice.rs:40:16}> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
   --> $DIR/issue-62203-hrtb-ice.rs:39:9
    |
 LL |       let v = Unit2.m(
    |                     - required by a bound introduced by this call
 LL | /         L {
-LL | |
-LL | |
 LL | |             f: |x| {
-...  |
+LL | |                 drop(x);
+LL | |                 Unit4
 LL | |             },
 LL | |         },
-   | |_________^ type mismatch resolving `<L<{closure@issue-62203-hrtb-ice.rs:42:16}> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
+   | |_________^ type mismatch resolving `<L<{closure@issue-62203-hrtb-ice.rs:40:16}> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
    |
 note: expected this to be `<_ as Ty<'_>>::V`
   --> $DIR/issue-62203-hrtb-ice.rs:21:14
@@ -30,21 +29,19 @@ LL |     where
 LL |         F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
    |                                                   ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
 
-error[E0271]: expected `{closure@issue-62203-hrtb-ice.rs:42:16}` to be a closure that returns `Unit3`, but it returns `Unit4`
-  --> $DIR/issue-62203-hrtb-ice.rs:39:9
-   |
-LL |       let v = Unit2.m(
-   |                     - required by a bound introduced by this call
-LL | /         L {
-LL | |
-LL | |
-LL | |             f: |x| {
-...  |
-LL | |             },
-LL | |         },
-   | |_________^ expected `Unit3`, found `Unit4`
-   |
-note: required for `L<{closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19}>` to implement `for<'r> T0<'r, (&'r u8,)>`
+error[E0271]: expected `{closure@issue-62203-hrtb-ice.rs:40:16}` to be a closure that returns `Unit3`, but it returns `Unit4`
+  --> $DIR/issue-62203-hrtb-ice.rs:42:17
+   |
+LL |     let v = Unit2.m(
+   |                   - required by a bound introduced by this call
+LL |         L {
+LL |             f: |x| {
+   |                --- this closure
+LL |                 drop(x);
+LL |                 Unit4
+   |                 ^^^^^ expected `Unit3`, found `Unit4`
+   |
+note: required for `L<{closure@$DIR/issue-62203-hrtb-ice.rs:40:16: 40:19}>` to implement `for<'r> T0<'r, (&'r u8,)>`
   --> $DIR/issue-62203-hrtb-ice.rs:17:16
    |
 LL | impl<'a, A, T> T0<'a, A> for L<T>
diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr
index fc3d9c2171d..183ee678d7a 100644
--- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr
@@ -5,7 +5,7 @@ LL |     let x: &dyn Foo = &();
    |                       ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/span-bug-issue-121597.rs:4:12
    |
 LL | trait Foo: for<T> Bar<T> {}
@@ -21,7 +21,7 @@ LL |     let x: &dyn Foo = &();
    |            ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/span-bug-issue-121597.rs:4:12
    |
 LL | trait Foo: for<T> Bar<T> {}
diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr
index 4abd7bcf31c..2869702d7fc 100644
--- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr
+++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr
@@ -5,7 +5,7 @@ LL | fn car() -> dyn DynIncompatible {
    |             ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8
    |
 LL | trait DynIncompatible {
@@ -33,7 +33,7 @@ LL | fn cat() -> Box<dyn DynIncompatible> {
    |                 ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8
    |
 LL | trait DynIncompatible {
@@ -78,7 +78,7 @@ LL |         return Box::new(A);
    |                ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8
    |
 LL | trait DynIncompatible {
@@ -107,7 +107,7 @@ LL |     Box::new(B)
    |     ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8
    |
 LL | trait DynIncompatible {
diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr
index 44ca09150fe..61fe9432a1e 100644
--- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr
+++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr
@@ -15,7 +15,7 @@ LL |         MyTrait::foo(&self)
    |         ^^^^^^^^^^^^ `MyTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22
    |
 LL | trait MyTrait {
@@ -40,7 +40,7 @@ LL | impl dyn MyTrait {
    |      ^^^^^^^^^^^ `MyTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22
    |
 LL | trait MyTrait {
@@ -57,7 +57,7 @@ LL |     fn other(&self) -> impl Marker {
    |               ^^^^ `MyTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22
    |
 LL | trait MyTrait {
diff --git a/tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.rs b/tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.rs
new file mode 100644
index 00000000000..fe73306966e
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.rs
@@ -0,0 +1,14 @@
+// There's a suggestion that turns `Iterator<u32>` into `Iterator<Item = u32>`
+// if we have more generics than the trait wants. Let's not consider RPITITs
+// for this, since that makes no sense right now.
+
+trait Foo {
+    fn bar(self) -> impl Sized;
+}
+
+impl Foo<u8> for () {
+    //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
+    fn bar(self) -> impl Sized {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.stderr b/tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.stderr
new file mode 100644
index 00000000000..fb497b89c5f
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-consider-unconstrained-rpitits.stderr
@@ -0,0 +1,17 @@
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/dont-consider-unconstrained-rpitits.rs:9:6
+   |
+LL | impl Foo<u8> for () {
+   |      ^^^---- help: remove the unnecessary generics
+   |      |
+   |      expected 0 generic arguments
+   |
+note: trait defined here, with 0 generic parameters
+  --> $DIR/dont-consider-unconstrained-rpitits.rs:5:7
+   |
+LL | trait Foo {
+   |       ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
index 87a5480b1e3..840c27e183f 100644
--- a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
+++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
@@ -5,7 +5,7 @@ LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
    |                                 ^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility.rs:4:22
    |
 LL | trait Foo {
@@ -22,7 +22,7 @@ LL |     let s = i.baz();
    |               ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility.rs:4:22
    |
 LL | trait Foo {
@@ -39,7 +39,7 @@ LL |     let s = i.baz();
    |             ^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility.rs:4:22
    |
 LL | trait Foo {
@@ -56,7 +56,7 @@ LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
    |             ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-compatibility.rs:4:22
    |
 LL | trait Foo {
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
index 07d09468b04..29235ca78a5 100644
--- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
@@ -5,7 +5,7 @@ LL |     let _: &dyn rpitit::Foo = todo!();
    |            ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/auxiliary/rpitit.rs:4:21
    |
 LL |     fn bar(self) -> impl Deref<Target = impl Sized>;
diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
index e28b8f373da..62fc079d9d9 100644
--- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
+++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
@@ -3,6 +3,9 @@
 //@ error-pattern: reached the recursion limit while instantiating
 //@ error-pattern: reached the recursion limit finding the struct tail
 
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
+
 // Regression test for #114484: This used to ICE during monomorphization, because we treated
 // `<VirtualWrapper<...> as Pointee>::Metadata` as a rigid projection after reaching the recursion
 // limit when finding the struct tail.
diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr
index 7c961b79c0c..b67e000bf74 100644
--- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr
+++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr
@@ -18,7 +18,7 @@ error: reached the recursion limit finding the struct tail for `[u8; 256]`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:29:18
    |
 LL |         unsafe { virtualize_my_trait(L, self) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ error: reached the recursion limit finding the struct tail for `SomeData<256>`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:29:18
    |
 LL |         unsafe { virtualize_my_trait(L, self) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@ error: reached the recursion limit finding the struct tail for `VirtualWrapper<S
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>`
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:29:18
    |
 LL |         unsafe { virtualize_my_trait(L, self) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,11 +76,11 @@ LL |         unsafe { virtualize_my_trait(L, self) }
 error: reached the recursion limit while instantiating `<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<..., 1>, 1>, 1>, 1>, 1> as MyTrait>::virtualize`
    |
 note: `<VirtualWrapper<T, L> as MyTrait>::virtualize` defined here
-  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:5
+  --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:28:5
    |
 LL |     fn virtualize(&self) -> &dyn MyTrait {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation-struct-tail-ice-114484/infinite-instantiation-struct-tail-ice-114484.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: aborting due to 13 previous errors
 
diff --git a/tests/ui/infinite/infinite-instantiation.rs b/tests/ui/infinite/infinite-instantiation.rs
index 7e1bff6b124..d5cb8e79592 100644
--- a/tests/ui/infinite/infinite-instantiation.rs
+++ b/tests/ui/infinite/infinite-instantiation.rs
@@ -1,5 +1,6 @@
 //@ build-fail
-//@ normalize-stderr: ".nll/" -> "/"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 trait ToOpt: Sized {
     fn to_option(&self) -> Option<Self>;
diff --git a/tests/ui/infinite/infinite-instantiation.stderr b/tests/ui/infinite/infinite-instantiation.stderr
index 43d267fa46b..71c745cf5eb 100644
--- a/tests/ui/infinite/infinite-instantiation.stderr
+++ b/tests/ui/infinite/infinite-instantiation.stderr
@@ -1,15 +1,15 @@
 error: reached the recursion limit while instantiating `function::<Option<Option<Option<Option<Option<...>>>>>>`
-  --> $DIR/infinite-instantiation.rs:22:9
+  --> $DIR/infinite-instantiation.rs:23:9
    |
 LL |         function(counter - 1, t.to_option());
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `function` defined here
-  --> $DIR/infinite-instantiation.rs:20:1
+  --> $DIR/infinite-instantiation.rs:21:1
    |
 LL | fn function<T:ToOpt + Clone>(counter: usize, t: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation/infinite-instantiation.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr
index 49d501c397f..c37c4177bfc 100644
--- a/tests/ui/issues/issue-18959.stderr
+++ b/tests/ui/issues/issue-18959.stderr
@@ -5,7 +5,7 @@ LL | fn foo(b: &dyn Bar) {
    |            ^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-18959.rs:1:20
    |
 LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
@@ -21,7 +21,7 @@ LL |     b.foo(&0)
    |     ^^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-18959.rs:1:20
    |
 LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
@@ -37,7 +37,7 @@ LL |     let test: &dyn Bar = &mut thing;
    |               ^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-18959.rs:1:20
    |
 LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
@@ -53,7 +53,7 @@ LL |     let test: &dyn Bar = &mut thing;
    |                          ^^^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-18959.rs:1:20
    |
 LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
@@ -70,7 +70,7 @@ LL |     foo(test);
    |         ^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-18959.rs:1:20
    |
 LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr
index 7d4812c3693..f8509891d3a 100644
--- a/tests/ui/issues/issue-19380.stderr
+++ b/tests/ui/issues/issue-19380.stderr
@@ -5,7 +5,7 @@ LL |   foos: &'static [&'static (dyn Qiz + 'static)]
    |                             ^^^^^^^^^^^^^^^^^ `Qiz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-19380.rs:2:6
    |
 LL | trait Qiz {
@@ -29,7 +29,7 @@ LL | const BAR : Bar = Bar { foos: &[&FOO]};
    |                                 ^^^^ `Qiz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-19380.rs:2:6
    |
 LL | trait Qiz {
@@ -54,7 +54,7 @@ LL | const BAR : Bar = Bar { foos: &[&FOO]};
    |                               ^^^^^^^ `Qiz` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-19380.rs:2:6
    |
 LL | trait Qiz {
diff --git a/tests/ui/issues/issue-26056.stderr b/tests/ui/issues/issue-26056.stderr
index d1cdf43351e..c2168af9496 100644
--- a/tests/ui/issues/issue-26056.stderr
+++ b/tests/ui/issues/issue-26056.stderr
@@ -5,7 +5,7 @@ LL |         as &dyn Map<Key=u32,MapValue=u32>;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-26056.rs:9:12
    |
 LL | trait Map: MapLookup<<Self as Map>::Key> {
diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs
index edf4f2fce26..ebaf244ac9c 100644
--- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs
+++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs
@@ -1,5 +1,6 @@
 //@ build-fail
-//@ normalize-stderr: ".nll/" -> "/"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 trait Mirror {
     type Image;
diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
index 84ed97572b3..fbbf80021be 100644
--- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
+++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
@@ -1,15 +1,15 @@
 error: reached the recursion limit while instantiating `<(&(&(..., ...), ...), ...) as Foo>::recurse`
-  --> $DIR/issue-37311.rs:17:9
+  --> $DIR/issue-37311.rs:18:9
    |
 LL |         (self, self).recurse();
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `<T as Foo>::recurse` defined here
-  --> $DIR/issue-37311.rs:16:5
+  --> $DIR/issue-37311.rs:17:5
    |
 LL |     fn recurse(&self) {
    |     ^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311/issue-37311.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr
index 293e9839944..88b83a83e0c 100644
--- a/tests/ui/issues/issue-50781.stderr
+++ b/tests/ui/issues/issue-50781.stderr
@@ -5,7 +5,7 @@ LL | impl Trait for dyn X {}
    |                ^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-50781.rs:4:8
    |
 LL | trait X {
@@ -22,7 +22,7 @@ LL |     <dyn X as X>::foo(&());
    |                       ^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-50781.rs:4:8
    |
 LL | trait X {
@@ -40,7 +40,7 @@ LL |     <dyn X as X>::foo(&());
    |      ^^^^^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-50781.rs:4:8
    |
 LL | trait X {
diff --git a/tests/ui/issues/issue-67552.rs b/tests/ui/issues/issue-67552.rs
index 343ae4f262f..8c7e95bd2e3 100644
--- a/tests/ui/issues/issue-67552.rs
+++ b/tests/ui/issues/issue-67552.rs
@@ -1,6 +1,7 @@
 //@ build-fail
 //@ compile-flags: -Copt-level=0
-//@ normalize-stderr: ".nll/" -> "/"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 fn main() {
     rec(Empty);
diff --git a/tests/ui/issues/issue-67552.stderr b/tests/ui/issues/issue-67552.stderr
index 1a8d7248b45..f94cd78c870 100644
--- a/tests/ui/issues/issue-67552.stderr
+++ b/tests/ui/issues/issue-67552.stderr
@@ -1,17 +1,17 @@
 error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut ...>`
-  --> $DIR/issue-67552.rs:29:9
+  --> $DIR/issue-67552.rs:30:9
    |
 LL |         rec(identity(&mut it))
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `rec` defined here
-  --> $DIR/issue-67552.rs:22:1
+  --> $DIR/issue-67552.rs:23:1
    |
 LL | / fn rec<T>(mut it: T)
 LL | | where
 LL | |     T: Iterator,
    | |________________^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552/issue-67552.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-8727.rs b/tests/ui/issues/issue-8727.rs
index b824be7c12f..7767729109e 100644
--- a/tests/ui/issues/issue-8727.rs
+++ b/tests/ui/issues/issue-8727.rs
@@ -2,7 +2,8 @@
 // recursions.
 
 //@ build-fail
-//@ normalize-stderr: ".nll/" -> "/"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 fn generic<T>() { //~ WARN function cannot return without recursing
     generic::<Option<T>>();
diff --git a/tests/ui/issues/issue-8727.stderr b/tests/ui/issues/issue-8727.stderr
index 9af598fe43f..22286eb8d7b 100644
--- a/tests/ui/issues/issue-8727.stderr
+++ b/tests/ui/issues/issue-8727.stderr
@@ -1,5 +1,5 @@
 warning: function cannot return without recursing
-  --> $DIR/issue-8727.rs:7:1
+  --> $DIR/issue-8727.rs:8:1
    |
 LL | fn generic<T>() {
    | ^^^^^^^^^^^^^^^ cannot return without recursing
@@ -10,17 +10,17 @@ LL |     generic::<Option<T>>();
    = note: `#[warn(unconditional_recursion)]` on by default
 
 error: reached the recursion limit while instantiating `generic::<Option<Option<Option<Option<Option<...>>>>>>`
-  --> $DIR/issue-8727.rs:8:5
+  --> $DIR/issue-8727.rs:9:5
    |
 LL |     generic::<Option<T>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `generic` defined here
-  --> $DIR/issue-8727.rs:7:1
+  --> $DIR/issue-8727.rs:8:1
    |
 LL | fn generic<T>() {
    | ^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727/issue-8727.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index 83446fc9ec0..95048c4454b 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -26,7 +26,7 @@ LL |     let z = &x as &dyn Foo;
    |                   ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/kindck-inherited-copy-bound.rs:10:13
    |
 LL | trait Foo : Copy {
@@ -41,7 +41,7 @@ LL |     let z = &x as &dyn Foo;
    |             ^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/kindck-inherited-copy-bound.rs:10:13
    |
 LL | trait Foo : Copy {
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr
index 271e5afb9e7..296f011193e 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr
@@ -26,7 +26,7 @@ LL |     let z = &x as &dyn Foo;
    |             ^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/kindck-inherited-copy-bound.rs:10:13
    |
 LL | trait Foo : Copy {
diff --git a/tests/ui/mir/null/addrof_null.rs b/tests/ui/mir/null/addrof_null.rs
new file mode 100644
index 00000000000..0d0b7edeef6
--- /dev/null
+++ b/tests/ui/mir/null/addrof_null.rs
@@ -0,0 +1,14 @@
+// Make sure that we don't insert a check for `addr_of!`.
+//@ run-pass
+//@ compile-flags: -C debug-assertions
+
+struct Field {
+    a: u32,
+}
+
+fn main() {
+    unsafe {
+        let ptr: *const Field = std::ptr::null();
+        let _ptr = core::ptr::addr_of!((*ptr).a);
+    }
+}
diff --git a/tests/ui/mir/null/borrowed_mut_null.rs b/tests/ui/mir/null/borrowed_mut_null.rs
new file mode 100644
index 00000000000..437955c452b
--- /dev/null
+++ b/tests/ui/mir/null/borrowed_mut_null.rs
@@ -0,0 +1,8 @@
+//@ run-fail
+//@ compile-flags: -C debug-assertions
+//@ error-pattern: null pointer dereference occured
+
+fn main() {
+    let ptr: *mut u32 = std::ptr::null_mut();
+    let _ptr: &mut u32 = unsafe { &mut *ptr };
+}
diff --git a/tests/ui/mir/null/borrowed_null.rs b/tests/ui/mir/null/borrowed_null.rs
new file mode 100644
index 00000000000..eb0794efaa5
--- /dev/null
+++ b/tests/ui/mir/null/borrowed_null.rs
@@ -0,0 +1,8 @@
+//@ run-fail
+//@ compile-flags: -C debug-assertions
+//@ error-pattern: null pointer dereference occured
+
+fn main() {
+    let ptr: *const u32 = std::ptr::null();
+    let _ptr: &u32 = unsafe { &*ptr };
+}
diff --git a/tests/ui/mir/null/null_lhs.rs b/tests/ui/mir/null/null_lhs.rs
new file mode 100644
index 00000000000..fd3bc3a78b8
--- /dev/null
+++ b/tests/ui/mir/null/null_lhs.rs
@@ -0,0 +1,10 @@
+//@ run-fail
+//@ compile-flags: -C debug-assertions
+//@ error-pattern: null pointer dereference occured
+
+fn main() {
+    let ptr: *mut u32 = std::ptr::null_mut();
+    unsafe {
+        *(ptr) = 42;
+    }
+}
diff --git a/tests/ui/mir/null/null_rhs.rs b/tests/ui/mir/null/null_rhs.rs
new file mode 100644
index 00000000000..45c8beb3fe8
--- /dev/null
+++ b/tests/ui/mir/null/null_rhs.rs
@@ -0,0 +1,10 @@
+//@ run-fail
+//@ compile-flags: -C debug-assertions
+//@ error-pattern: null pointer dereference occured
+
+fn main() {
+    let ptr: *mut u32 = std::ptr::null_mut();
+    unsafe {
+        let _v = *ptr;
+    }
+}
diff --git a/tests/ui/mir/null/place_without_read.rs b/tests/ui/mir/null/place_without_read.rs
new file mode 100644
index 00000000000..d6bfb089b01
--- /dev/null
+++ b/tests/ui/mir/null/place_without_read.rs
@@ -0,0 +1,10 @@
+// Make sure that we don't insert a check for places that do not read.
+//@ run-pass
+//@ compile-flags: -C debug-assertions
+
+fn main() {
+    let ptr: *const u16 = std::ptr::null();
+    unsafe {
+        let _ = *ptr;
+    }
+}
diff --git a/tests/ui/mir/null/two_pointers.rs b/tests/ui/mir/null/two_pointers.rs
new file mode 100644
index 00000000000..d9f0687fe0d
--- /dev/null
+++ b/tests/ui/mir/null/two_pointers.rs
@@ -0,0 +1,12 @@
+//@ run-fail
+//@ compile-flags: -C debug-assertions
+//@ error-pattern: null pointer dereference occured
+
+fn main() {
+    let ptr = std::ptr::null();
+    let mut dest = 0u32;
+    let dest_ptr = &mut dest as *mut u32;
+    unsafe {
+        *dest_ptr = *(ptr);
+    }
+}
diff --git a/tests/ui/mir/null/zero_sized_access.rs b/tests/ui/mir/null/zero_sized_access.rs
new file mode 100644
index 00000000000..e8aaf820c49
--- /dev/null
+++ b/tests/ui/mir/null/zero_sized_access.rs
@@ -0,0 +1,15 @@
+// Make sure that we don't insert a check for zero-sized reads or writes to
+// null, because they are allowed.
+//@ run-pass
+//@ compile-flags: -C debug-assertions
+
+fn main() {
+    let ptr: *mut () = std::ptr::null_mut();
+    unsafe {
+        *(ptr) = ();
+    }
+    let ptr1: *const () = std::ptr::null_mut();
+    unsafe {
+        let _ptr = *ptr1;
+    }
+}
diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr
index aa4a2760ffd..a559a95a334 100644
--- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr
+++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr
@@ -1,16 +1,15 @@
 error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to be a closure that returns `()`, but it returns `!`
-  --> $DIR/fallback-closure-wrap.rs:18:31
+  --> $DIR/fallback-closure-wrap.rs:19:9
    |
-LL |       let error = Closure::wrap(Box::new(move || {
-   |  _______________________________^
-LL | |
-LL | |         panic!("Can't connect to server.");
-LL | |     }) as Box<dyn FnMut()>);
-   | |______^ expected `()`, found `!`
+LL |     let error = Closure::wrap(Box::new(move || {
+   |                                        ------- this closure
+LL |         panic!("Can't connect to server.");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `!`
    |
    = note: expected unit type `()`
                    found type `!`
    = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box<dyn FnMut()>`
+   = note: this error originates in the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback-closure-wrap.rs
index 27020289c68..e97505b6bc0 100644
--- a/tests/ui/never_type/fallback-closure-wrap.rs
+++ b/tests/ui/never_type/fallback-closure-wrap.rs
@@ -16,8 +16,8 @@ use std::marker::PhantomData;
 
 fn main() {
     let error = Closure::wrap(Box::new(move || {
-        //[fallback]~^ to be a closure that returns `()`, but it returns `!`
         panic!("Can't connect to server.");
+        //[fallback]~^ to be a closure that returns `()`, but it returns `!`
     }) as Box<dyn FnMut()>);
 }
 
diff --git a/tests/ui/recursion/recursion.rs b/tests/ui/recursion/recursion.rs
index f3c633983b1..ce56fe974b7 100644
--- a/tests/ui/recursion/recursion.rs
+++ b/tests/ui/recursion/recursion.rs
@@ -1,6 +1,7 @@
 //@ build-fail
 //@ compile-flags:-C overflow-checks=off
-//@ normalize-stderr: ".nll/" -> "/"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
 
 enum Nil {NilValue}
 struct Cons<T> {head:isize, tail:T}
diff --git a/tests/ui/recursion/recursion.stderr b/tests/ui/recursion/recursion.stderr
index 7a9f04d4bd6..cb9f67ba741 100644
--- a/tests/ui/recursion/recursion.stderr
+++ b/tests/ui/recursion/recursion.stderr
@@ -1,15 +1,15 @@
 error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>`
-  --> $DIR/recursion.rs:18:11
+  --> $DIR/recursion.rs:19:11
    |
 LL |     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `test` defined here
-  --> $DIR/recursion.rs:16:1
+  --> $DIR/recursion.rs:17:1
    |
 LL | fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion/recursion.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/resolve/issue-3907-2.stderr b/tests/ui/resolve/issue-3907-2.stderr
index 4ab72a42eb8..40cdfb7a302 100644
--- a/tests/ui/resolve/issue-3907-2.stderr
+++ b/tests/ui/resolve/issue-3907-2.stderr
@@ -5,7 +5,7 @@ LL | fn bar(_x: Foo) {}
    |            ^^^ `issue_3907::Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/auxiliary/issue-3907.rs:2:8
    |
 LL |     fn bar();
diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr
index 3e018995ba5..8382b4867e2 100644
--- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr
+++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr
@@ -8,7 +8,7 @@ LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
    |                                ^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18
    |
 LL | trait Foo {
@@ -27,7 +27,7 @@ LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
    |             ^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18
    |
 LL | trait Foo {
diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr
index 12c93d58537..d324f4641cf 100644
--- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr
+++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr
@@ -8,7 +8,7 @@ LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
    |             ^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18
    |
 LL | trait Foo {
diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
index 08c744979f5..28427161e87 100644
--- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
+++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
@@ -5,7 +5,7 @@ LL |     pub desc: &'static dyn Qux,
    |                        ^^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
    |
 LL | trait Qux {
@@ -44,7 +44,7 @@ LL | static FOO: &Lint = &Lint { desc: "desc" };
    |                                   ^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
    |
 LL | trait Qux {
@@ -68,7 +68,7 @@ LL | static FOO: &Lint = &Lint { desc: "desc" };
    |                                   ^^^^^^ `Qux` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
    |
 LL | trait Qux {
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr
index cb0e7fce910..ae009d26029 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr
@@ -5,7 +5,7 @@ LL | fn bar(x: &dyn Trait) {}
    |            ^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-references-self.rs:2:22
    |
 LL | trait Trait {
@@ -25,7 +25,7 @@ LL | fn foo(x: &dyn Other) {}
    |            ^^^^^^^^^ `Other` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-references-self.rs:11:14
    |
 LL | trait Other: Sized {}
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr
index 2efcad1e7bd..742011ad0c0 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr
@@ -18,7 +18,7 @@ LL |     fn f(a: dyn A) -> dyn A;
    |             ^^^^^ `A` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:3:10
    |
 LL | trait A: Sized {
@@ -46,7 +46,7 @@ LL |     fn f(a: dyn B) -> dyn B;
    |             ^^^^^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:8
    |
 LL | trait B {
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr
index ecb3ee9185f..843c139851d 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr
@@ -18,7 +18,7 @@ LL |     fn f(a: A) -> A;
    |             ^ `A` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-should-use-self.rs:2:10
    |
 LL | trait A: Sized {
@@ -46,7 +46,7 @@ LL |     fn f(a: B) -> B;
    |             ^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:8
    |
 LL | trait B {
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
index 696840d3ba4..e2250807603 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
@@ -5,7 +5,7 @@ LL | fn bar(x: &dyn Trait) {}
    |            ^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:5:8
    |
 LL | trait Trait {
diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr
index 508c3ec5e4f..e7b8cd2f101 100644
--- a/tests/ui/suggestions/issue-116434-2015.stderr
+++ b/tests/ui/suggestions/issue-116434-2015.stderr
@@ -47,7 +47,7 @@ LL |     fn foo() -> Clone;
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
-           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 help: there is an associated type with the same name
    |
 LL |     fn foo() -> Self::Clone;
@@ -74,7 +74,7 @@ LL |     fn handle() -> DbHandle;
    |                    ^^^^^^^^ `DbHandle` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-116434-2015.rs:14:17
    |
 LL | trait DbHandle: Sized {}
diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr
index 97b712acfcb..ec984c0d60e 100644
--- a/tests/ui/suggestions/issue-98500.stderr
+++ b/tests/ui/suggestions/issue-98500.stderr
@@ -5,7 +5,7 @@ LL | struct S(Box<dyn B>);
    |              ^^^^^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/auxiliary/dyn-incompatible.rs:4:8
    |
 LL |     fn f();
diff --git a/tests/ui/traits/alias/generic-default-in-dyn.stderr b/tests/ui/traits/alias/generic-default-in-dyn.stderr
index 1ab9e6d5c5c..c6f8ab4137b 100644
--- a/tests/ui/traits/alias/generic-default-in-dyn.stderr
+++ b/tests/ui/traits/alias/generic-default-in-dyn.stderr
@@ -15,7 +15,7 @@ LL | struct Foo<T>(dyn SendEqAlias<T>);
    |                   ^^^^^^^^^^^^^^ `SendEqAlias` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generic-default-in-dyn.rs:1:24
    |
 LL | trait SendEqAlias<T> = PartialEq;
@@ -30,7 +30,7 @@ LL | struct Bar<T>(dyn SendEqAlias<T>, T);
    |                   ^^^^^^^^^^^^^^ `SendEqAlias` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/generic-default-in-dyn.rs:1:24
    |
 LL | trait SendEqAlias<T> = PartialEq;
diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr
index 52ce79a4597..d60d8843407 100644
--- a/tests/ui/traits/alias/object-fail.stderr
+++ b/tests/ui/traits/alias/object-fail.stderr
@@ -5,7 +5,7 @@ LL |     let _: &dyn EqAlias = &123;
    |                 ^^^^^^^ `EqAlias` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: ...because it uses `Self` as a type parameter
diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr
index 3c799492591..b5538cb6e2f 100644
--- a/tests/ui/traits/alias/self-in-const-generics.stderr
+++ b/tests/ui/traits/alias/self-in-const-generics.stderr
@@ -5,7 +5,7 @@ LL | fn foo(x: &dyn BB) {}
    |                ^^ `BB` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/self-in-const-generics.rs:7:12
    |
 LL | trait BB = Bar<{ 2 + 1 }>;
diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr
index 5639b2b44a1..afe4dff45ed 100644
--- a/tests/ui/traits/alias/self-in-generics.stderr
+++ b/tests/ui/traits/alias/self-in-generics.stderr
@@ -5,7 +5,7 @@ LL | pub fn f(_f: &dyn SelfInput) {}
    |                   ^^^^^^^^^ `SelfInput` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/self-in-generics.rs:6:23
    |
 LL | pub trait SelfInput = Fn(&mut Self);
diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr
index 50ea7cde961..32e29de49a1 100644
--- a/tests/ui/traits/issue-20692.stderr
+++ b/tests/ui/traits/issue-20692.stderr
@@ -5,7 +5,7 @@ LL |     &dyn Array;
    |     ^^^^^^^^^^ `Array` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-20692.rs:1:14
    |
 LL | trait Array: Sized + Copy {}
@@ -21,7 +21,7 @@ LL |     let _ = x
    |             ^ `Array` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-20692.rs:1:14
    |
 LL | trait Array: Sized + Copy {}
diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr
index ba113d573d6..ba61ce98554 100644
--- a/tests/ui/traits/issue-28576.stderr
+++ b/tests/ui/traits/issue-28576.stderr
@@ -27,7 +27,7 @@ LL | |               <Assoc=()>
    | |________________________^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-28576.rs:5:16
    |
 LL | pub trait Bar: Foo<Assoc=()> {
diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr
index f9e592255dd..63269d3379e 100644
--- a/tests/ui/traits/issue-38404.stderr
+++ b/tests/ui/traits/issue-38404.stderr
@@ -5,7 +5,7 @@ LL | trait C<T>: A<dyn B<T, Output = usize>> {}
    |                   ^^^^^^^^^^^^^^^^^^^^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-38404.rs:1:13
    |
 LL | trait A<T>: std::ops::Add<Self> + Sized {}
@@ -20,7 +20,7 @@ LL | trait C<T>: A<dyn B<T, Output = usize>> {}
    |                   ^^^^^^^^^^^^^^^^^^^^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-38404.rs:1:13
    |
 LL | trait A<T>: std::ops::Add<Self> + Sized {}
@@ -36,7 +36,7 @@ LL | trait C<T>: A<dyn B<T, Output = usize>> {}
    |                   ^^^^^^^^^^^^^^^^^^^^ `B` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-38404.rs:1:13
    |
 LL | trait A<T>: std::ops::Add<Self> + Sized {}
diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr
index 94f9c1540ad..e6a6b44e730 100644
--- a/tests/ui/traits/issue-38604.stderr
+++ b/tests/ui/traits/issue-38604.stderr
@@ -5,7 +5,7 @@ LL |     let _f: Box<dyn Foo> =
    |             ^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-38604.rs:2:22
    |
 LL | trait Foo where u32: Q<Self> {
@@ -21,7 +21,7 @@ LL |         Box::new(());
    |         ^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-38604.rs:2:22
    |
 LL | trait Foo where u32: Q<Self> {
diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr
index 002345bff84..c9e133437dd 100644
--- a/tests/ui/traits/issue-72410.stderr
+++ b/tests/ui/traits/issue-72410.stderr
@@ -5,7 +5,7 @@ LL |     where for<'a> &'a mut [dyn Bar]: ;
    |                   ^^^^^^^^^^^^^^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-72410.rs:13:8
    |
 LL | pub trait Bar {
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index c97158a5b76..58c558d6685 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -143,7 +143,7 @@ LL |     <dyn C>::A;
    |      ^^^^^ `assoc_const::C` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/item-privacy.rs:25:15
    |
 LL |         const A: u8 = 0;
diff --git a/tests/ui/traits/missing-for-type-in-impl.e2015.stderr b/tests/ui/traits/missing-for-type-in-impl.e2015.stderr
index 682d18842b8..c8a1329e3d0 100644
--- a/tests/ui/traits/missing-for-type-in-impl.e2015.stderr
+++ b/tests/ui/traits/missing-for-type-in-impl.e2015.stderr
@@ -41,7 +41,7 @@ LL | impl Foo<i64> {
    |      ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/missing-for-type-in-impl.rs:4:8
    |
 LL | trait Foo<T> {
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
index 8448890c084..43b69d0b50e 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
@@ -14,7 +14,7 @@ LL |     let x: &dyn Foo = &();
    |                       ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/supertrait-dyn-compatibility.rs:4:12
    |
 LL | trait Foo: for<T> Bar<T> {}
@@ -31,7 +31,7 @@ LL |     let x: &dyn Foo = &();
    |            ^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/supertrait-dyn-compatibility.rs:4:12
    |
 LL | trait Foo: for<T> Bar<T> {}
@@ -47,7 +47,7 @@ LL |     needs_bar(x);
    |     ^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/supertrait-dyn-compatibility.rs:4:12
    |
 LL | trait Foo: for<T> Bar<T> {}
diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs
index 2a301788525..2a301788525 100644
--- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs
+++ b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs
diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr
index 38dcdbd0af2..38dcdbd0af2 100644
--- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr
+++ b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr
diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.rs
index 23f3666618b..23f3666618b 100644
--- a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs
+++ b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.rs
diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.stderr
index 3c352c9889c..3c352c9889c 100644
--- a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr
+++ b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.stderr
diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
index ae3762704c6..b4bbd65b2f4 100644
--- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
+++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
@@ -20,7 +20,7 @@ LL |     let b: &dyn FromResidual = &();
    |                                ^^^ `FromResidual` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8
    |
 LL | trait FromResidual<R = <Self as Try>::Residual> {
@@ -44,7 +44,7 @@ LL |     let b: &dyn FromResidual = &();
    |            ^^^^^^^^^^^^^^^^^ `FromResidual` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8
    |
 LL | trait FromResidual<R = <Self as Try>::Residual> {
diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr
index ab0fc213c9f..3c668ce99c7 100644
--- a/tests/ui/traits/object/macro-matcher.stderr
+++ b/tests/ui/traits/object/macro-matcher.stderr
@@ -12,7 +12,7 @@ LL |     m!(dyn Copy + Send + 'static);
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
-           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/object/print_vtable_sizes.rs b/tests/ui/traits/object/print_vtable_sizes.rs
deleted file mode 100644
index 2b1745da5f3..00000000000
--- a/tests/ui/traits/object/print_vtable_sizes.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-//@ check-pass
-//@ compile-flags: -Z print-vtable-sizes
-#![crate_type = "lib"]
-
-trait A<T: help::V>: AsRef<[T::V]> + AsMut<[T::V]> {}
-
-trait B<T>: AsRef<T> + AsRef<T> + AsRef<T> + AsRef<T> {}
-
-trait C {
-    fn x() {} // not dyn-compatible, shouldn't be reported
-}
-
-// This does not have any upcasting cost,
-// because both `Send` and `Sync` are traits
-// with no methods
-trait D: Send + Sync + help::MarkerWithSuper {}
-
-// This can't have no cost without reordering,
-// because `Super::f`.
-trait E: help::MarkerWithSuper + Send + Sync {}
-
-trait F {
-    fn a(&self);
-    fn b(&self);
-    fn c(&self);
-
-    fn d() -> Self
-    where
-        Self: Sized;
-}
-
-trait G: AsRef<u8> + AsRef<u16> + help::MarkerWithSuper {
-    fn a(&self);
-    fn b(&self);
-    fn c(&self);
-    fn d(&self);
-    fn e(&self);
-
-    fn f() -> Self
-    where
-        Self: Sized;
-}
-
-// Traits with the same name
-const _: () = {
-    trait S {}
-};
-const _: () = {
-    trait S {}
-};
-
-mod help {
-    pub trait V {
-        type V;
-    }
-
-    pub trait MarkerWithSuper: Super {}
-
-    pub trait Super {
-        fn f(&self);
-    }
-}
diff --git a/tests/ui/traits/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout
deleted file mode 100644
index 4daf4769576..00000000000
--- a/tests/ui/traits/object/print_vtable_sizes.stdout
+++ /dev/null
@@ -1,11 +0,0 @@
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "13", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "2", "upcasting_cost_percent": "18.181818181818183" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
-print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr
index eab59f39c28..593e42619f4 100644
--- a/tests/ui/traits/object/safety.stderr
+++ b/tests/ui/traits/object/safety.stderr
@@ -5,7 +5,7 @@ LL |     let _: &dyn Tr = &St;
    |                      ^^^ `Tr` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/safety.rs:4:8
    |
 LL | trait Tr {
@@ -30,7 +30,7 @@ LL |     let _: &dyn Tr = &St;
    |            ^^^^^^^ `Tr` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/safety.rs:4:8
    |
 LL | trait Tr {
diff --git a/tests/ui/traits/on_unimplemented_long_types.rs b/tests/ui/traits/on_unimplemented_long_types.rs
index 98749b8db7a..c652b71e51a 100644
--- a/tests/ui/traits/on_unimplemented_long_types.rs
+++ b/tests/ui/traits/on_unimplemented_long_types.rs
@@ -1,5 +1,6 @@
 //@ compile-flags: --diagnostic-width=60 -Z write-long-types-to-disk=yes
-//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
 
 pub fn foo() -> impl std::fmt::Display {
     //~^ ERROR doesn't implement `std::fmt::Display`
diff --git a/tests/ui/traits/on_unimplemented_long_types.stderr b/tests/ui/traits/on_unimplemented_long_types.stderr
index bddc5695696..5722f4006ff 100644
--- a/tests/ui/traits/on_unimplemented_long_types.stderr
+++ b/tests/ui/traits/on_unimplemented_long_types.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Option<Option<Option<...>>>` doesn't implement `std::fmt::Display`
-  --> $DIR/on_unimplemented_long_types.rs:4:17
+  --> $DIR/on_unimplemented_long_types.rs:5:17
    |
 LL |   pub fn foo() -> impl std::fmt::Display {
    |                   ^^^^^^^^^^^^^^^^^^^^^^ `Option<Option<Option<...>>>` cannot be formatted with the default formatter
@@ -13,11 +13,11 @@ LL | |         ))))))))))),
 LL | |     )))))))))))
    | |_______________- return type was inferred to be `Option<Option<Option<...>>>` here
    |
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/traits/on_unimplemented_long_types/on_unimplemented_long_types.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
    = help: the trait `std::fmt::Display` is not implemented for `Option<Option<Option<...>>>`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-   = note: the full name for the type has been written to '$TEST_BUILD_DIR/traits/on_unimplemented_long_types/on_unimplemented_long_types.long-type-hash.txt'
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/traits/sized-coniductive.rs b/tests/ui/traits/sized-coniductive.rs
deleted file mode 100644
index 5f63b166f98..00000000000
--- a/tests/ui/traits/sized-coniductive.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ check-pass
-// https://github.com/rust-lang/rust/issues/129541
-
-#[derive(Clone)]
-struct Test {
-    field: std::borrow::Cow<'static, [Self]>,
-}
-
-#[derive(Clone)]
-struct Hello {
-    a: <[Hello] as std::borrow::ToOwned>::Owned,
-}
-
-fn main(){}
diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct-and-array-impl.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct-and-array-impl.rs
deleted file mode 100644
index defb39aae06..00000000000
--- a/tests/ui/traits/solver-cycles/129541-recursive-struct-and-array-impl.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Regression test for #129541
-
-//@ check-pass
-
-trait Bound {}
-trait Normalize {
-    type Assoc;
-}
-
-impl<T: Bound> Normalize for T {
-    type Assoc = T;
-}
-
-impl<T: Bound> Normalize for [T] {
-    type Assoc = T;
-}
-
-impl Bound for Hello {}
-struct Hello {
-    a: <[Hello] as Normalize>::Assoc,
-}
-
-fn main() {}
diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs
index d4339dd54d6..4fbcbefec91 100644
--- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs
+++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs
@@ -1,5 +1,6 @@
 // Regression test for #129541
 
+//@ revisions: unique multiple
 //@ check-pass
 
 trait Bound {}
@@ -7,6 +8,10 @@ trait Normalize {
     type Assoc;
 }
 
+#[cfg(multiple)]
+impl<T: Bound> Normalize for T {
+    type Assoc = T;
+}
 impl<T: Bound> Normalize for [T] {
     type Assoc = T;
 }
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index 8915e490b4d..6a6cb503aa4 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -33,7 +33,7 @@ LL |     (Box::new(10) as Box<dyn bar>).dup();
    |                      ^^^^^^^^^^^^ `bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/test-2.rs:4:30
    |
 LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
@@ -56,7 +56,7 @@ LL |     (Box::new(10) as Box<dyn bar>).dup();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/test-2.rs:4:30
    |
 LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
@@ -79,7 +79,7 @@ LL |     (Box::new(10) as Box<dyn bar>).dup();
    |      ^^^^^^^^^^^^ `bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/test-2.rs:4:30
    |
 LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.rs
new file mode 100644
index 00000000000..796ddec46ac
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.rs
@@ -0,0 +1,27 @@
+#![feature(rustc_attrs)]
+
+// Test for <https://github.com/rust-lang/rust/issues/135316>.
+
+trait Supertrait<T> {
+    fn _print_numbers(&self, mem: &[usize; 100]) {
+    }
+}
+impl<T> Supertrait<T> for () {}
+
+trait Trait<T, U>: Supertrait<T> + Supertrait<U> {
+    fn say_hello(&self, _: &usize) {
+    }
+}
+impl<T, U> Trait<T, U> for () {}
+
+// We should observe compatibility between these two vtables.
+
+#[rustc_dump_vtable]
+type First = dyn for<'a> Trait<&'static (), &'a ()>;
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
+type Second = dyn Trait<&'static (), &'static ()>;
+//~^ ERROR vtable entries
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.stderr b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.stderr
new file mode 100644
index 00000000000..24fa1650ca1
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder-vtable.stderr
@@ -0,0 +1,26 @@
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<dyn for<'a> Trait<&(), &'a ()> as Supertrait<&()>>::_print_numbers - shim(reify)),
+           Method(<dyn for<'a> Trait<&(), &'a ()> as Trait<&(), &()>>::say_hello - shim(reify)),
+       ]
+  --> $DIR/multiple-supertraits-modulo-binder-vtable.rs:20:1
+   |
+LL | type First = dyn for<'a> Trait<&'static (), &'a ()>;
+   | ^^^^^^^^^^
+
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<dyn Trait<&(), &()> as Supertrait<&()>>::_print_numbers - shim(reify)),
+           Method(<dyn Trait<&(), &()> as Trait<&(), &()>>::say_hello - shim(reify)),
+       ]
+  --> $DIR/multiple-supertraits-modulo-binder-vtable.rs:24:1
+   |
+LL | type Second = dyn Trait<&'static (), &'static ()>;
+   | ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs
new file mode 100644
index 00000000000..510a1471af2
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs
@@ -0,0 +1,26 @@
+//@ run-pass
+//@ check-run-results
+
+// Test for <https://github.com/rust-lang/rust/issues/135316>.
+
+#![feature(trait_upcasting)]
+
+trait Supertrait<T> {
+    fn _print_numbers(&self, mem: &[usize; 100]) {
+        println!("{mem:?}");
+    }
+}
+impl<T> Supertrait<T> for () {}
+
+trait Trait<T, U>: Supertrait<T> + Supertrait<U> {
+    fn say_hello(&self, _: &usize) {
+        println!("Hello!");
+    }
+}
+impl<T, U> Trait<T, U> for () {}
+
+fn main() {
+    (&() as &'static dyn for<'a> Trait<&'static (), &'a ()>
+        as &'static dyn Trait<&'static (), &'static ()>)
+        .say_hello(&0);
+}
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.run.stdout b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.run.stdout
new file mode 100644
index 00000000000..10ddd6d257e
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.run.stdout
@@ -0,0 +1 @@
+Hello!
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs
new file mode 100644
index 00000000000..69a71859a5c
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs
@@ -0,0 +1,37 @@
+#![feature(rustc_attrs)]
+#![feature(trait_upcasting)]
+
+// Test for <https://github.com/rust-lang/rust/issues/135315>.
+
+trait Supertrait<T> {
+    fn _print_numbers(&self, mem: &[usize; 100]) {
+        println!("{mem:?}");
+    }
+}
+impl<T> Supertrait<T> for () {}
+
+trait Identity {
+    type Selff;
+}
+impl<Selff> Identity for Selff {
+    type Selff = Selff;
+}
+
+trait Middle<T>: Supertrait<()> + Supertrait<T> {
+    fn say_hello(&self, _: &usize) {
+        println!("Hello!");
+    }
+}
+impl<T> Middle<T> for () {}
+
+trait Trait: Middle<<() as Identity>::Selff> {}
+
+#[rustc_dump_vtable]
+impl Trait for () {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
+type Virtual = dyn Middle<()>;
+//~^ ERROR vtable entries
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr
new file mode 100644
index 00000000000..757e2dc6939
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr
@@ -0,0 +1,26 @@
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<() as Supertrait<()>>::_print_numbers),
+           Method(<() as Middle<()>>::say_hello),
+       ]
+  --> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:30:1
+   |
+LL | impl Trait for () {}
+   | ^^^^^^^^^^^^^^^^^
+
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<dyn Middle<()> as Supertrait<()>>::_print_numbers - shim(reify)),
+           Method(<dyn Middle<()> as Middle<()>>::say_hello - shim(reify)),
+       ]
+  --> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:34:1
+   |
+LL | type Virtual = dyn Middle<()>;
+   | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs
new file mode 100644
index 00000000000..c744e6e64f5
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs
@@ -0,0 +1,34 @@
+//@ run-pass
+//@ check-run-results
+
+#![feature(trait_upcasting)]
+
+// Test for <https://github.com/rust-lang/rust/issues/135315>.
+
+trait Supertrait<T> {
+    fn _print_numbers(&self, mem: &[usize; 100]) {
+        println!("{mem:?}");
+    }
+}
+impl<T> Supertrait<T> for () {}
+
+trait Identity {
+    type Selff;
+}
+impl<Selff> Identity for Selff {
+    type Selff = Selff;
+}
+
+trait Middle<T>: Supertrait<()> + Supertrait<T> {
+    fn say_hello(&self, _: &usize) {
+        println!("Hello!");
+    }
+}
+impl<T> Middle<T> for () {}
+
+trait Trait: Middle<<() as Identity>::Selff> {}
+impl Trait for () {}
+
+fn main() {
+    (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
+}
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.run.stdout b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.run.stdout
new file mode 100644
index 00000000000..10ddd6d257e
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.run.stdout
@@ -0,0 +1 @@
+Hello!
diff --git a/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs b/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs
new file mode 100644
index 00000000000..6cd74b6c7f7
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+
+#![feature(trait_upcasting)]
+
+trait Super<U> {
+    fn call(&self)
+    where
+        U: HigherRanked,
+    {
+    }
+}
+
+impl<T> Super<T> for () {}
+
+trait HigherRanked {}
+impl HigherRanked for for<'a> fn(&'a ()) {}
+
+trait Unimplemented {}
+impl<T: Unimplemented> HigherRanked for T {}
+
+trait Sub: Super<fn(&'static ())> + Super<for<'a> fn(&'a ())> {}
+impl Sub for () {}
+
+fn main() {
+    let a: &dyn Sub = &();
+    // `Super<fn(&'static ())>` and `Super<for<'a> fn(&'a ())>` have different
+    // vtables and we need to upcast to the latter!
+    let b: &dyn Super<for<'a> fn(&'a ())> = a;
+    b.call();
+}
diff --git a/tests/ui/traits/vtable/multiple-markers.rs b/tests/ui/traits/vtable/multiple-markers.rs
index 8a9e7a006cf..8eba5135582 100644
--- a/tests/ui/traits/vtable/multiple-markers.rs
+++ b/tests/ui/traits/vtable/multiple-markers.rs
@@ -2,8 +2,7 @@
 //
 // This test makes sure that multiple marker (method-less) traits can reuse the
 // same pointer for upcasting.
-//
-//@ build-fail
+
 #![crate_type = "lib"]
 #![feature(rustc_attrs)]
 
@@ -17,17 +16,13 @@ trait T {
     fn method(&self) {}
 }
 
-#[rustc_dump_vtable]
-trait A: M0 + M1 + M2 + T {} //~ error: vtable entries for `<S as A>`:
+trait A: M0 + M1 + M2 + T {}
 
-#[rustc_dump_vtable]
-trait B: M0 + M1 + T + M2 {} //~ error: vtable entries for `<S as B>`:
+trait B: M0 + M1 + T + M2 {}
 
-#[rustc_dump_vtable]
-trait C: M0 + T + M1 + M2 {} //~ error: vtable entries for `<S as C>`:
+trait C: M0 + T + M1 + M2 {}
 
-#[rustc_dump_vtable]
-trait D: T + M0 + M1 + M2 {} //~ error: vtable entries for `<S as D>`:
+trait D: T + M0 + M1 + M2 {}
 
 struct S;
 
@@ -35,13 +30,21 @@ impl M0 for S {}
 impl M1 for S {}
 impl M2 for S {}
 impl T for S {}
+
+#[rustc_dump_vtable]
 impl A for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl B for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl C for S {}
-impl D for S {}
+//~^ ERROR vtable entries
 
-pub fn require_vtables() {
-    fn require_vtables(_: &dyn A, _: &dyn B, _: &dyn C, _: &dyn D) {}
+#[rustc_dump_vtable]
+impl D for S {}
+//~^ ERROR vtable entries
 
-    require_vtables(&S, &S, &S, &S)
-}
+fn main() {}
diff --git a/tests/ui/traits/vtable/multiple-markers.stderr b/tests/ui/traits/vtable/multiple-markers.stderr
index 36ac8b24eb5..35dd3c2516d 100644
--- a/tests/ui/traits/vtable/multiple-markers.stderr
+++ b/tests/ui/traits/vtable/multiple-markers.stderr
@@ -1,46 +1,46 @@
-error: vtable entries for `<S as A>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as T>::method),
        ]
-  --> $DIR/multiple-markers.rs:21:1
+  --> $DIR/multiple-markers.rs:35:1
    |
-LL | trait A: M0 + M1 + M2 + T {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl A for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as B>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as T>::method),
        ]
-  --> $DIR/multiple-markers.rs:24:1
+  --> $DIR/multiple-markers.rs:39:1
    |
-LL | trait B: M0 + M1 + T + M2 {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl B for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as C>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as T>::method),
        ]
-  --> $DIR/multiple-markers.rs:27:1
+  --> $DIR/multiple-markers.rs:43:1
    |
-LL | trait C: M0 + T + M1 + M2 {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl C for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as D>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as T>::method),
        ]
-  --> $DIR/multiple-markers.rs:30:1
+  --> $DIR/multiple-markers.rs:47:1
    |
-LL | trait D: T + M0 + M1 + M2 {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl D for S {}
+   | ^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/vtable/vtable-diamond.rs b/tests/ui/traits/vtable/vtable-diamond.rs
index 2cfa86c526d..56053f6d026 100644
--- a/tests/ui/traits/vtable/vtable-diamond.rs
+++ b/tests/ui/traits/vtable/vtable-diamond.rs
@@ -1,44 +1,37 @@
-//@ build-fail
 #![feature(rustc_attrs)]
 
-#[rustc_dump_vtable]
 trait A {
     fn foo_a(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait B: A {
     fn foo_b(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait C: A {
-    //~^ error vtable
     fn foo_c(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait D: B + C {
-    //~^ error vtable
     fn foo_d(&self) {}
 }
 
 struct S;
 
+#[rustc_dump_vtable]
 impl A for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl B for S {}
-impl C for S {}
-impl D for S {}
+//~^ ERROR vtable entries
 
-fn foo(d: &dyn D) {
-    d.foo_d();
-}
+#[rustc_dump_vtable]
+impl C for S {}
+//~^ ERROR vtable entries
 
-fn bar(d: &dyn C) {
-    d.foo_c();
-}
+#[rustc_dump_vtable]
+impl D for S {}
+//~^ ERROR vtable entries
 
-fn main() {
-    foo(&S);
-    bar(&S);
-}
+fn main() {}
diff --git a/tests/ui/traits/vtable/vtable-diamond.stderr b/tests/ui/traits/vtable/vtable-diamond.stderr
index f3718c5d852..4644bf339b1 100644
--- a/tests/ui/traits/vtable/vtable-diamond.stderr
+++ b/tests/ui/traits/vtable/vtable-diamond.stderr
@@ -1,29 +1,52 @@
-error: vtable entries for `<S as D>`: [
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<S as A>::foo_a),
+       ]
+  --> $DIR/vtable-diamond.rs:22:1
+   |
+LL | impl A for S {}
+   | ^^^^^^^^^^^^
+
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as A>::foo_a),
            Method(<S as B>::foo_b),
+       ]
+  --> $DIR/vtable-diamond.rs:26:1
+   |
+LL | impl B for S {}
+   | ^^^^^^^^^^^^
+
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<S as A>::foo_a),
            Method(<S as C>::foo_c),
-           TraitVPtr(<S as C>),
-           Method(<S as D>::foo_d),
        ]
-  --> $DIR/vtable-diamond.rs:21:1
+  --> $DIR/vtable-diamond.rs:30:1
    |
-LL | trait D: B + C {
-   | ^^^^^^^^^^^^^^
+LL | impl C for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as C>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as A>::foo_a),
+           Method(<S as B>::foo_b),
            Method(<S as C>::foo_c),
+           TraitVPtr(<S as C>),
+           Method(<S as D>::foo_d),
        ]
-  --> $DIR/vtable-diamond.rs:15:1
+  --> $DIR/vtable-diamond.rs:34:1
    |
-LL | trait C: A {
-   | ^^^^^^^^^^
+LL | impl D for S {}
+   | ^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/vtable/vtable-dyn-incompatible.rs b/tests/ui/traits/vtable/vtable-dyn-incompatible.rs
index 64a8138bdcf..fb19dec4ace 100644
--- a/tests/ui/traits/vtable/vtable-dyn-incompatible.rs
+++ b/tests/ui/traits/vtable/vtable-dyn-incompatible.rs
@@ -1,15 +1,16 @@
-//@ build-fail
 #![feature(rustc_attrs)]
 
 // Ensure that dyn-incompatible methods in Iterator does not generate
 // vtable entries.
 
-#[rustc_dump_vtable]
 trait A: Iterator {}
-//~^ error vtable
 
 impl<T> A for T where T: Iterator {}
 
+#[rustc_dump_vtable]
+type Test = dyn A<Item=u8>;
+//~^ error vtable
+
 fn foo(_a: &mut dyn A<Item=u8>) {
 }
 
diff --git a/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr b/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr
index e442c3eac00..c80a763998b 100644
--- a/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr
+++ b/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr
@@ -1,16 +1,16 @@
-error: vtable entries for `<std::vec::IntoIter<u8> as A>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
-           Method(<std::vec::IntoIter<u8> as Iterator>::next),
-           Method(<std::vec::IntoIter<u8> as Iterator>::size_hint),
-           Method(<std::vec::IntoIter<u8> as Iterator>::advance_by),
-           Method(<std::vec::IntoIter<u8> as Iterator>::nth),
+           Method(<dyn A<Item = u8> as Iterator>::next - shim(reify)),
+           Method(<dyn A<Item = u8> as Iterator>::size_hint - shim(reify)),
+           Method(<dyn A<Item = u8> as Iterator>::advance_by - shim(reify)),
+           Method(<dyn A<Item = u8> as Iterator>::nth - shim(reify)),
        ]
-  --> $DIR/vtable-dyn-incompatible.rs:8:1
+  --> $DIR/vtable-dyn-incompatible.rs:11:1
    |
-LL | trait A: Iterator {}
-   | ^^^^^^^^^^^^^^^^^
+LL | type Test = dyn A<Item=u8>;
+   | ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/vtable/vtable-multi-level.rs b/tests/ui/traits/vtable/vtable-multi-level.rs
index bedbf84d303..67bac49f9f6 100644
--- a/tests/ui/traits/vtable/vtable-multi-level.rs
+++ b/tests/ui/traits/vtable/vtable-multi-level.rs
@@ -1,4 +1,3 @@
-//@ build-fail
 #![feature(rustc_attrs)]
 
 //   O --> G --> C --> A
@@ -10,134 +9,126 @@
 //           |-> M --> K
 //                 \-> L
 
-#[rustc_dump_vtable]
 trait A {
-    //~^ error vtable
     fn foo_a(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait B {
-    //~^ error vtable
     fn foo_b(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait C: A + B {
-    //~^ error vtable
     fn foo_c(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait D {
-    //~^ error vtable
     fn foo_d(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait E {
-    //~^ error vtable
     fn foo_e(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait F: D + E {
-    //~^ error vtable
     fn foo_f(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait G: C + F {
     fn foo_g(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait H {
-    //~^ error vtable
     fn foo_h(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait I {
-    //~^ error vtable
     fn foo_i(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait J: H + I {
-    //~^ error vtable
     fn foo_j(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait K {
-    //~^ error vtable
     fn foo_k(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait L {
-    //~^ error vtable
     fn foo_l(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait M: K + L {
-    //~^ error vtable
     fn foo_m(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait N: J + M {
-    //~^ error vtable
     fn foo_n(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait O: G + N {
-    //~^ error vtable
     fn foo_o(&self) {}
 }
 
 struct S;
 
+#[rustc_dump_vtable]
 impl A for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl B for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl C for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl D for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl E for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl F for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl G for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl H for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl I for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl J for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl K for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl L for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl M for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
 impl N for S {}
-impl O for S {}
+//~^ ERROR vtable entries
 
-macro_rules! monomorphize_vtable {
-    ($trait:ident) => {{
-        fn foo(_ : &dyn $trait) {}
-        foo(&S);
-    }}
-}
+#[rustc_dump_vtable]
+impl O for S {}
+//~^ ERROR vtable entries
 
-fn main() {
-    monomorphize_vtable!(O);
-
-    monomorphize_vtable!(A);
-    monomorphize_vtable!(B);
-    monomorphize_vtable!(C);
-    monomorphize_vtable!(D);
-    monomorphize_vtable!(E);
-    monomorphize_vtable!(F);
-    monomorphize_vtable!(H);
-    monomorphize_vtable!(I);
-    monomorphize_vtable!(J);
-    monomorphize_vtable!(K);
-    monomorphize_vtable!(L);
-    monomorphize_vtable!(M);
-    monomorphize_vtable!(N);
-}
+fn main() {}
diff --git a/tests/ui/traits/vtable/vtable-multi-level.stderr b/tests/ui/traits/vtable/vtable-multi-level.stderr
index c4389e23fc1..961900aa3d2 100644
--- a/tests/ui/traits/vtable/vtable-multi-level.stderr
+++ b/tests/ui/traits/vtable/vtable-multi-level.stderr
@@ -1,134 +1,119 @@
-error: vtable entries for `<S as O>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as A>::foo_a),
-           Method(<S as B>::foo_b),
-           TraitVPtr(<S as B>),
-           Method(<S as C>::foo_c),
-           Method(<S as D>::foo_d),
-           TraitVPtr(<S as D>),
-           Method(<S as E>::foo_e),
-           TraitVPtr(<S as E>),
-           Method(<S as F>::foo_f),
-           TraitVPtr(<S as F>),
-           Method(<S as G>::foo_g),
-           Method(<S as H>::foo_h),
-           TraitVPtr(<S as H>),
-           Method(<S as I>::foo_i),
-           TraitVPtr(<S as I>),
-           Method(<S as J>::foo_j),
-           TraitVPtr(<S as J>),
-           Method(<S as K>::foo_k),
-           TraitVPtr(<S as K>),
-           Method(<S as L>::foo_l),
-           TraitVPtr(<S as L>),
-           Method(<S as M>::foo_m),
-           TraitVPtr(<S as M>),
-           Method(<S as N>::foo_n),
-           TraitVPtr(<S as N>),
-           Method(<S as O>::foo_o),
        ]
-  --> $DIR/vtable-multi-level.rs:97:1
+  --> $DIR/vtable-multi-level.rs:75:1
    |
-LL | trait O: G + N {
-   | ^^^^^^^^^^^^^^
+LL | impl A for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as A>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
-           Method(<S as A>::foo_a),
+           Method(<S as B>::foo_b),
        ]
-  --> $DIR/vtable-multi-level.rs:14:1
+  --> $DIR/vtable-multi-level.rs:79:1
    |
-LL | trait A {
-   | ^^^^^^^
+LL | impl B for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as B>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
+           Method(<S as A>::foo_a),
            Method(<S as B>::foo_b),
+           TraitVPtr(<S as B>),
+           Method(<S as C>::foo_c),
        ]
-  --> $DIR/vtable-multi-level.rs:20:1
+  --> $DIR/vtable-multi-level.rs:83:1
    |
-LL | trait B {
-   | ^^^^^^^
+LL | impl C for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as C>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
-           Method(<S as A>::foo_a),
-           Method(<S as B>::foo_b),
-           TraitVPtr(<S as B>),
-           Method(<S as C>::foo_c),
+           Method(<S as D>::foo_d),
        ]
-  --> $DIR/vtable-multi-level.rs:26:1
+  --> $DIR/vtable-multi-level.rs:87:1
    |
-LL | trait C: A + B {
-   | ^^^^^^^^^^^^^^
+LL | impl D for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as D>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
-           Method(<S as D>::foo_d),
+           Method(<S as E>::foo_e),
        ]
-  --> $DIR/vtable-multi-level.rs:32:1
+  --> $DIR/vtable-multi-level.rs:91:1
    |
-LL | trait D {
-   | ^^^^^^^
+LL | impl E for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as E>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
+           Method(<S as D>::foo_d),
            Method(<S as E>::foo_e),
+           TraitVPtr(<S as E>),
+           Method(<S as F>::foo_f),
        ]
-  --> $DIR/vtable-multi-level.rs:38:1
+  --> $DIR/vtable-multi-level.rs:95:1
    |
-LL | trait E {
-   | ^^^^^^^
+LL | impl F for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as F>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
+           Method(<S as A>::foo_a),
+           Method(<S as B>::foo_b),
+           TraitVPtr(<S as B>),
+           Method(<S as C>::foo_c),
            Method(<S as D>::foo_d),
+           TraitVPtr(<S as D>),
            Method(<S as E>::foo_e),
            TraitVPtr(<S as E>),
            Method(<S as F>::foo_f),
+           TraitVPtr(<S as F>),
+           Method(<S as G>::foo_g),
        ]
-  --> $DIR/vtable-multi-level.rs:44:1
+  --> $DIR/vtable-multi-level.rs:99:1
    |
-LL | trait F: D + E {
-   | ^^^^^^^^^^^^^^
+LL | impl G for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as H>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as H>::foo_h),
        ]
-  --> $DIR/vtable-multi-level.rs:55:1
+  --> $DIR/vtable-multi-level.rs:103:1
    |
-LL | trait H {
-   | ^^^^^^^
+LL | impl H for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as I>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as I>::foo_i),
        ]
-  --> $DIR/vtable-multi-level.rs:61:1
+  --> $DIR/vtable-multi-level.rs:107:1
    |
-LL | trait I {
-   | ^^^^^^^
+LL | impl I for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as J>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
@@ -137,34 +122,34 @@ error: vtable entries for `<S as J>`: [
            TraitVPtr(<S as I>),
            Method(<S as J>::foo_j),
        ]
-  --> $DIR/vtable-multi-level.rs:67:1
+  --> $DIR/vtable-multi-level.rs:111:1
    |
-LL | trait J: H + I {
-   | ^^^^^^^^^^^^^^
+LL | impl J for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as K>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as K>::foo_k),
        ]
-  --> $DIR/vtable-multi-level.rs:73:1
+  --> $DIR/vtable-multi-level.rs:115:1
    |
-LL | trait K {
-   | ^^^^^^^
+LL | impl K for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as L>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as L>::foo_l),
        ]
-  --> $DIR/vtable-multi-level.rs:79:1
+  --> $DIR/vtable-multi-level.rs:119:1
    |
-LL | trait L {
-   | ^^^^^^^
+LL | impl L for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as M>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
@@ -173,12 +158,12 @@ error: vtable entries for `<S as M>`: [
            TraitVPtr(<S as L>),
            Method(<S as M>::foo_m),
        ]
-  --> $DIR/vtable-multi-level.rs:85:1
+  --> $DIR/vtable-multi-level.rs:123:1
    |
-LL | trait M: K + L {
-   | ^^^^^^^^^^^^^^
+LL | impl M for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as N>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
@@ -194,10 +179,46 @@ error: vtable entries for `<S as N>`: [
            TraitVPtr(<S as M>),
            Method(<S as N>::foo_n),
        ]
-  --> $DIR/vtable-multi-level.rs:91:1
+  --> $DIR/vtable-multi-level.rs:127:1
+   |
+LL | impl N for S {}
+   | ^^^^^^^^^^^^
+
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<S as A>::foo_a),
+           Method(<S as B>::foo_b),
+           TraitVPtr(<S as B>),
+           Method(<S as C>::foo_c),
+           Method(<S as D>::foo_d),
+           TraitVPtr(<S as D>),
+           Method(<S as E>::foo_e),
+           TraitVPtr(<S as E>),
+           Method(<S as F>::foo_f),
+           TraitVPtr(<S as F>),
+           Method(<S as G>::foo_g),
+           Method(<S as H>::foo_h),
+           TraitVPtr(<S as H>),
+           Method(<S as I>::foo_i),
+           TraitVPtr(<S as I>),
+           Method(<S as J>::foo_j),
+           TraitVPtr(<S as J>),
+           Method(<S as K>::foo_k),
+           TraitVPtr(<S as K>),
+           Method(<S as L>::foo_l),
+           TraitVPtr(<S as L>),
+           Method(<S as M>::foo_m),
+           TraitVPtr(<S as M>),
+           Method(<S as N>::foo_n),
+           TraitVPtr(<S as N>),
+           Method(<S as O>::foo_o),
+       ]
+  --> $DIR/vtable-multi-level.rs:131:1
    |
-LL | trait N: J + M {
-   | ^^^^^^^^^^^^^^
+LL | impl O for S {}
+   | ^^^^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/traits/vtable/vtable-multiple.rs b/tests/ui/traits/vtable/vtable-multiple.rs
index beaaf4db6b1..51e20ee20c9 100644
--- a/tests/ui/traits/vtable/vtable-multiple.rs
+++ b/tests/ui/traits/vtable/vtable-multiple.rs
@@ -1,33 +1,29 @@
-//@ build-fail
 #![feature(rustc_attrs)]
 
-#[rustc_dump_vtable]
 trait A {
     fn foo_a(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait B {
-    //~^ error vtable
     fn foo_b(&self) {}
 }
 
-#[rustc_dump_vtable]
 trait C: A + B {
-    //~^ error vtable
     fn foo_c(&self) {}
 }
 
 struct S;
 
+#[rustc_dump_vtable]
 impl A for S {}
+//~^ error vtable
+
+#[rustc_dump_vtable]
 impl B for S {}
-impl C for S {}
+//~^ error vtable
 
-fn foo(c: &dyn C) {}
-fn bar(c: &dyn B) {}
+#[rustc_dump_vtable]
+impl C for S {}
+//~^ error vtable
 
-fn main() {
-    foo(&S);
-    bar(&S);
-}
+fn main() {}
diff --git a/tests/ui/traits/vtable/vtable-multiple.stderr b/tests/ui/traits/vtable/vtable-multiple.stderr
index 0dcd8443309..bae44148baa 100644
--- a/tests/ui/traits/vtable/vtable-multiple.stderr
+++ b/tests/ui/traits/vtable/vtable-multiple.stderr
@@ -1,27 +1,38 @@
-error: vtable entries for `<S as C>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
            Method(<S as A>::foo_a),
+       ]
+  --> $DIR/vtable-multiple.rs:18:1
+   |
+LL | impl A for S {}
+   | ^^^^^^^^^^^^
+
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
            Method(<S as B>::foo_b),
-           TraitVPtr(<S as B>),
-           Method(<S as C>::foo_c),
        ]
-  --> $DIR/vtable-multiple.rs:16:1
+  --> $DIR/vtable-multiple.rs:22:1
    |
-LL | trait C: A + B {
-   | ^^^^^^^^^^^^^^
+LL | impl B for S {}
+   | ^^^^^^^^^^^^
 
-error: vtable entries for `<S as B>`: [
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
+           Method(<S as A>::foo_a),
            Method(<S as B>::foo_b),
+           TraitVPtr(<S as B>),
+           Method(<S as C>::foo_c),
        ]
-  --> $DIR/vtable-multiple.rs:10:1
+  --> $DIR/vtable-multiple.rs:26:1
    |
-LL | trait B {
-   | ^^^^^^^
+LL | impl C for S {}
+   | ^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/vtable/vtable-vacant.rs b/tests/ui/traits/vtable/vtable-vacant.rs
index b3c76815703..b023565c56e 100644
--- a/tests/ui/traits/vtable/vtable-vacant.rs
+++ b/tests/ui/traits/vtable/vtable-vacant.rs
@@ -1,18 +1,14 @@
-//@ build-fail
 #![feature(rustc_attrs)]
 #![feature(negative_impls)]
 
 // B --> A
 
-#[rustc_dump_vtable]
 trait A {
     fn foo_a1(&self) {}
     fn foo_a2(&self) where Self: Send {}
 }
 
-#[rustc_dump_vtable]
 trait B: A {
-    //~^ error vtable
     fn foo_b1(&self) {}
     fn foo_b2(&self) where Self: Send {}
 }
@@ -20,11 +16,12 @@ trait B: A {
 struct S;
 impl !Send for S {}
 
+#[rustc_dump_vtable]
 impl A for S {}
-impl B for S {}
+//~^ error vtable
 
-fn foo(_: &dyn B) {}
+#[rustc_dump_vtable]
+impl B for S {}
+//~^ error vtable
 
-fn main() {
-    foo(&S);
-}
+fn main() {}
diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr
index f6961ca010e..ed8466f7f2e 100644
--- a/tests/ui/traits/vtable/vtable-vacant.stderr
+++ b/tests/ui/traits/vtable/vtable-vacant.stderr
@@ -1,4 +1,16 @@
-error: vtable entries for `<S as B>`: [
+error: vtable entries: [
+           MetadataDropInPlace,
+           MetadataSize,
+           MetadataAlign,
+           Method(<S as A>::foo_a1),
+           Vacant,
+       ]
+  --> $DIR/vtable-vacant.rs:20:1
+   |
+LL | impl A for S {}
+   | ^^^^^^^^^^^^
+
+error: vtable entries: [
            MetadataDropInPlace,
            MetadataSize,
            MetadataAlign,
@@ -7,10 +19,10 @@ error: vtable entries for `<S as B>`: [
            Method(<S as B>::foo_b1),
            Vacant,
        ]
-  --> $DIR/vtable-vacant.rs:14:1
+  --> $DIR/vtable-vacant.rs:24:1
    |
-LL | trait B: A {
-   | ^^^^^^^^^^
+LL | impl B for S {}
+   | ^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
index 71717c6945e..eea2e75a238 100644
--- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
+++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -17,7 +17,7 @@ LL |     let y = x as dyn MyAdd<i32>;
    |                  ^^^^^^^^^^^^^^ `MyAdd` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:6:55
    |
 LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
diff --git a/tests/ui/type_length_limit.rs b/tests/ui/type_length_limit.rs
index 87f5ffd76d7..b629455aced 100644
--- a/tests/ui/type_length_limit.rs
+++ b/tests/ui/type_length_limit.rs
@@ -2,6 +2,9 @@
 //@ compile-flags: -Copt-level=0 -Zenforce-type-length-limit
 //~^^ ERROR reached the type-length limit
 
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type.txt'"
+
 // Test that the type length limit can be changed.
 // The exact type depends on optimizations, so disable them.
 
diff --git a/tests/ui/type_length_limit.stderr b/tests/ui/type_length_limit.stderr
index 83353547d34..d913b661c6f 100644
--- a/tests/ui/type_length_limit.stderr
+++ b/tests/ui/type_length_limit.stderr
@@ -1,11 +1,11 @@
 error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
-  --> $DIR/type_length_limit.rs:32:5
+  --> $DIR/type_length_limit.rs:35:5
    |
 LL |     drop::<Option<A>>(None);
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
-   = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
+   = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type.txt'
 
 error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
    |
diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr
index 7be327e61d1..0c293e3576d 100644
--- a/tests/ui/wf/issue-87495.stderr
+++ b/tests/ui/wf/issue-87495.stderr
@@ -5,7 +5,7 @@ LL |     const CONST: (bool, dyn T);
    |                         ^^^^^ `T` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/issue-87495.rs:4:11
    |
 LL | trait T {
diff --git a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr
index 0b7f4cd4362..f3e4f2a63e9 100644
--- a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr
+++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr
@@ -5,7 +5,7 @@ LL |     let t_box: Box<dyn Trait> = Box::new(S);
    |                                 ^^^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14
    |
 LL | trait Trait: Sized {}
@@ -22,7 +22,7 @@ LL |     takes_box(Box::new(S));
    |               ^^^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14
    |
 LL | trait Trait: Sized {}
@@ -39,7 +39,7 @@ LL |     Box::new(S) as Box<dyn Trait>;
    |     ^^^^^^^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14
    |
 LL | trait Trait: Sized {}
diff --git a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr
index 3f50e1192cf..716d0e78ff1 100644
--- a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr
+++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr
@@ -5,7 +5,7 @@ LL |     let t: &dyn Trait = &S;
    |                         ^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14
    |
 LL | trait Trait: Sized {}
@@ -22,7 +22,7 @@ LL |     takes_trait(&S);
    |                 ^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14
    |
 LL | trait Trait: Sized {}
@@ -39,7 +39,7 @@ LL |     &S as &dyn Trait;
    |     ^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14
    |
 LL | trait Trait: Sized {}
diff --git a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr
index 8f68f9c5b6b..a7405ce4caa 100644
--- a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr
@@ -19,7 +19,7 @@ LL |         Some(()) => &S,
    |                     ^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14
    |
 LL | trait Trait: Sized {}
@@ -40,7 +40,7 @@ LL |         None => &R,
    |                 ^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14
    |
 LL | trait Trait: Sized {}
diff --git a/tests/ui/wf/wf-dyn-incompatible.stderr b/tests/ui/wf/wf-dyn-incompatible.stderr
index 1803376aaa1..e61b37d9293 100644
--- a/tests/ui/wf/wf-dyn-incompatible.stderr
+++ b/tests/ui/wf/wf-dyn-incompatible.stderr
@@ -5,7 +5,7 @@ LL |     let _x: &dyn A;
    |             ^^^^^^ `A` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
   --> $DIR/wf-dyn-incompatible.rs:5:23
    |
 LL | trait A {
diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr
index d73376e9861..b419bc8347f 100644
--- a/tests/ui/wf/wf-fn-where-clause.stderr
+++ b/tests/ui/wf/wf-fn-where-clause.stderr
@@ -22,7 +22,7 @@ LL | fn bar() where Vec<dyn Copy>:, {}
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
-           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 
 error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time
   --> $DIR/wf-fn-where-clause.rs:12:16
diff --git a/tests/ui/wf/wf-trait-default-fn-ret.rs b/tests/ui/wf/wf-trait-default-fn-ret.rs
index 2103dae8d23..a7f83dcf678 100644
--- a/tests/ui/wf/wf-trait-default-fn-ret.rs
+++ b/tests/ui/wf/wf-trait-default-fn-ret.rs
@@ -1,5 +1,4 @@
-// Check that we test WF conditions for fn arguments. Because the
-// current code is so goofy, this is only a warning for now.
+// Check that we test WF conditions for fn arguments.
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/tests/ui/wf/wf-trait-default-fn-ret.stderr b/tests/ui/wf/wf-trait-default-fn-ret.stderr
index f749ac7b1b3..f0d1b55edc4 100644
--- a/tests/ui/wf/wf-trait-default-fn-ret.stderr
+++ b/tests/ui/wf/wf-trait-default-fn-ret.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Self: Eq` is not satisfied
-  --> $DIR/wf-trait-default-fn-ret.rs:11:22
+  --> $DIR/wf-trait-default-fn-ret.rs:10:22
    |
 LL |     fn bar(&self) -> Bar<Self> {
    |                      ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
    |
 note: required by a bound in `Bar`
-  --> $DIR/wf-trait-default-fn-ret.rs:8:14
+  --> $DIR/wf-trait-default-fn-ret.rs:7:14
    |
 LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    |              ^^ required by this bound in `Bar`
diff --git a/triagebot.toml b/triagebot.toml
index 29c84e19c56..49cf1213987 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1025,7 +1025,6 @@ users_on_vacation = [
     "nnethercote",
     "workingjubilee",
     "kobzol",
-    "jieyouxu",
 ]
 
 [[assign.warn_non_default_branch.exceptions]]