about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock4
-rw-r--r--compiler/rustc_ast/src/util/parser.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/glue.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs8
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs19
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0206.md8
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0794.md64
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs24
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs8
-rw-r--r--compiler/rustc_hir/src/intravisit.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs12
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs61
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs9
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs34
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs8
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs32
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs8
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs5
-rw-r--r--compiler/rustc_lint/messages.ftl3
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs8
-rw-r--r--compiler/rustc_lint/src/reexports.rs82
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs17
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs1
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs20
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs47
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs19
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs133
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs5
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs3
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs16
-rw-r--r--compiler/rustc_resolve/src/late.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs37
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs41
-rw-r--r--library/alloc/src/lib.rs4
-rw-r--r--library/core/src/error.rs4
-rw-r--r--library/core/src/ffi/c_str.rs8
-rw-r--r--library/core/src/fmt/mod.rs6
-rw-r--r--library/core/src/fmt/rt/v1.rs6
-rw-r--r--library/core/src/hash/mod.rs2
-rw-r--r--library/core/src/iter/mod.rs2
-rw-r--r--library/core/src/iter/range.rs32
-rw-r--r--library/core/src/iter/traits/double_ended.rs11
-rw-r--r--library/core/src/iter/traits/iterator.rs15
-rw-r--r--library/core/src/iter/traits/marker.rs3
-rw-r--r--library/core/src/lib.rs7
-rw-r--r--library/core/src/macros/mod.rs4
-rw-r--r--library/core/src/marker.rs5
-rw-r--r--library/core/src/net/socket_addr.rs26
-rw-r--r--library/core/src/ops/try_trait.rs9
-rw-r--r--library/core/src/pin.rs35
-rw-r--r--library/core/src/sync/atomic.rs45
-rw-r--r--library/core/tests/iter/consts.rs36
-rw-r--r--library/core/tests/iter/mod.rs2
-rw-r--r--library/core/tests/lib.rs3
-rw-r--r--library/std/src/io/mod.rs18
-rw-r--r--library/std/src/os/android/net.rs4
-rw-r--r--library/std/src/os/fd/owned.rs2
-rw-r--r--library/std/src/os/fd/raw.rs2
-rw-r--r--library/std/src/os/linux/net.rs4
-rw-r--r--library/std/src/os/net/linux_ext/addr.rs6
-rw-r--r--library/std/src/os/net/linux_ext/mod.rs2
-rw-r--r--library/std/src/os/unix/net/addr.rs4
-rw-r--r--library/std/src/os/unix/net/datagram.rs9
-rw-r--r--library/std/src/os/unix/net/listener.rs3
-rw-r--r--library/std/src/os/unix/net/stream.rs3
-rw-r--r--library/std/src/panic.rs3
-rw-r--r--library/std/src/sys/mod.rs9
-rw-r--r--library/std/src/sys/windows/fs.rs12
-rw-r--r--src/bootstrap/compile.rs6
-rw-r--r--src/bootstrap/config.rs9
-rw-r--r--src/bootstrap/install.rs11
-rw-r--r--src/bootstrap/test.rs6
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile4
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh2
-rw-r--r--src/ci/stage-build.py4
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/html/format.rs14
-rw-r--r--src/librustdoc/html/templates/STYLE.md14
-rw-r--r--src/stage0.json796
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs1
-rw-r--r--src/tools/compiletest/src/runtest.rs50
-rw-r--r--src/tools/miri/.github/workflows/ci.yml8
-rw-r--r--src/tools/miri/CONTRIBUTING.md11
-rw-r--r--src/tools/miri/README.md151
-rwxr-xr-xsrc/tools/miri/ci.sh4
-rwxr-xr-xsrc/tools/miri/miri9
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs70
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs592
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs539
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs307
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs554
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs304
-rw-r--r--src/tools/miri/src/diagnostics.rs14
-rw-r--r--src/tools/miri/src/eval.rs4
-rw-r--r--src/tools/miri/src/helpers.rs20
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/src/machine.rs8
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs41
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs4
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs67
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd.rs15
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd/epoll.rs8
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd/event.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd/socketpair.rs4
-rw-r--r--src/tools/miri/tests/compiletest.rs6
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs2
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/alternate-read-write.rs19
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/alternate-read-write.stderr14
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/fragile-data-race.rs42
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/fragile-data-race.stderr14
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/outside-range.rs22
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/outside-range.stderr19
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/read-to-local.rs14
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/read-to-local.stderr14
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.rs34
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.stderr28
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.rs32
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.stderr28
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/retag-data-race.rs28
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/retag-data-race.stderr25
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/write-during-2phase.rs27
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/write-during-2phase.stderr26
-rw-r--r--src/tools/miri/tests/pass/adjacent-allocs.rs2
-rw-r--r--src/tools/miri/tests/pass/associated-const.rs2
-rw-r--r--src/tools/miri/tests/pass/assume_bug.rs2
-rw-r--r--src/tools/miri/tests/pass/atomic.rs2
-rw-r--r--src/tools/miri/tests/pass/available-parallelism.rs2
-rw-r--r--src/tools/miri/tests/pass/box-custom-alloc.rs2
-rw-r--r--src/tools/miri/tests/pass/box.rs2
-rw-r--r--src/tools/miri/tests/pass/box.stack.stderr (renamed from src/tools/miri/tests/pass/box.stderr)0
-rw-r--r--src/tools/miri/tests/pass/box.stack.stdout (renamed from src/tools/miri/tests/pass/box.stdout)0
-rw-r--r--src/tools/miri/tests/pass/box.tree.stdout3
-rw-r--r--src/tools/miri/tests/pass/btreemap.rs2
-rw-r--r--src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/channels.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/sync.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/sync.stack.stdout (renamed from src/tools/miri/tests/pass/concurrency/sync.stdout)0
-rw-r--r--src/tools/miri/tests/pass/concurrency/sync.tree.stdout20
-rw-r--r--src/tools/miri/tests/pass/concurrency/thread_locals.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs3
-rw-r--r--src/tools/miri/tests/pass/concurrency/tls_lib_drop.stack.stdout (renamed from src/tools/miri/tests/pass/concurrency/tls_lib_drop.stdout)0
-rw-r--r--src/tools/miri/tests/pass/concurrency/tls_lib_drop.tree.stdout5
-rw-r--r--src/tools/miri/tests/pass/disable-alignment-check.rs2
-rw-r--r--src/tools/miri/tests/pass/dyn-arbitrary-self.rs2
-rw-r--r--src/tools/miri/tests/pass/extern_types.rs2
-rw-r--r--src/tools/miri/tests/pass/extern_types.stack.stderr (renamed from src/tools/miri/tests/pass/extern_types.stderr)0
-rw-r--r--src/tools/miri/tests/pass/float.rs30
-rw-r--r--src/tools/miri/tests/pass/future-self-referential.rs (renamed from src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs)3
-rw-r--r--src/tools/miri/tests/pass/generator.rs2
-rw-r--r--src/tools/miri/tests/pass/hashmap.rs2
-rw-r--r--src/tools/miri/tests/pass/intptrcast.rs2
-rw-r--r--src/tools/miri/tests/pass/linked-list.rs2
-rw-r--r--src/tools/miri/tests/pass/many_shr_bor.rs2
-rw-r--r--src/tools/miri/tests/pass/memleak_ignored.rs2
-rw-r--r--src/tools/miri/tests/pass/option_box_transmute_ptr.rs2
-rw-r--r--src/tools/miri/tests/pass/pointers.rs2
-rw-r--r--src/tools/miri/tests/pass/provenance.rs2
-rw-r--r--src/tools/miri/tests/pass/ptr_int_casts.rs2
-rw-r--r--src/tools/miri/tests/pass/ptr_int_from_exposed.rs2
-rw-r--r--src/tools/miri/tests/pass/ptr_int_transmute.rs2
-rw-r--r--src/tools/miri/tests/pass/rc.rs2
-rw-r--r--src/tools/miri/tests/pass/send-is-not-static-par-for.rs2
-rw-r--r--src/tools/miri/tests/pass/slices.rs2
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs6
-rw-r--r--src/tools/miri/tests/pass/threadleak_ignored.rs2
-rw-r--r--src/tools/miri/tests/pass/threadleak_ignored.stack.stderr (renamed from src/tools/miri/tests/pass/threadleak_ignored.stderr)0
-rw-r--r--src/tools/miri/tests/pass/threadleak_ignored.tree.stderr1
-rw-r--r--src/tools/miri/tests/pass/transmute_ptr.rs2
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/2phase-interiormut.rs27
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.rs27
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.stderr10
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/copy-nonoverlapping.rs29
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/end-of-protector.rs32
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/end-of-protector.stderr32
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/formatting.rs73
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/formatting.stderr29
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/read-only-from-mut.rs14
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.rs24
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.stderr13
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/reserved.rs127
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/reserved.stderr52
-rw-r--r--src/tools/miri/tests/pass/tree-borrows/transmute-unsafecell.rs13
-rw-r--r--src/tools/miri/tests/pass/unsized.rs2
-rw-r--r--src/tools/miri/tests/pass/vec.rs2
-rw-r--r--src/tools/miri/tests/pass/vecdeque.rs2
-rw-r--r--src/tools/miri/tests/pass/vecdeque.stack.stdout (renamed from src/tools/miri/tests/pass/vecdeque.stdout)0
-rw-r--r--src/tools/miri/tests/pass/vecdeque.tree.stdout2
-rw-r--r--src/tools/miri/tests/utils/macros.rs61
-rw-r--r--src/tools/miri/tests/utils/miri_extern.rs142
-rw-r--r--src/tools/miri/tests/utils/mod.rs2
-rw-r--r--src/tools/tidy/src/bins.rs2
-rw-r--r--src/tools/tidy/src/debug_artifacts.rs12
-rw-r--r--src/tools/tidy/src/features.rs17
-rw-r--r--src/tools/tidy/src/main.rs21
-rw-r--r--src/tools/tidy/src/pal.rs1
-rw-r--r--src/tools/tidy/src/style.rs31
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs100
-rw-r--r--src/tools/tidy/src/ui_tests.rs122
-rw-r--r--src/tools/tidy/src/walk.rs30
-rw-r--r--tests/codegen/inherit_overflow.rs2
-rw-r--r--tests/incremental/auxiliary/circular-dependencies-aux.rs10
-rw-r--r--tests/incremental/circular-dependencies.rs37
-rw-r--r--tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir80
-rw-r--r--tests/ui/async-await/async-trait-fn.current.stderr42
-rw-r--r--tests/ui/async-await/async-trait-fn.next.stderr42
-rw-r--r--tests/ui/async-await/async-trait-fn.rs1
-rw-r--r--tests/ui/async-await/async-trait-fn.stderr6
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.current.stderr (renamed from tests/ui/async-await/edition-deny-async-fns-2015.stderr)20
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.next.stderr98
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr (renamed from tests/ui/async-await/in-trait/async-default-fn-overridden.stderr)2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.current.stderr (renamed from tests/ui/async-await/in-trait/async-generics-and-bounds.stderr)12
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics.current.stderr (renamed from tests/ui/async-await/in-trait/async-generics.stderr)12
-rw-r--r--tests/ui/async-await/in-trait/async-generics.next.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics.rs2
-rw-r--r--tests/ui/async-await/in-trait/generics-mismatch.current.stderr16
-rw-r--r--tests/ui/async-await/in-trait/generics-mismatch.next.stderr16
-rw-r--r--tests/ui/async-await/in-trait/generics-mismatch.rs15
-rw-r--r--tests/ui/async-await/in-trait/generics-mismatch.stderr16
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.current.stderr (renamed from tests/ui/async-await/in-trait/return-type-suggestion.stderr)4
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.next.stderr23
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.rs2
-rw-r--r--tests/ui/const-generics/const-arg-in-const-arg.full.stderr17
-rw-r--r--tests/ui/const-generics/const-arg-in-const-arg.min.stderr18
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr (renamed from tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-body-type-err.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr)6
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr24
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-method-constraint.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.current.stderr (renamed from tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr)4
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr17
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/generics-mismatch.current.stderr (renamed from tests/ui/impl-trait/in-trait/generics-mismatch.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/generics-mismatch.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.current.stderr (renamed from tests/ui/impl-trait/in-trait/issue-102571.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.next.stderr14
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.current.stderr (renamed from tests/ui/impl-trait/in-trait/specialization-broken.stderr)6
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.next.stderr31
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.current.stderr (renamed from tests/ui/impl-trait/in-trait/wf-bounds.stderr)6
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.next.stderr30
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.rs2
-rw-r--r--tests/ui/imports/issue-99695-b.fixed2
-rw-r--r--tests/ui/imports/issue-99695-b.rs2
-rw-r--r--tests/ui/imports/issue-99695.fixed2
-rw-r--r--tests/ui/imports/issue-99695.rs2
-rw-r--r--tests/ui/late-bound-lifetimes/issue-80618.rs8
-rw-r--r--tests/ui/late-bound-lifetimes/issue-80618.stderr15
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.rs5
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.stderr21
-rw-r--r--tests/ui/lint/anonymous-reexport.rs21
-rw-r--r--tests/ui/lint/anonymous-reexport.stderr55
-rw-r--r--tests/ui/macros/issue-109237.rs7
-rw-r--r--tests/ui/macros/issue-109237.stderr18
-rw-r--r--tests/ui/methods/method-call-lifetime-args-fail.stderr31
-rw-r--r--tests/ui/methods/method-call-lifetime-args.stderr5
-rw-r--r--tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs13
-rw-r--r--tests/ui/stability-attribute/issue-109177.rs13
-rw-r--r--tests/ui/stability-attribute/issue-109177.stderr21
-rw-r--r--tests/ui/suggestions/bad-infer-in-trait-impl.rs10
-rw-r--r--tests/ui/suggestions/bad-infer-in-trait-impl.stderr14
-rw-r--r--tests/ui/suggestions/suggest-ret-on-async-w-late.rs11
-rw-r--r--tests/ui/suggestions/suggest-ret-on-async-w-late.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr18
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.rs1
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.stderr15
339 files changed, 6301 insertions, 1509 deletions
diff --git a/.gitignore b/.gitignore
index ce797a7a837..04d2597ecc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ no_llvm_build
 /llvm/
 /mingw-build/
 build/
+!/compiler/rustc_mir_build/src/build/
 /build-rust-analyzer/
 /dist/
 /unicode-downloads
diff --git a/Cargo.lock b/Cargo.lock
index 49b89c71994..1d40b8acc66 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1365,9 +1365,9 @@ dependencies = [
 
 [[package]]
 name = "ena"
-version = "0.14.1"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d"
+checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
 dependencies = [
  "log",
 ]
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 3a0af04f9eb..3893875e9a4 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -259,7 +259,6 @@ pub enum ExprPrecedence {
     Assign,
     AssignOp,
 
-    Box,
     AddrOf,
     Let,
     Unary,
@@ -319,8 +318,7 @@ impl ExprPrecedence {
             ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
 
             // Unary, prefix
-            ExprPrecedence::Box
-            | ExprPrecedence::AddrOf
+            ExprPrecedence::AddrOf
             // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.
             // However, this is not exactly right. When `let _ = a` is the LHS of a binop we
             // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 905d8c42b28..dbf15a3e05f 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -255,7 +255,7 @@ fn sccs_info<'cx, 'tcx>(
     let var_to_origin = infcx.reg_var_to_origin.borrow();
 
     let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::<Vec<_>>();
-    var_to_origin_sorted.sort_by(|a, b| a.0.cmp(&b.0));
+    var_to_origin_sorted.sort_by_key(|vto| vto.0);
     let mut debug_str = "region variables to origins:\n".to_string();
     for (reg_var, origin) in var_to_origin_sorted.into_iter() {
         debug_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin));
@@ -2216,7 +2216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // is in the same SCC or something. In that case, find what
         // appears to be the most interesting point to report to the
         // user via an even more ad-hoc guess.
-        categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
+        categorized_path.sort_by_key(|p| p.category);
         debug!("sorted_path={:#?}", categorized_path);
 
         (categorized_path.remove(0), extra_info)
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index d0af3729b23..1b8e9312e2f 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -346,17 +346,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 crate::abi::codegen_return(fx);
             }
             TerminatorKind::Assert { cond, expected, msg, target, cleanup: _ } => {
-                if !fx.tcx.sess.overflow_checks() {
-                    let overflow_not_to_check = match msg {
-                        AssertKind::OverflowNeg(..) => true,
-                        AssertKind::Overflow(op, ..) => op.is_checkable(),
-                        _ => false,
-                    };
-                    if overflow_not_to_check {
-                        let target = fx.get_block(*target);
-                        fx.bcx.ins().jump(target, &[]);
-                        continue;
-                    }
+                if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() {
+                    let target = fx.get_block(*target);
+                    fx.bcx.ins().jump(target, &[]);
+                    continue;
                 }
                 let cond = codegen_operand(fx, cond).load_scalar(fx);
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 64742bbb986..6a0d0ca55c2 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1199,7 +1199,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
                     .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
                     .unwrap_or(stem);
 
-                // GCC can have an optional target prefix.
+                // GCC/Clang can have an optional target prefix.
                 let flavor = if stem == "emcc" {
                     LinkerFlavor::EmCc
                 } else if stem == "gcc"
@@ -1207,7 +1207,9 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
                     || stem == "g++"
                     || stem.ends_with("-g++")
                     || stem == "clang"
+                    || stem.ends_with("-clang")
                     || stem == "clang++"
+                    || stem.ends_with("-clang++")
                 {
                     LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target)
                 } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/glue.rs
index 0f6e6032f9b..c34f1dbf856 100644
--- a/compiler/rustc_codegen_ssa/src/glue.rs
+++ b/compiler/rustc_codegen_ssa/src/glue.rs
@@ -46,7 +46,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 // NOTE: ideally, we want the effects of both `unchecked_smul` and `unchecked_umul`
                 // (resulting in `mul nsw nuw` in LLVM IR), since we know that the multiplication
                 // cannot signed wrap, and that both operands are non-negative. But at the time of writing,
-                // `BuilderMethods` can't do this, and it doesn't seem to enable any further optimizations.
+                // the `LLVM-C` binding can't do this, and it doesn't seem to enable any further optimizations.
                 bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())),
                 bx.const_usize(unit.align.abi.bytes()),
             )
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 71c71d59b7a..f9aa2aecf65 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -563,15 +563,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // with #[rustc_inherit_overflow_checks] and inlined from
         // another crate (mostly core::num generic/#[inline] fns),
         // while the current crate doesn't use overflow checks.
-        if !bx.cx().check_overflow() {
-            let overflow_not_to_check = match msg {
-                AssertKind::OverflowNeg(..) => true,
-                AssertKind::Overflow(op, ..) => op.is_checkable(),
-                _ => false,
-            };
-            if overflow_not_to_check {
-                const_cond = Some(expected);
-            }
+        if !bx.cx().check_overflow() && msg.is_optional_overflow_check() {
+            const_cond = Some(expected);
         }
 
         // Don't codegen the panic block if success if known.
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 92fa59aec6e..c134d3a6b2f 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -155,7 +155,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
 
     /// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually
     /// check for overflow.
-    fn ignore_checkable_overflow_assertions(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+    fn ignore_optional_overflow_checks(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
     /// Entry point for obtaining the MIR of anything that should get evaluated.
     /// So not just functions and shims, but also const/static initializers, anonymous
@@ -474,7 +474,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     }
 
     #[inline(always)]
-    fn ignore_checkable_overflow_assertions(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
+    fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
         false
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 685a5599cde..c2d1bc11c37 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -138,12 +138,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                let ignored = M::ignore_checkable_overflow_assertions(self)
-                    && match msg {
-                        mir::AssertKind::OverflowNeg(..) => true,
-                        mir::AssertKind::Overflow(op, ..) => op.is_checkable(),
-                        _ => false,
-                    };
+                let ignored =
+                    M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check();
                 let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
                 if ignored || expected == cond_val {
                     self.go_to_block(target);
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 29cb2c0a33e..f2a904a6654 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -9,7 +9,7 @@ edition = "2021"
 arrayvec = { version = "0.7", default-features = false }
 bitflags = "1.2.1"
 cfg-if = "1.0"
-ena = "0.14.1"
+ena = "0.14.2"
 indexmap = { version = "1.9.1" }
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 libc = "0.2"
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 91abdaadabd..27a869eb7cd 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -97,7 +97,17 @@ pub trait ObligationProcessor {
     type Error: Debug;
     type OUT: OutcomeTrait<Obligation = Self::Obligation, Error = Error<Self::Obligation, Self::Error>>;
 
-    fn needs_process_obligation(&self, obligation: &Self::Obligation) -> bool;
+    /// Implementations can provide a fast-path to obligation-processing
+    /// by counting the prefix of the passed iterator for which
+    /// `needs_process_obligation` would return false.
+    fn skippable_obligations<'a>(
+        &'a self,
+        _it: impl Iterator<Item = &'a Self::Obligation>,
+    ) -> usize {
+        0
+    }
+
+    fn needs_process_obligation(&self, _obligation: &Self::Obligation) -> bool;
 
     fn process_obligation(
         &mut self,
@@ -416,6 +426,10 @@ impl<O: ForestObligation> ObligationForest<O> {
         loop {
             let mut has_changed = false;
 
+            // This is the super fast path for cheap-to-check conditions.
+            let mut index =
+                processor.skippable_obligations(self.nodes.iter().map(|n| &n.obligation));
+
             // Note that the loop body can append new nodes, and those new nodes
             // will then be processed by subsequent iterations of the loop.
             //
@@ -424,9 +438,8 @@ impl<O: ForestObligation> ObligationForest<O> {
             // `for index in 0..self.nodes.len() { ... }` because the range would
             // be computed with the initial length, and we would miss the appended
             // nodes. Therefore we use a `while` loop.
-            let mut index = 0;
             while let Some(node) = self.nodes.get_mut(index) {
-                // This test is extremely hot.
+                // This is the moderately fast path when the prefix skipping above didn't work out.
                 if node.state.get() != NodeState::Pending
                     || !processor.needs_process_obligation(&node.obligation)
                 {
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index df857be85ad..d104ff0891d 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -513,6 +513,7 @@ E0790: include_str!("./error_codes/E0790.md"),
 E0791: include_str!("./error_codes/E0791.md"),
 E0792: include_str!("./error_codes/E0792.md"),
 E0793: include_str!("./error_codes/E0793.md"),
+E0794: include_str!("./error_codes/E0794.md"),
 }
 
 // Undocumented removed error codes. Note that many removed error codes are documented.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0206.md b/compiler/rustc_error_codes/src/error_codes/E0206.md
index 4405a2149ce..9e85234bdbb 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0206.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0206.md
@@ -1,5 +1,5 @@
-The `Copy` trait was implemented on a type which is neither a struct nor an
-enum.
+The `Copy` trait was implemented on a type which is neither a struct, an
+enum, nor a union.
 
 Erroneous code example:
 
@@ -10,6 +10,6 @@ struct Bar;
 impl Copy for &'static mut Bar { } // error!
 ```
 
-You can only implement `Copy` for a struct or an enum.
+You can only implement `Copy` for a struct, an enum, or a union.
 The previous example will fail because `&'static mut Bar`
-is not a struct or enum.
+is not a struct, an enum, or a union.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0794.md b/compiler/rustc_error_codes/src/error_codes/E0794.md
new file mode 100644
index 00000000000..a33802885c0
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0794.md
@@ -0,0 +1,64 @@
+A lifetime parameter of a function definition is called *late-bound* if it both:
+
+1. appears in an argument type
+2. does not appear in a generic type constraint
+
+You cannot specify lifetime arguments for late-bound lifetime parameters.
+
+Erroneous code example:
+
+```compile_fail,E0794
+fn foo<'a>(x: &'a str) -> &'a str { x }
+let _ = foo::<'static>;
+```
+
+The type of a concrete instance of a generic function is universally quantified
+over late-bound lifetime parameters. This is because we want the function to
+work for any lifetime substituted for the late-bound lifetime parameter, no
+matter where the function is called. Consequently, it doesn't make sense to
+specify arguments for late-bound lifetime parameters, since they are not
+resolved until the function's call site(s).
+
+To fix the issue, remove the specified lifetime:
+
+```
+fn foo<'a>(x: &'a str) -> &'a str { x }
+let _ = foo;
+```
+
+### Additional information
+
+Lifetime parameters that are not late-bound are called *early-bound*.
+Confusion may arise from the fact that late-bound and early-bound
+lifetime parameters are declared the same way in function definitions.
+When referring to a function pointer type, universal quantification over
+late-bound lifetime parameters can be made explicit:
+
+```
+trait BarTrait<'a> {}
+
+struct Bar<'a> {
+    s: &'a str
+}
+
+impl<'a> BarTrait<'a> for Bar<'a> {}
+
+fn bar<'a, 'b, T>(x: &'a str, _t: T) -> &'a str
+where T: BarTrait<'b>
+{
+    x
+}
+
+let bar_fn: for<'a> fn(&'a str, Bar<'static>) -> &'a str = bar; // OK
+let bar_fn2 = bar::<'static, Bar>; // Not allowed
+let bar_fn3 = bar::<Bar>; // OK
+```
+
+In the definition of `bar`, the lifetime parameter `'a` is late-bound, while
+`'b` is early-bound. This is reflected in the type annotation for `bar_fn`,
+where `'a` is universally quantified and `'b` is substituted by a specific
+lifetime. It is not allowed to explicitly specify early-bound lifetime
+arguments when late-bound lifetime parameters are present (as for `bar_fn2`,
+see issue #42868: https://github.com/rust-lang/rust/issues/42868), although the
+types that are constrained by early-bound parameters can be specified (as for
+`bar_fn3`).
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index b1d9cea2773..6bc393c6534 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -245,12 +245,24 @@ pub(super) fn emit_frag_parse_err(
                 e.note(
                     "the macro call doesn't expand to an expression, but it can expand to a statement",
                 );
-                e.span_suggestion_verbose(
-                    site_span.shrink_to_hi(),
-                    "add `;` to interpret the expansion as a statement",
-                    ";",
-                    Applicability::MaybeIncorrect,
-                );
+
+                if parser.token == token::Semi {
+                    if let Ok(snippet) = parser.sess.source_map().span_to_snippet(site_span) {
+                        e.span_suggestion_verbose(
+                            site_span,
+                            "surround the macro invocation with `{}` to interpret the expansion as a statement",
+                            format!("{{ {}; }}", snippet),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                } else {
+                    e.span_suggestion_verbose(
+                        site_span.shrink_to_hi(),
+                        "add `;` to interpret the expansion as a statement",
+                        ";",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
             }
         },
         _ => annotate_err_with_kind(&mut e, kind, site_span),
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index ac93dd555b7..3d644de1665 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -91,7 +91,7 @@ declare_features! (
     /// Allows coercing non capturing closures to function pointers.
     (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
     /// Allows using the CMPXCHG16B target feature.
-    (accepted, cmpxchg16b_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
+    (accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839), None),
     /// Allows usage of the `compile_error!` macro.
     (accepted, compile_error, "1.20.0", Some(40872), None),
     /// Allows `impl Trait` in function return types.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index c893b34b4ac..e0a7c864b94 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -161,7 +161,7 @@ declare_features! (
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
     (active, lang_items, "1.0.0", None, None),
     /// Allows the `multiple_supertrait_upcastable` lint.
-    (active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
+    (active, multiple_supertrait_upcastable, "1.69.0", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
@@ -214,7 +214,7 @@ declare_features! (
     /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed.
     (active, needs_panic_runtime, "1.10.0", Some(32837), None),
     /// Allows using `+bundled,+whole-archive` native libs.
-    (active, packed_bundled_libs, "CURRENT_RUSTC_VERSION", Some(108081), None),
+    (active, packed_bundled_libs, "1.69.0", Some(108081), None),
     /// Allows using the `#![panic_runtime]` attribute.
     (active, panic_runtime, "1.10.0", Some(32837), None),
     /// Allows using `#[rustc_allow_const_fn_unstable]`.
@@ -468,7 +468,7 @@ declare_features! (
     /// Allows using the `non_exhaustive_omitted_patterns` lint.
     (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
     /// Allows `for<T>` binders in where-clauses
-    (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(108185), None),
+    (incomplete, non_lifetime_binders, "1.69.0", Some(108185), None),
     /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f00a5f24e45..f4b46b9a131 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1673,7 +1673,6 @@ pub struct Expr<'hir> {
 impl Expr<'_> {
     pub fn precedence(&self) -> ExprPrecedence {
         match self.kind {
-            ExprKind::Box(_) => ExprPrecedence::Box,
             ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
             ExprKind::Array(_) => ExprPrecedence::Array,
             ExprKind::Call(..) => ExprPrecedence::Call,
@@ -1763,7 +1762,6 @@ impl Expr<'_> {
             | ExprKind::Lit(_)
             | ExprKind::ConstBlock(..)
             | ExprKind::Unary(..)
-            | ExprKind::Box(..)
             | ExprKind::AddrOf(..)
             | ExprKind::Binary(..)
             | ExprKind::Yield(..)
@@ -1851,7 +1849,6 @@ impl Expr<'_> {
             | ExprKind::InlineAsm(..)
             | ExprKind::AssignOp(..)
             | ExprKind::ConstBlock(..)
-            | ExprKind::Box(..)
             | ExprKind::Binary(..)
             | ExprKind::Yield(..)
             | ExprKind::DropTemps(..)
@@ -1862,8 +1859,7 @@ impl Expr<'_> {
     /// To a first-order approximation, is this a pattern?
     pub fn is_approximately_pattern(&self) -> bool {
         match &self.kind {
-            ExprKind::Box(_)
-            | ExprKind::Array(_)
+            ExprKind::Array(_)
             | ExprKind::Call(..)
             | ExprKind::Tup(_)
             | ExprKind::Lit(_)
@@ -1910,8 +1906,6 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
 
 #[derive(Debug, HashStable_Generic)]
 pub enum ExprKind<'hir> {
-    /// A `box x` expression.
-    Box(&'hir Expr<'hir>),
     /// Allow anonymous constants from an inline `const` block
     ConstBlock(AnonConst),
     /// An array (e.g., `[a, b, c, d]`).
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index cc0f64017e4..234256ab553 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -682,7 +682,6 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
     visitor.visit_id(expression.hir_id);
     match expression.kind {
-        ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
         ExprKind::Array(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 2f4963f6bc3..3b5c67de239 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -612,7 +612,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
         if position == GenericArgPosition::Value
             && args.num_lifetime_params() != param_counts.lifetimes
         {
-            let mut err = tcx.sess.struct_span_err(span, msg);
+            let mut err = struct_span_err!(tcx.sess, span, E0794, "{}", msg);
             err.span_note(span_late, note);
             err.emit();
         } else {
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index f830269b45d..2e788de9fab 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2396,13 +2396,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                     tcx,
                                     infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
                                 );
+                                // I guess we don't need to make a universe unless we need it,
+                                // but also we're on the error path, so it doesn't matter here.
+                                let universe = infcx.create_next_universe();
                                 infcx
                                     .can_eq(
                                         ty::ParamEnv::empty(),
                                         impl_.self_ty(),
-                                        // Must fold past escaping bound vars too,
-                                        // since we have those at this point in astconv.
-                                        tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
+                                        tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate {
+                                            regions: &mut |_| tcx.lifetimes.re_erased,
+                                            types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
+                                                universe,
+                                                name: bv.kind,
+                                            }),
+                                            consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
+                                                universe,
+                                                name: bv
+                                            }, ty),
+                                        })
                                     )
                             })
                             && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
@@ -3317,10 +3328,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             tcx,
             trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
         );
+        let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
 
-        let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
-
-        Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty))
+        Some(if let Some(arg_idx) = arg_idx {
+            *fn_sig.inputs().get(arg_idx)?
+        } else {
+            fn_sig.output()
+        })
     }
 
     #[instrument(level = "trace", skip(self, generate_err))]
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 14dc9d89180..872fec3954b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -557,7 +557,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             check_opaque(tcx, id);
         }
         DefKind::ImplTraitPlaceholder => {
-            let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
+            let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
             // Only check the validity of this opaque type if the function has a default body
             if let hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
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 6e6f8c1533b..32b6aeed5f8 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1205,6 +1205,17 @@ fn compare_number_of_generics<'tcx>(
         return Ok(());
     }
 
+    // We never need to emit a separate error for RPITITs, since if an RPITIT
+    // has mismatched type or const generic arguments, then the method that it's
+    // inheriting the generics from will also have mismatched arguments, and
+    // we'll report an error for that instead. Delay a bug for safety, though.
+    if tcx.opt_rpitit_info(trait_.def_id).is_some() {
+        return Err(tcx.sess.delay_span_bug(
+            rustc_span::DUMMY_SP,
+            "errors comparing numbers of generics of trait/impl functions were not emitted",
+        ));
+    }
+
     let matchings = [
         ("type", trait_own_counts.types, impl_own_counts.types),
         ("const", trait_own_counts.consts, impl_own_counts.consts),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 71050864ce0..4120ad45f6a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,6 @@
 use crate::autoderef::Autoderef;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
-use hir::def::DefKind;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -1548,16 +1547,27 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
     if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
         && assoc_item.container == ty::AssocItemContainer::TraitContainer
     {
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
+        // strategy, we can't just call `check_associated_item` on the new RPITITs,
+        // because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
+        // That's because we need to check that the bounds of the RPITIT hold using
+        // the special substs that we create during opaque type lowering, otherwise we're
+        // getting a bunch of early bound and free regions mixed up... Haven't looked too
+        // deep into this, though.
         for arg in fn_output.walk() {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Alias(ty::Opaque, proj) = ty.kind()
-                && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
-                && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
+                // RPITITs are always eagerly normalized into opaques, so always look for an
+                // opaque here.
+                && let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
+                && let Some(opaque_def_id) = opaque_ty.def_id.as_local()
+                && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
+                && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+                && source == fn_def_id
             {
-                let span = tcx.def_span(proj.def_id);
-                let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
+                let span = tcx.def_span(opaque_ty.def_id);
+                let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
                 let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
-                    let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
+                    let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
                     let normalized_bound = wfcx.normalize(span, None, bound);
                     traits::wf::predicate_obligations(
                         wfcx.infcx,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 7dce29cc0bb..df0258ff7a3 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
@@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
     tcx: TyCtxt<'_>,
     def_id: DefId,
 ) -> &'_ [(ty::Predicate<'_>, Span)] {
-    // If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
-    // generated the synthesized associate type.
-    let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
-        tcx.opt_rpitit_info(def_id)
-    {
-        Some(opaque_def_id)
-    } else {
-        None
-    };
+    match tcx.opt_rpitit_info(def_id) {
+        // RPITIT's bounds are the same as opaque type bounds, but with
+        // a projection self type.
+        Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
+            let opaque_ty = item.expect_opaque_ty();
+            return opaque_type_bounds(
+                tcx,
+                opaque_def_id,
+                opaque_ty.bounds,
+                tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
+                item.span,
+            );
+        }
+        // These should have been fed!
+        Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
+        None => {}
+    }
 
-    let bounds_def_id = rpitit_info.unwrap_or(def_id);
-    let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     match tcx.hir().get(hir_id) {
         hir::Node::TraitItem(hir::TraitItem {
             kind: hir::TraitItemKind::Type(bounds, _),
@@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
             ..
         }) => {
             let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            let item_ty = if *in_trait || rpitit_info.is_some() {
+            let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
                 tcx.mk_projection(def_id, substs)
             } else {
                 tcx.mk_opaque(def_id, substs)
             };
-            opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
+            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
         _ => bug!("item_bounds called on {:?}", def_id),
     }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index a8b7699b667..361e8948e85 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -112,10 +112,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
                 ty::Alias(_, ty::AliasTy { def_id, substs, .. })
-                    if matches!(
-                        self.tcx.def_kind(*def_id),
-                        DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
-                    ) =>
+                    if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
+                {
+                    self.visit_opaque(*def_id, substs)
+                }
+                // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
+                // at all for RPITITs.
+                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                    if self.tcx.is_impl_trait_in_trait(*def_id) =>
                 {
                     self.visit_opaque(*def_id, substs)
                 }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index d715b03e40e..63ea6c90477 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1366,10 +1366,6 @@ impl<'a> State<'a> {
         self.ibox(INDENT_UNIT);
         self.ann.pre(self, AnnNode::Expr(expr));
         match expr.kind {
-            hir::ExprKind::Box(expr) => {
-                self.word_space("Box::new");
-                self.print_call_post(std::slice::from_ref(expr));
-            }
             hir::ExprKind::Array(exprs) => {
                 self.print_expr_vec(exprs);
             }
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index e19ef2ff3bf..035ccf30b24 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -299,7 +299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 // check that the `if` expr without `else` is the fn body's expr
                 if expr.span == sp {
-                    return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
+                    return self.get_fn_decl(hir_id).and_then(|(_, fn_decl, _)| {
                         let span = fn_decl.output.span();
                         let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
                         Some((span, format!("expected `{snippet}` because of this return type")))
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 6becf4892ac..ec391ea80f4 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -2,7 +2,6 @@
 
 use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
 
-use hir::def::DefKind;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
@@ -715,14 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .subst_iter_copied(self.tcx, substs)
                 .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
-            ty::Alias(ty::Projection, proj)
-                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
-            {
-                self.tcx
-                    .bound_explicit_item_bounds(proj.def_id)
-                    .subst_iter_copied(self.tcx, proj.substs)
-                    .find_map(|(p, s)| get_future_output(p, s))?
-            }
+            ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
+                .tcx
+                .bound_explicit_item_bounds(proj.def_id)
+                .subst_iter_copied(self.tcx, proj.substs)
+                .find_map(|(p, s)| get_future_output(p, s))?,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
                 "async fn generator return type not an inference variable: {ret_ty}"
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 3d6274ede81..a27905ea46c 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1722,12 +1722,13 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
                 }
             }
-            fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
+            fcx.get_node_fn_decl(parent)
+                .map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
         } else {
             fcx.get_fn_decl(parent_id)
         };
 
-        if let Some((fn_decl, can_suggest)) = fn_decl {
+        if let Some((fn_id, fn_decl, can_suggest)) = fn_decl {
             if blk_id.is_none() {
                 pointing_at_return_type |= fcx.suggest_missing_return_type(
                     &mut err,
@@ -1735,7 +1736,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     expected,
                     found,
                     can_suggest,
-                    fcx.tcx.hir().get_parent_item(id).into(),
+                    fn_id,
                 );
             }
             if !pointing_at_return_type {
@@ -1746,17 +1747,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let parent_id = fcx.tcx.hir().get_parent_item(id);
         let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id);
 
-        if let (Some(expr), Some(_), Some((fn_decl, _, _))) =
+        if let (Some(expr), Some(_), Some((fn_id, fn_decl, _, _))) =
             (expression, blk_id, fcx.get_node_fn_decl(parent_item))
         {
             fcx.suggest_missing_break_or_return_expr(
-                &mut err,
-                expr,
-                fn_decl,
-                expected,
-                found,
-                id,
-                parent_id.into(),
+                &mut err, expr, fn_decl, expected, found, id, fn_id,
             );
         }
 
@@ -1882,7 +1877,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
     }
 
     fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
-        if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id)
+        if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id)
             && let hir::FnRetTy::Return(ty) = fn_decl.output
             && let ty = fcx.astconv().ast_ty_to_ty( ty)
             && let ty::Dynamic(..) = ty.kind()
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index afef331ec1d..29db16849dd 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -284,7 +284,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let tcx = self.tcx;
         match expr.kind {
-            ExprKind::Box(subexpr) => self.check_expr_box(subexpr, expected),
             ExprKind::Lit(ref lit) => self.check_lit(&lit, expected),
             ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected),
             ExprKind::Assign(lhs, rhs, span) => {
@@ -359,16 +358,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn check_expr_box(&self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>) -> Ty<'tcx> {
-        let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| match ty.kind() {
-            ty::Adt(def, _) if def.is_box() => Expectation::rvalue_hint(self, ty.boxed_ty()),
-            _ => NoExpectation,
-        });
-        let referent_ty = self.check_expr_with_expectation(expr, expected_inner);
-        self.require_type_is_sized(referent_ty, expr.span, traits::SizedBoxType);
-        self.tcx.mk_box(referent_ty)
-    }
-
     fn check_expr_unary(
         &self,
         unop: hir::UnOp,
@@ -799,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.ret_coercion_span.set(Some(expr.span));
             }
             let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
-            if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
+            if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
                 coercion.coerce_forced_unit(
                     self,
                     &cause,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index b9a058d6bba..9aa6c7f103f 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -356,10 +356,6 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 self.walk_captures(closure);
             }
 
-            hir::ExprKind::Box(ref base) => {
-                self.consume_expr(base);
-            }
-
             hir::ExprKind::Yield(value, _) => {
                 self.consume_expr(value);
             }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index e539693402a..8455076de56 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -898,51 +898,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
     }
 
-    /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise.
+    /// Given a function `Node`, return its  `HirId` and `FnDecl` if it exists. Given a closure
+    /// that is the child of a function, return that function's `HirId` and `FnDecl` instead.
+    /// This may seem confusing at first, but this is used in diagnostics for `async fn`,
+    /// for example, where most of the type checking actually happens within a nested closure,
+    /// but we often want access to the parent function's signature.
+    ///
+    /// Otherwise, return false.
     pub(in super::super) fn get_node_fn_decl(
         &self,
         node: Node<'tcx>,
-    ) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident, bool)> {
+    ) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
         match node {
-            Node::Item(&hir::Item { ident, kind: hir::ItemKind::Fn(ref sig, ..), .. }) => {
+            Node::Item(&hir::Item {
+                ident,
+                kind: hir::ItemKind::Fn(ref sig, ..),
+                owner_id,
+                ..
+            }) => {
                 // This is less than ideal, it will not suggest a return type span on any
                 // method called `main`, regardless of whether it is actually the entry point,
                 // but it will still present it as the reason for the expected type.
-                Some((&sig.decl, ident, ident.name != sym::main))
+                Some((
+                    hir::HirId::make_owner(owner_id.def_id),
+                    &sig.decl,
+                    ident,
+                    ident.name != sym::main,
+                ))
             }
             Node::TraitItem(&hir::TraitItem {
                 ident,
                 kind: hir::TraitItemKind::Fn(ref sig, ..),
+                owner_id,
                 ..
-            }) => Some((&sig.decl, ident, true)),
+            }) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, true)),
             Node::ImplItem(&hir::ImplItem {
                 ident,
                 kind: hir::ImplItemKind::Fn(ref sig, ..),
+                owner_id,
                 ..
-            }) => Some((&sig.decl, ident, false)),
-            Node::Expr(&hir::Expr {
-                hir_id,
-                kind: hir::ExprKind::Closure(..),
-                ..
-            }) if let Some(Node::Item(&hir::Item {
+            }) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)),
+            Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(..), .. })
+                if let Some(Node::Item(&hir::Item {
+                    ident,
+                    kind: hir::ItemKind::Fn(ref sig, ..),
+                    owner_id,
+                    ..
+                })) = self.tcx.hir().find_parent(hir_id) => Some((
+                hir::HirId::make_owner(owner_id.def_id),
+                &sig.decl,
                 ident,
-                kind: hir::ItemKind::Fn(ref sig, ..),
-                ..
-            })) = self.tcx.hir().find_parent(hir_id) => {
-                Some((&sig.decl, ident, ident.name != sym::main))
-            },
+                ident.name != sym::main,
+            )),
             _ => None,
         }
     }
 
-    /// Given a `HirId`, return the `FnDecl` of the method it is enclosed by and whether a
+    /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a
     /// suggestion can be made, `None` otherwise.
-    pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, bool)> {
+    pub fn get_fn_decl(
+        &self,
+        blk_id: hir::HirId,
+    ) -> Option<(hir::HirId, &'tcx hir::FnDecl<'tcx>, bool)> {
         // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
         // `while` before reaching it, as block tail returns are not available in them.
         self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
             let parent = self.tcx.hir().get(blk_id);
-            self.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
+            self.get_node_fn_decl(parent)
+                .map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
         })
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 7064ff65384..61338ac613a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
     fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
         let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
-        self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
+        self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
     }
 
     /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 690d8a23826..7a09ea40d79 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -64,8 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let expr = expr.peel_drop_temps();
         self.suggest_missing_semicolon(err, expr, expected, false);
         let mut pointing_at_return_type = false;
-        if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
-            let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
+        if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
             pointing_at_return_type = self.suggest_missing_return_type(
                 err,
                 &fn_decl,
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 7c0402b1c7f..1eeb7d984ee 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -190,7 +190,6 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
             //
             // Some of these may be interesting in the future
             ExprKind::Path(..)
-            | ExprKind::Box(..)
             | ExprKind::ConstBlock(..)
             | ExprKind::Array(..)
             | ExprKind::Call(..)
@@ -478,7 +477,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
             | ExprKind::AssignOp(..)
             | ExprKind::Binary(..)
             | ExprKind::Block(..)
-            | ExprKind::Box(..)
             | ExprKind::Cast(..)
             | ExprKind::Closure { .. }
             | ExprKind::ConstBlock(..)
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 4d3969d28aa..9a8d7ca9e33 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -382,7 +382,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             | hir::ExprKind::Struct(..)
             | hir::ExprKind::Repeat(..)
             | hir::ExprKind::InlineAsm(..)
-            | hir::ExprKind::Box(..)
             | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 8f31a79e7b3..b6d39341fe7 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1028,6 +1028,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     true
                 }
             })
+            // ensure that we don't suggest unstable methods
+            .filter(|candidate| {
+                // note that `DUMMY_SP` is ok here because it is only used for
+                // suggestions and macro stuff which isn't applicable here.
+                !matches!(
+                    self.tcx.eval_stability(candidate.item.def_id, None, DUMMY_SP, None),
+                    stability::EvalResult::Deny { .. }
+                )
+            })
             .map(|candidate| candidate.item.ident(self.tcx))
             .filter(|&name| set.insert(name))
             .collect();
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ac4986a577c..fd16363a1db 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -359,10 +359,12 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let (def_id, substs) = match *ty.kind() {
             ty::Alias(_, ty::AliasTy { def_id, substs, .. })
-                if matches!(
-                    self.tcx.def_kind(def_id),
-                    DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
-                ) =>
+                if matches!(self.tcx.def_kind(def_id), DefKind::OpaqueTy) =>
+            {
+                (def_id, substs)
+            }
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                if self.tcx.is_impl_trait_in_trait(def_id) =>
             {
                 (def_id, substs)
             }
@@ -613,9 +615,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
 
         let report_path_match = |err: &mut Diagnostic, did1: DefId, did2: DefId| {
-            // Only external crates, if either is from a local
-            // module we could have false positives
-            if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
+            // Only report definitions from different crates. If both definitions
+            // are from a local module we could have false positives, e.g.
+            // let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
+            if did1.krate != did2.krate {
                 let abs_path =
                     |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]);
 
@@ -627,10 +630,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 };
                 if same_path().unwrap_or(false) {
                     let crate_name = self.tcx.crate_name(did1.krate);
-                    err.note(&format!(
-                        "perhaps two different versions of crate `{}` are being used?",
-                        crate_name
-                    ));
+                    let msg = if did1.is_local() || did2.is_local() {
+                        format!(
+                            "the crate `{crate_name}` is compiled multiple times, possibly with different configurations"
+                        )
+                    } else {
+                        format!(
+                            "perhaps two different versions of crate `{crate_name}` are being used?"
+                        )
+                    };
+                    err.note(msg);
                 }
             }
         };
@@ -1757,8 +1766,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 )
                             }
                             (true, ty::Alias(ty::Projection, proj))
-                                if self.tcx.def_kind(proj.def_id)
-                                    == DefKind::ImplTraitPlaceholder =>
+                                if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
                             {
                                 let sm = self.tcx.sess.source_map();
                                 let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index b33729d0be5..b38bbdfe7bb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -1,7 +1,7 @@
 use super::TypeErrCtxt;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, Diagnostic, MultiSpan};
-use rustc_hir::{self as hir, def::DefKind};
+use rustc_hir as hir;
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::Printer;
@@ -75,7 +75,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         diag.note("an associated type was expected, but a different one was found");
                     }
                     (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
-                        if tcx.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
+                        if !tcx.is_impl_trait_in_trait(proj.def_id) =>
                     {
                         let p_def_id = tcx
                             .generics_of(body_owner_def_id)
@@ -222,7 +222,7 @@ impl<T> Trait<T> for X {
                             diag.span_label(p_span, "this type parameter");
                         }
                     }
-                    (ty::Alias(ty::Projection, proj_ty), _) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+                    (ty::Alias(ty::Projection, proj_ty), _) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
                         self.expected_projection(
                             diag,
                             proj_ty,
@@ -231,7 +231,7 @@ impl<T> Trait<T> for X {
                             cause.code(),
                         );
                     }
-                    (_, ty::Alias(ty::Projection, proj_ty)) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+                    (_, ty::Alias(ty::Projection, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
                         let msg = format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 96e7c095d34..aeb4ddb4212 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -188,6 +188,16 @@ impl<'tcx> InferCtxtInner<'tcx> {
     }
 
     #[inline]
+    fn try_type_variables_probe_ref(
+        &self,
+        vid: ty::TyVid,
+    ) -> Option<&type_variable::TypeVariableValue<'tcx>> {
+        // Uses a read-only view of the unification table, this way we don't
+        // need an undo log.
+        self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
+    }
+
+    #[inline]
     fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> {
         self.type_variable_storage.with_log(&mut self.undo_log)
     }
@@ -1646,6 +1656,28 @@ impl<'tcx> InferCtxt<'tcx> {
         tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
     }
 
+    /// The returned function is used in a fast path. If it returns `true` the variable is
+    /// unchanged, `false` indicates that the status is unknown.
+    #[inline]
+    pub fn is_ty_infer_var_definitely_unchanged<'a>(
+        &'a self,
+    ) -> (impl Fn(TyOrConstInferVar<'tcx>) -> bool + 'a) {
+        // This hoists the borrow/release out of the loop body.
+        let inner = self.inner.try_borrow();
+
+        return move |infer_var: TyOrConstInferVar<'tcx>| match (infer_var, &inner) {
+            (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
+                use self::type_variable::TypeVariableValue;
+
+                match inner.try_type_variables_probe_ref(ty_var) {
+                    Some(TypeVariableValue::Unknown { .. }) => true,
+                    _ => false,
+                }
+            }
+            _ => false,
+        };
+    }
+
     /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
     ///   * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
     ///   * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index ed4bc594d1a..49f823a47b8 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -3,7 +3,6 @@ use super::{DefineOpaqueTypes, InferResult};
 use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
 use crate::traits;
-use hir::def::DefKind;
 use hir::def_id::{DefId, LocalDefId};
 use hir::OpaqueTyOrigin;
 use rustc_data_structures::sync::Lrc;
@@ -478,9 +477,7 @@ where
                 }
             }
 
-            ty::Alias(ty::Projection, proj)
-                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
-            {
+            ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => {
                 // Skip lifetime parameters that are not captures.
                 let variances = self.tcx.variances_of(proj.def_id);
 
@@ -559,8 +556,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     // FIXME(RPITIT): Don't replace RPITITs with inference vars.
                     ty::Alias(ty::Projection, projection_ty)
                         if !projection_ty.has_escaping_bound_vars()
-                            && tcx.def_kind(projection_ty.def_id)
-                                != DefKind::ImplTraitPlaceholder =>
+                            && !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
                     {
                         self.infer_projection(
                             param_env,
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index 263c6a47dd2..f7ab05b2d49 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -190,6 +190,11 @@ impl<'tcx> TypeVariableStorage<'tcx> {
     ) -> TypeVariableTable<'a, 'tcx> {
         TypeVariableTable { storage: self, undo_log }
     }
+
+    #[inline]
+    pub(crate) fn eq_relations_ref(&self) -> &ut::UnificationTableStorage<TyVidEqKey<'tcx>> {
+        &self.eq_relations
+    }
 }
 
 impl<'tcx> TypeVariableTable<'_, 'tcx> {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 68e62c9789a..c822237413c 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -508,3 +508,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
     .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
 
 lint_opaque_hidden_inferred_bound_sugg = add this bound
+
+lint_useless_anonymous_reexport = useless anonymous re-export
+    .note = only anonymous re-exports of traits are useful, this is {$article} `{$desc}`
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index b3578540516..c2cc2fcdf55 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -74,6 +74,7 @@ mod opaque_hidden_inferred_bound;
 mod pass_by_value;
 mod passes;
 mod redundant_semicolon;
+mod reexports;
 mod traits;
 mod types;
 mod unused;
@@ -111,6 +112,7 @@ use noop_method_call::*;
 use opaque_hidden_inferred_bound::*;
 use pass_by_value::*;
 use redundant_semicolon::*;
+use reexports::*;
 use traits::*;
 use types::*;
 use unused::*;
@@ -242,6 +244,7 @@ late_lint_methods!(
             OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
             MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
             MapUnitFn: MapUnitFn,
+            UselessAnonymousReexport: UselessAnonymousReexport,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 308c02929ca..46a025f41e0 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1528,3 +1528,11 @@ pub struct UnusedAllocationDiag;
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_allocation_mut)]
 pub struct UnusedAllocationMutDiag;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_useless_anonymous_reexport)]
+#[note]
+pub struct UselessAnonymousReexportDiag {
+    pub article: &'static str,
+    pub desc: &'static str,
+}
diff --git a/compiler/rustc_lint/src/reexports.rs b/compiler/rustc_lint/src/reexports.rs
new file mode 100644
index 00000000000..8737a57ea02
--- /dev/null
+++ b/compiler/rustc_lint/src/reexports.rs
@@ -0,0 +1,82 @@
+use crate::lints::UselessAnonymousReexportDiag;
+use crate::{LateContext, LateLintPass, LintContext};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{Item, ItemKind, UseKind};
+use rustc_middle::ty::Visibility;
+use rustc_span::symbol::kw;
+use rustc_span::Span;
+
+declare_lint! {
+    /// The `useless_anonymous_reexport` lint checks if anonymous re-exports
+    /// are re-exports of traits.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(useless_anonymous_reexport)]
+    ///
+    /// mod sub {
+    ///     pub struct Bar;
+    /// }
+    ///
+    /// pub use self::sub::Bar as _;
+    /// # fn main() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Anonymous re-exports are only useful if it's a re-export of a trait
+    /// in case you want to give access to it. If you re-export any other kind,
+    /// you won't be able to use it since its name won't be accessible.
+    pub USELESS_ANONYMOUS_REEXPORT,
+    Warn,
+    "useless anonymous re-export"
+}
+
+declare_lint_pass!(UselessAnonymousReexport => [USELESS_ANONYMOUS_REEXPORT]);
+
+fn emit_err(cx: &LateContext<'_>, span: Span, def_id: DefId) {
+    let article = cx.tcx.def_descr_article(def_id);
+    let desc = cx.tcx.def_descr(def_id);
+    cx.emit_spanned_lint(
+        USELESS_ANONYMOUS_REEXPORT,
+        span,
+        UselessAnonymousReexportDiag { article, desc },
+    );
+}
+
+impl<'tcx> LateLintPass<'tcx> for UselessAnonymousReexport {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if let ItemKind::Use(path, kind) = item.kind &&
+            !matches!(kind, UseKind::Glob) &&
+            item.ident.name == kw::Underscore &&
+            // We only want re-exports. If it's just a `use X;`, then we ignore it.
+            match cx.tcx.local_visibility(item.owner_id.def_id) {
+                Visibility::Public => true,
+                Visibility::Restricted(level) => {
+                    level != cx.tcx.parent_module_from_def_id(item.owner_id.def_id)
+                }
+            }
+        {
+            for def_id in path.res.iter().filter_map(|r| r.opt_def_id()) {
+                match cx.tcx.def_kind(def_id) {
+                    DefKind::Trait | DefKind::TraitAlias => {}
+                    DefKind::TyAlias => {
+                        let ty = cx.tcx.type_of(def_id);
+                        if !ty.0.is_trait() {
+                            emit_err(cx, item.span, def_id);
+                            break;
+                        }
+                    }
+                    _ => {
+                        emit_err(cx, item.span, def_id);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 9649ce2c5a7..c778574b2c5 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1028,7 +1028,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::InlineConst => true,
 
         DefKind::ImplTraitPlaceholder => {
-            let parent_def_id = tcx.impl_trait_in_trait_parent(def_id.to_def_id());
+            let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
             let assoc_item = tcx.associated_item(parent_def_id);
             match assoc_item.container {
                 // Always encode an RPIT in an impl fn, since it always has a body
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 7d515bb0f5a..42c0354d03a 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1268,6 +1268,13 @@ impl<'tcx> BasicBlockData<'tcx> {
 }
 
 impl<O> AssertKind<O> {
+    /// Returns true if this an overflow checking assertion controlled by -C overflow-checks.
+    pub fn is_optional_overflow_check(&self) -> bool {
+        use AssertKind::*;
+        use BinOp::*;
+        matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..))
+    }
+
     /// Getting a description does not require `O` to be printable, and does not
     /// require allocation.
     /// The caller is expected to handle `BoundsCheck` separately.
@@ -1992,16 +1999,6 @@ impl BorrowKind {
     }
 }
 
-impl BinOp {
-    /// The checkable operators are those whose overflow checking behavior is controlled by
-    /// -Coverflow-checks option. The remaining operators have either no overflow conditions (e.g.,
-    /// BitAnd, BitOr, BitXor) or are always checked for overflow (e.g., Div, Rem).
-    pub fn is_checkable(self) -> bool {
-        use self::BinOp::*;
-        matches!(self, Add | Sub | Mul | Shl | Shr)
-    }
-}
-
 impl<'tcx> Debug for Rvalue<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         use self::Rvalue::*;
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index a28ecfa9bdc..b16b6616415 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -646,8 +646,7 @@ pub enum TerminatorKind<'tcx> {
     /// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR
     /// that is used for CTFE), the following variants of this terminator behave as `goto target`:
     /// - `OverflowNeg(..)`,
-    /// - `Overflow(op, ..)` if op is a "checkable" operation (add, sub, mul, shl, shr, but NOT
-    /// div or rem).
+    /// - `Overflow(op, ..)` if op is add, sub, mul, shl, shr, but NOT div or rem.
     Assert {
         cond: Operand<'tcx>,
         expected: bool,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 2cd79157441..c8860cc55f6 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -191,6 +191,7 @@ rustc_queries! {
     {
         desc { "determine whether the opaque is a type-alias impl trait" }
         separate_provide_extern
+        feedable
     }
 
     query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 6231dd9b6f5..fb3e9cb1263 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -305,8 +305,6 @@ pub enum ObligationCauseCode<'tcx> {
     SizedReturnType,
     /// Yield type must be `Sized`.
     SizedYieldType,
-    /// Box expression result type must be `Sized`.
-    SizedBoxType,
     /// Inline asm operand type must be `Sized`.
     InlineAsmSized,
     /// `[expr; N]` requires `type_of(expr): Copy`.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 04d7de531c2..6ef8384d010 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2552,12 +2552,18 @@ impl<'tcx> TyCtxt<'tcx> {
         matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
     }
 
-    pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId {
-        while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
-            debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
-            def_id = self.parent(def_id);
+    pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId {
+        match self.opt_rpitit_info(def_id) {
+            Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
+            | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
+            None => {
+                while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
+                    debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
+                    def_id = self.parent(def_id);
+                }
+                def_id
+            }
         }
-        def_id
     }
 
     pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
@@ -2572,6 +2578,10 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
 
+        if self.lower_impl_trait_in_trait_to_assoc_ty() {
+            return !self.associated_items_for_impl_trait_in_trait(trait_item_def_id).is_empty();
+        }
+
         // FIXME(RPITIT): This does a somewhat manual walk through the signature
         // of the trait fn to look for any RPITITs, but that's kinda doing a lot
         // of work. We can probably remove this when we refactor RPITITs to be
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b3139d23d36..fffdbfc9660 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -728,7 +728,7 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Alias(ty::Projection, ref data) => {
                 if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
-                    && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+                    && self.tcx().is_impl_trait_in_trait(data.def_id)
                 {
                     return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
                 } else {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 52d114bae30..4c606b939b2 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1288,7 +1288,7 @@ impl<'tcx> AliasTy<'tcx> {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
-                tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
+                tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
             }
             kind => bug!("expected a projection AliasTy; found {kind:?}"),
         }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 9f48986b1ad..140d1154718 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -73,19 +73,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             ExprKind::Binary { op, lhs, rhs } => {
                 let lhs = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[lhs], LocalInfo::Boring, NeedsTemporary::Maybe)
+                    block = this.as_operand(
+                        block,
+                        scope,
+                        &this.thir[lhs],
+                        LocalInfo::Boring,
+                        NeedsTemporary::Maybe
+                    )
                 );
                 let rhs = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[rhs], LocalInfo::Boring, NeedsTemporary::No)
+                    block = this.as_operand(
+                        block,
+                        scope,
+                        &this.thir[rhs],
+                        LocalInfo::Boring,
+                        NeedsTemporary::No
+                    )
                 );
                 this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
             }
             ExprKind::Unary { op, arg } => {
                 let arg = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[arg], LocalInfo::Boring, NeedsTemporary::No)
+                    block = this.as_operand(
+                        block,
+                        scope,
+                        &this.thir[arg],
+                        LocalInfo::Boring,
+                        NeedsTemporary::No
+                    )
                 );
                 // Check for -MIN on signed integers
                 if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
@@ -272,8 +287,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             ExprKind::Pointer { cast, source } => {
                 let source = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[source], LocalInfo::Boring, NeedsTemporary::No)
+                    block = this.as_operand(
+                        block,
+                        scope,
+                        &this.thir[source],
+                        LocalInfo::Boring,
+                        NeedsTemporary::No
+                    )
                 );
                 block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
             }
@@ -502,8 +522,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Category::of(&expr.kind),
                     Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant)
                 ));
-                let operand =
-                    unpack!(block = this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No));
+                let operand = unpack!(
+                    block =
+                        this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
+                );
                 block.and(Rvalue::Use(operand))
             }
         }
@@ -662,8 +684,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // Repeating a const does nothing
         } else {
             // For a non-const, we may need to generate an appropriate `Drop`
-            let value_operand =
-                unpack!(block = this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No));
+            let value_operand = unpack!(
+                block = this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No)
+            );
             if let Operand::Move(to_drop) = value_operand {
                 let success = this.cfg.start_new_block();
                 this.cfg.terminate(
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 22785dfd2ce..2d52102db2c 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2252,7 +2252,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 user_ty: None,
                 source_info,
                 internal: false,
-                local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::RefForGuard))),
+                local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(
+                    BindingForm::RefForGuard,
+                ))),
             });
             self.var_debug_info.push(VarDebugInfo {
                 name,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 6814fd4cb35..80d8b27336c 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -876,21 +876,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 } => {
                     self.local_decls[local].mutability = mutability;
                     self.local_decls[local].source_info.scope = self.source_scope;
-                    **self.local_decls[local].local_info.as_mut().assert_crate_local() = if let Some(kind) = param.self_kind {
-                        LocalInfo::User(
-                            BindingForm::ImplicitSelf(kind),
-                        )
-                    } else {
-                        let binding_mode = ty::BindingMode::BindByValue(mutability);
-                        LocalInfo::User(BindingForm::Var(
-                            VarBindingForm {
+                    **self.local_decls[local].local_info.as_mut().assert_crate_local() =
+                        if let Some(kind) = param.self_kind {
+                            LocalInfo::User(BindingForm::ImplicitSelf(kind))
+                        } else {
+                            let binding_mode = ty::BindingMode::BindByValue(mutability);
+                            LocalInfo::User(BindingForm::Var(VarBindingForm {
                                 binding_mode,
                                 opt_ty_info: param.ty_span,
                                 opt_match_place: Some((None, span)),
                                 pat_span: span,
-                            },
-                        ))
-                    };
+                            }))
+                        };
                     self.var_indices.insert(var, LocalsForNode::One(local));
                 }
                 _ => {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 9086412c09a..cecb8a61aa2 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -780,7 +780,6 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::DropTemps(ref source) => {
                 ExprKind::Use { source: self.mirror_expr(source) }
             }
-            hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) },
             hir::ExprKind::Array(ref fields) => {
                 ExprKind::Array { fields: self.mirror_exprs(fields) }
             }
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index bd12087629c..486275570bd 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -655,26 +655,20 @@ where
     ///
     /// ```text
     /// loop-block:
-    ///    can_go = cur == length_or_end
+    ///    can_go = cur == len
     ///    if can_go then succ else drop-block
     /// drop-block:
-    ///    if ptr_based {
-    ///        ptr = cur
-    ///        cur = cur.offset(1)
-    ///    } else {
-    ///        ptr = &raw mut P[cur]
-    ///        cur = cur + 1
-    ///    }
+    ///    ptr = &raw mut P[cur]
+    ///    cur = cur + 1
     ///    drop(ptr)
     /// ```
     fn drop_loop(
         &mut self,
         succ: BasicBlock,
         cur: Local,
-        length_or_end: Place<'tcx>,
+        len: Local,
         ety: Ty<'tcx>,
         unwind: Unwind,
-        ptr_based: bool,
     ) -> BasicBlock {
         let copy = |place: Place<'tcx>| Operand::Copy(place);
         let move_ = |place: Place<'tcx>| Operand::Move(place);
@@ -683,22 +677,19 @@ where
         let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mut });
         let ptr = Place::from(self.new_temp(ptr_ty));
         let can_go = Place::from(self.new_temp(tcx.types.bool));
-
         let one = self.constant_usize(1);
-        let (ptr_next, cur_next) = if ptr_based {
-            (
-                Rvalue::Use(copy(cur.into())),
-                Rvalue::BinaryOp(BinOp::Offset, Box::new((move_(cur.into()), one))),
-            )
-        } else {
-            (
-                Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
-                Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))),
-            )
-        };
 
         let drop_block = BasicBlockData {
-            statements: vec![self.assign(ptr, ptr_next), self.assign(Place::from(cur), cur_next)],
+            statements: vec![
+                self.assign(
+                    ptr,
+                    Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
+                ),
+                self.assign(
+                    cur.into(),
+                    Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))),
+                ),
+            ],
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
                 source_info: self.source_info,
@@ -711,10 +702,7 @@ where
         let loop_block = BasicBlockData {
             statements: vec![self.assign(
                 can_go,
-                Rvalue::BinaryOp(
-                    BinOp::Eq,
-                    Box::new((copy(Place::from(cur)), copy(length_or_end))),
-                ),
+                Rvalue::BinaryOp(BinOp::Eq, Box::new((copy(Place::from(cur)), copy(len.into())))),
             )],
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
@@ -738,13 +726,6 @@ where
 
     fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> BasicBlock {
         debug!("open_drop_for_array({:?}, {:?})", ety, opt_size);
-
-        // if size_of::<ety>() == 0 {
-        //     index_based_loop
-        // } else {
-        //     ptr_based_loop
-        // }
-
         let tcx = self.tcx();
 
         if let Some(size) = opt_size {
@@ -770,86 +751,36 @@ where
             }
         }
 
-        let move_ = |place: Place<'tcx>| Operand::Move(place);
-        let elem_size = Place::from(self.new_temp(tcx.types.usize));
-        let len = Place::from(self.new_temp(tcx.types.usize));
-
-        let base_block = BasicBlockData {
-            statements: vec![
-                self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
-                self.assign(len, Rvalue::Len(self.place)),
-            ],
-            is_cleanup: self.unwind.is_cleanup(),
-            terminator: Some(Terminator {
-                source_info: self.source_info,
-                kind: TerminatorKind::SwitchInt {
-                    discr: move_(elem_size),
-                    targets: SwitchTargets::static_if(
-                        0,
-                        self.drop_loop_pair(ety, false, len),
-                        self.drop_loop_pair(ety, true, len),
-                    ),
-                },
-            }),
-        };
-        self.elaborator.patch().new_block(base_block)
+        self.drop_loop_pair(ety)
     }
 
     /// Creates a pair of drop-loops of `place`, which drops its contents, even
-    /// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
-    /// otherwise create an index loop.
-    fn drop_loop_pair(
-        &mut self,
-        ety: Ty<'tcx>,
-        ptr_based: bool,
-        length: Place<'tcx>,
-    ) -> BasicBlock {
-        debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based);
+    /// in the case of 1 panic.
+    fn drop_loop_pair(&mut self, ety: Ty<'tcx>) -> BasicBlock {
+        debug!("drop_loop_pair({:?})", ety);
         let tcx = self.tcx();
-        let iter_ty = if ptr_based { tcx.mk_mut_ptr(ety) } else { tcx.types.usize };
+        let len = self.new_temp(tcx.types.usize);
+        let cur = self.new_temp(tcx.types.usize);
 
-        let cur = self.new_temp(iter_ty);
-        let length_or_end = if ptr_based { Place::from(self.new_temp(iter_ty)) } else { length };
+        let unwind =
+            self.unwind.map(|unwind| self.drop_loop(unwind, cur, len, ety, Unwind::InCleanup));
 
-        let unwind = self.unwind.map(|unwind| {
-            self.drop_loop(unwind, cur, length_or_end, ety, Unwind::InCleanup, ptr_based)
-        });
+        let loop_block = self.drop_loop(self.succ, cur, len, ety, unwind);
 
-        let loop_block = self.drop_loop(self.succ, cur, length_or_end, ety, unwind, ptr_based);
-
-        let cur = Place::from(cur);
-        let drop_block_stmts = if ptr_based {
-            let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
-            let tmp = Place::from(self.new_temp(tmp_ty));
-            // tmp = &raw mut P;
-            // cur = tmp as *mut T;
-            // end = Offset(cur, len);
-            let mir_cast_kind = ty::cast::mir_cast_kind(iter_ty, tmp_ty);
-            vec![
-                self.assign(tmp, Rvalue::AddressOf(Mutability::Mut, self.place)),
-                self.assign(cur, Rvalue::Cast(mir_cast_kind, Operand::Move(tmp), iter_ty)),
-                self.assign(
-                    length_or_end,
-                    Rvalue::BinaryOp(
-                        BinOp::Offset,
-                        Box::new((Operand::Copy(cur), Operand::Move(length))),
-                    ),
-                ),
-            ]
-        } else {
-            // cur = 0 (length already pushed)
-            let zero = self.constant_usize(0);
-            vec![self.assign(cur, Rvalue::Use(zero))]
-        };
-        let drop_block = self.elaborator.patch().new_block(BasicBlockData {
-            statements: drop_block_stmts,
+        let zero = self.constant_usize(0);
+        let block = BasicBlockData {
+            statements: vec![
+                self.assign(len.into(), Rvalue::Len(self.place)),
+                self.assign(cur.into(), Rvalue::Use(zero)),
+            ],
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
                 source_info: self.source_info,
                 kind: TerminatorKind::Goto { target: loop_block },
             }),
-        });
+        };
 
+        let drop_block = self.elaborator.patch().new_block(block);
         // FIXME(#34708): handle partially-dropped array/slice elements.
         let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind);
         self.drop_flag_test_block(reset_block, self.succ, unwind)
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 3e0d53029ef..47e032758f2 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -300,7 +300,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         record_variants!(
             (self, e, e.kind, Id::Node(e.hir_id), hir, Expr, ExprKind),
             [
-                Box, ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
+                ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
                 DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index,
                 Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err
             ]
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index db9d0dcc300..36324e6f8da 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -473,7 +473,6 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
             | hir::ExprKind::Struct(..)
             | hir::ExprKind::Repeat(..)
             | hir::ExprKind::InlineAsm(..)
-            | hir::ExprKind::Box(..)
             | hir::ExprKind::Type(..)
             | hir::ExprKind::Err(_)
             | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
@@ -1059,8 +1058,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 self.propagate_through_expr(&l, r_succ)
             }
 
-            hir::ExprKind::Box(ref e)
-            | hir::ExprKind::AddrOf(_, _, ref e)
+            hir::ExprKind::AddrOf(_, _, ref e)
             | hir::ExprKind::Cast(ref e, _)
             | hir::ExprKind::Type(ref e, _)
             | hir::ExprKind::DropTemps(ref e)
@@ -1425,7 +1423,6 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
         | hir::ExprKind::Closure { .. }
         | hir::ExprKind::Path(_)
         | hir::ExprKind::Yield(..)
-        | hir::ExprKind::Box(..)
         | hir::ExprKind::Type(..)
         | hir::ExprKind::Err(_) => {}
     }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index c5b5cf7f5a9..f07a64c7c3c 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -179,8 +179,7 @@ enum ItemKind {
 impl<'tcx> CheckInlineAssembly<'tcx> {
     fn check_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) {
         match expr.kind {
-            ExprKind::Box(..)
-            | ExprKind::ConstBlock(..)
+            ExprKind::ConstBlock(..)
             | ExprKind::Array(..)
             | ExprKind::Call(..)
             | ExprKind::MethodCall(..)
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index ef7c68c1a33..cd676445898 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -132,7 +132,7 @@ where
                 projection.trait_ref_and_own_substs(tcx)
             } else {
                 // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
-                let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
+                let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id);
                 let trait_generics = tcx.generics_of(def_id);
                 (
                     tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 5d40c6e4e48..6e27bcc5bf3 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -85,20 +85,28 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
             Single {
                 ref source,
                 ref target,
+                ref source_bindings,
+                ref target_bindings,
                 ref type_ns_only,
                 ref nested,
                 ref id,
-                // Ignore the following to avoid an infinite loop while printing.
-                source_bindings: _,
-                target_bindings: _,
             } => f
                 .debug_struct("Single")
                 .field("source", source)
                 .field("target", target)
+                // Ignore the nested bindings to avoid an infinite loop while printing.
+                .field(
+                    "source_bindings",
+                    &source_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
+                )
+                .field(
+                    "target_bindings",
+                    &target_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
+                )
                 .field("type_ns_only", type_ns_only)
                 .field("nested", nested)
                 .field("id", id)
-                .finish_non_exhaustive(),
+                .finish(),
             Glob { ref is_prelude, ref max_vis, ref id } => f
                 .debug_struct("Glob")
                 .field("is_prelude", is_prelude)
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index eff10e5af9f..1afd8851ce0 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1478,8 +1478,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                                     } else {
                                         LifetimeUseSet::Many
                                     }),
-                                    LifetimeRibKind::Generics { .. } => None,
-                                    LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
+                                    LifetimeRibKind::Generics { .. }
+                                    | LifetimeRibKind::ConstGeneric => None,
+                                    LifetimeRibKind::AnonConst => {
                                         span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
                                     }
                                 })
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs
index ab7c08958fa..0585ed76fe8 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs
@@ -2,7 +2,7 @@ use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "riscv64gc-unknown-fuchsia".into(),
+        llvm_target: "riscv64-unknown-fuchsia".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 277926688e2..a9c4e126816 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -144,18 +144,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
     ) -> OnUnimplementedNote {
-        if self.tcx.opt_rpitit_info(obligation.cause.body_id.to_def_id()).is_some() {
-            return OnUnimplementedNote::default();
-        }
-
         let (def_id, substs) = self
             .impl_similar_to(trait_ref, obligation)
             .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
         let trait_ref = trait_ref.skip_binder();
 
-        let body_hir = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
-        let mut flags =
-            vec![(sym::ItemContext, self.describe_enclosure(body_hir).map(|s| s.to_owned()))];
+        let mut flags = vec![];
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
+        // but I guess we could synthesize one here. We don't see any errors that rely on
+        // that yet, though.
+        let enclosure =
+            if let Some(body_hir) = self.tcx.opt_local_def_id_to_hir_id(obligation.cause.body_id) {
+                self.describe_enclosure(body_hir).map(|s| s.to_owned())
+            } else {
+                None
+            };
+        flags.push((sym::ItemContext, enclosure));
 
         match obligation.cause.code() {
             ObligationCauseCode::BuiltinDerivedObligation(..)
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 5541c085075..186bfc701bc 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2944,9 +2944,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::SizedYieldType => {
                 err.note("the yield type of a generator must have a statically known size");
             }
-            ObligationCauseCode::SizedBoxType => {
-                err.note("the type of a box expression must have a statically known size");
-            }
             ObligationCauseCode::AssignmentLhsSized => {
                 err.note("the left-hand-side of an assignment must have a statically known size");
             }
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1aaadae12dd..23754480fcf 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -211,6 +211,29 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
     type Error = FulfillmentErrorCode<'tcx>;
     type OUT = Outcome<Self::Obligation, Self::Error>;
 
+    /// Compared to `needs_process_obligation` this and its callees
+    /// contain some optimizations that come at the price of false negatives.
+    ///
+    /// They
+    /// - reduce branching by covering only the most common case
+    /// - take a read-only view of the unification tables which allows skipping undo_log
+    ///   construction.
+    /// - bail out on value-cache misses in ena to avoid pointer chasing
+    /// - hoist RefCell locking out of the loop
+    #[inline]
+    fn skippable_obligations<'b>(
+        &'b self,
+        it: impl Iterator<Item = &'b Self::Obligation>,
+    ) -> usize {
+        let is_unchanged = self.selcx.infcx.is_ty_infer_var_definitely_unchanged();
+
+        it.take_while(|o| match o.stalled_on.as_slice() {
+            [o] => is_unchanged(*o),
+            _ => false,
+        })
+        .count()
+    }
+
     /// Identifies whether a predicate obligation needs processing.
     ///
     /// This is always inlined because it has a single callsite and it is
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0f0cccea130..b8d9cff9c48 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1298,7 +1298,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
 
         let trait_def_id = tcx.parent(trait_fn_def_id);
         let trait_substs =
@@ -2200,7 +2200,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let tcx = selcx.tcx();
     let mut obligations = data.nested;
 
-    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
+    let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
     let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
         Ok(assoc_ty) => assoc_ty,
         Err(guar) => return Progress::error(tcx, guar),
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index a2816124538..68b1086e8e3 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -244,7 +244,7 @@ fn associated_item_for_impl_trait_in_trait(
     tcx: TyCtxt<'_>,
     opaque_ty_def_id: LocalDefId,
 ) -> LocalDefId {
-    let fn_def_id = tcx.impl_trait_in_trait_parent(opaque_ty_def_id.to_def_id());
+    let fn_def_id = tcx.impl_trait_in_trait_parent_fn(opaque_ty_def_id.to_def_id());
     let trait_def_id = tcx.parent(fn_def_id);
     assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
 
@@ -289,8 +289,39 @@ fn associated_item_for_impl_trait_in_trait(
         InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
     )));
 
-    // Copy generics_of of the opaque.
-    trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
+    trait_assoc_ty.is_type_alias_impl_trait(false);
+
+    // Copy generics_of of the opaque type item but the trait is the parent.
+    trait_assoc_ty.generics_of({
+        let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
+        let opaque_ty_parent_count = opaque_ty_generics.parent_count;
+        let mut params = opaque_ty_generics.params.clone();
+
+        let parent_generics = tcx.generics_of(trait_def_id);
+        let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+        let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
+
+        for param in &mut params {
+            param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
+                - opaque_ty_parent_count as u32;
+        }
+
+        trait_fn_params.extend(params);
+        params = trait_fn_params;
+
+        let param_def_id_to_index =
+            params.iter().map(|param| (param.def_id, param.index)).collect();
+
+        ty::Generics {
+            parent: Some(trait_def_id),
+            parent_count,
+            params,
+            param_def_id_to_index,
+            has_self: false,
+            has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
+        }
+    });
 
     // There are no predicates for the synthesized associated type.
     trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index d41bf603983..9fed1e57c92 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -117,16 +117,22 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
 
 /// See `ParamEnv` struct definition for details.
 fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
-    // When computing the param_env of an RPITIT, copy param_env of the containing function. The
-    // synthesized associated type doesn't have extra predicates to assume.
-    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
-        return tcx.param_env(fn_def_id);
-    }
-
     // Compute the bounds on Self and the type parameters.
     let ty::InstantiatedPredicates { mut predicates, .. } =
         tcx.predicates_of(def_id).instantiate_identity(tcx);
 
+    // When computing the param_env of an RPITIT, use predicates of the containing function,
+    // *except* for the additional assumption that the RPITIT normalizes to the trait method's
+    // default opaque type. This is needed to properly check the item bounds of the assoc
+    // type hold (`check_type_bounds`), since that method already installs a similar projection
+    // bound, so they will conflict.
+    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
+    // at least be making sure that the generics in RPITITs and their parent fn don't
+    // get out of alignment, or else we do actually need to substitute these predicates.
+    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
+        predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
+    }
+
     // Finally, we have to normalize the bounds in the environment, in
     // case they contain any associated type projections. This process
     // can yield errors if the put in illegal associated types, like
@@ -160,7 +166,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     }
 
     let local_did = def_id.as_local();
-    let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
+    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for
+    // RPITITs in const trait fn.
+    let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id));
 
     // FIXME(consts): This is not exactly in line with the constness query.
     let constness = match hir_id {
@@ -268,8 +276,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
         if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
-            && self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
-            && self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
+            && self.tcx.is_impl_trait_in_trait(alias_ty.def_id)
+            && self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id
             && self.seen.insert(alias_ty.def_id)
         {
             // We have entered some binders as we've walked into the
@@ -282,11 +290,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
                     re
                 }
             });
+
+            // If we're lowering to associated item, install the opaque type which is just
+            // the `type_of` of the trait's associated item. If we're using the old lowering
+            // strategy, then just reinterpret the associated type like an opaque :^)
+            let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+                self
+                    .tcx
+                    .type_of(alias_ty.def_id)
+                    .subst(self.tcx, alias_ty.substs)
+            } else {
+                self.tcx.mk_alias(ty::Opaque, alias_ty)
+            };
+
             self.predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
                         projection_ty: alias_ty,
-                        term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
+                        term: default_ty.into(),
                     },
                     self.bound_vars,
                 )
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index e9cc3875f68..5469261ef56 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -87,7 +87,7 @@
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
-#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
+#![warn(multiple_supertrait_upcastable)]
 //
 // Library features:
 #![feature(alloc_layout_extra)]
@@ -195,7 +195,7 @@
 #![feature(c_unwind)]
 #![feature(with_negative_coherence)]
 #![cfg_attr(test, feature(panic_update_hook))]
-#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
+#![feature(multiple_supertrait_upcastable)]
 //
 // Rustdoc features:
 #![feature(doc_cfg)]
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 571bc4bcfd1..11cb0827578 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -28,7 +28,7 @@ use crate::fmt::{Debug, Display};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "Error")]
 #[rustc_has_incoherent_inherent_impls]
-#[cfg_attr(not(bootstrap), allow(multiple_supertrait_upcastable))]
+#[allow(multiple_supertrait_upcastable)]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
     ///
@@ -489,7 +489,7 @@ impl Error for crate::char::CharTryFromError {
 #[stable(feature = "duration_checked_float", since = "1.66.0")]
 impl Error for crate::time::TryFromFloatSecsError {}
 
-#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
 impl Error for crate::ffi::FromBytesUntilNulError {}
 
 #[unstable(feature = "get_many_mut", issue = "104642")]
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 87f077325f8..fe8abdf7fad 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -153,10 +153,10 @@ impl Error for FromBytesWithNulError {
 /// This error is created by the [`CStr::from_bytes_until_nul`] method.
 ///
 #[derive(Clone, PartialEq, Eq, Debug)]
-#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
 pub struct FromBytesUntilNulError(());
 
-#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
 impl fmt::Display for FromBytesUntilNulError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "data provided does not contain a nul")
@@ -324,8 +324,8 @@ impl CStr {
     /// ```
     ///
     #[rustc_allow_const_fn_unstable(const_slice_index)]
-    #[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+    #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
     pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> {
         let nul_pos = memchr::memchr(0, bytes);
         match nul_pos {
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 6d764237dc8..fcda097f01f 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -267,7 +267,7 @@ extern "C" {
 /// family of functions. It contains a function to format the given value. At
 /// compile time it is ensured that the function and the value have the correct
 /// types, and then this struct is used to canonicalize arguments to one type.
-#[cfg_attr(not(bootstrap), lang = "format_argument")]
+#[lang = "format_argument"]
 #[derive(Copy, Clone)]
 #[allow(missing_debug_implementations)]
 #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -280,7 +280,7 @@ pub struct ArgumentV1<'a> {
 /// This struct represents the unsafety of constructing an `Arguments`.
 /// It exists, rather than an unsafe function, in order to simplify the expansion
 /// of `format_args!(..)` and reduce the scope of the `unsafe` block.
-#[cfg_attr(not(bootstrap), lang = "format_unsafe_arg")]
+#[lang = "format_unsafe_arg"]
 #[allow(missing_debug_implementations)]
 #[doc(hidden)]
 #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -497,7 +497,7 @@ impl<'a> Arguments<'a> {
 /// ```
 ///
 /// [`format()`]: ../../std/fmt/fn.format.html
-#[cfg_attr(not(bootstrap), lang = "format_arguments")]
+#[lang = "format_arguments"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone)]
 pub struct Arguments<'a> {
diff --git a/library/core/src/fmt/rt/v1.rs b/library/core/src/fmt/rt/v1.rs
index 11a50951a75..6d70796f707 100644
--- a/library/core/src/fmt/rt/v1.rs
+++ b/library/core/src/fmt/rt/v1.rs
@@ -5,7 +5,7 @@
 //! these can be statically allocated and are slightly optimized for the runtime
 #![allow(missing_debug_implementations)]
 
-#[cfg_attr(not(bootstrap), lang = "format_placeholder")]
+#[lang = "format_placeholder"]
 #[derive(Copy, Clone)]
 // FIXME: Rename this to Placeholder
 pub struct Argument {
@@ -37,7 +37,7 @@ impl Argument {
 }
 
 /// Possible alignments that can be requested as part of a formatting directive.
-#[cfg_attr(not(bootstrap), lang = "format_alignment")]
+#[lang = "format_alignment"]
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum Alignment {
     /// Indication that contents should be left-aligned.
@@ -51,7 +51,7 @@ pub enum Alignment {
 }
 
 /// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
-#[cfg_attr(not(bootstrap), lang = "format_count")]
+#[lang = "format_count"]
 #[derive(Copy, Clone)]
 pub enum Count {
     /// Specified with a literal number, stores the value
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 3bdde0993b9..4e7bae7bcb0 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -834,7 +834,7 @@ mod impls {
 
                 #[inline]
                 fn hash_slice<H: ~const Hasher>(data: &[$ty], state: &mut H) {
-                    let newlen = data.len() * mem::size_of::<$ty>();
+                    let newlen = mem::size_of_val(data);
                     let ptr = data.as_ptr() as *const u8;
                     // SAFETY: `ptr` is valid and aligned, as this macro is only used
                     // for numeric primitives which have no padding. The new slice only
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index ae00232c12c..de638552fa3 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -278,7 +278,7 @@
 //!
 //! ```
 //! # #![allow(unused_must_use)]
-//! # #![cfg_attr(not(bootstrap), allow(map_unit_fn))]
+//! # #![allow(map_unit_fn)]
 //! let v = vec![1, 2, 3, 4, 5];
 //! v.iter().map(|x| println!("{x}"));
 //! ```
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 78e27d73065..f19636fba5d 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,4 +1,5 @@
 use crate::convert::TryFrom;
+use crate::marker::Destruct;
 use crate::mem;
 use crate::ops::{self, Try};
 
@@ -20,7 +21,8 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi
 /// The *successor* operation moves towards values that compare greater.
 /// The *predecessor* operation moves towards values that compare lesser.
 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-pub trait Step: Clone + PartialOrd + Sized {
+#[const_trait]
+pub trait Step: ~const Clone + ~const PartialOrd + Sized {
     /// Returns the number of *successor* steps required to get from `start` to `end`.
     ///
     /// Returns `None` if the number of steps would overflow `usize`
@@ -234,7 +236,8 @@ macro_rules! step_integer_impls {
         $(
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $u_narrower {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $u_narrower {
                 step_identical_methods!();
 
                 #[inline]
@@ -266,7 +269,8 @@ macro_rules! step_integer_impls {
 
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $i_narrower {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $i_narrower {
                 step_identical_methods!();
 
                 #[inline]
@@ -330,7 +334,8 @@ macro_rules! step_integer_impls {
         $(
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $u_wider {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $u_wider {
                 step_identical_methods!();
 
                 #[inline]
@@ -355,7 +360,8 @@ macro_rules! step_integer_impls {
 
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $i_wider {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $i_wider {
                 step_identical_methods!();
 
                 #[inline]
@@ -405,7 +411,8 @@ step_integer_impls! {
 }
 
 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-impl Step for char {
+#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+impl const Step for char {
     #[inline]
     fn steps_between(&start: &char, &end: &char) -> Option<usize> {
         let start = start as u32;
@@ -423,6 +430,7 @@ impl Step for char {
     }
 
     #[inline]
+    #[rustc_allow_const_fn_unstable(const_try)]
     fn forward_checked(start: char, count: usize) -> Option<char> {
         let start = start as u32;
         let mut res = Step::forward_checked(start, count)?;
@@ -439,6 +447,7 @@ impl Step for char {
     }
 
     #[inline]
+    #[rustc_allow_const_fn_unstable(const_try)]
     fn backward_checked(start: char, count: usize) -> Option<char> {
         let start = start as u32;
         let mut res = Step::backward_checked(start, count)?;
@@ -514,6 +523,7 @@ macro_rules! range_incl_exact_iter_impl {
 }
 
 /// Specialization implementations for `Range`.
+#[const_trait]
 trait RangeIteratorImpl {
     type Item;
 
@@ -528,7 +538,7 @@ trait RangeIteratorImpl {
     fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>;
 }
 
-impl<A: Step> RangeIteratorImpl for ops::Range<A> {
+impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
     type Item = A;
 
     #[inline]
@@ -614,7 +624,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
     }
 }
 
-impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
+impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
     #[inline]
     fn spec_next(&mut self) -> Option<T> {
         if self.start < self.end {
@@ -702,7 +712,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Step> Iterator for ops::Range<A> {
+#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+impl<A: ~const Step + ~const Destruct> const Iterator for ops::Range<A> {
     type Item = A;
 
     #[inline]
@@ -812,7 +823,8 @@ range_incl_exact_iter_impl! {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Step> DoubleEndedIterator for ops::Range<A> {
+#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
         self.spec_next_back()
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index ed23873cdde..7a10dea500a 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -1,3 +1,4 @@
+use crate::marker::Destruct;
 use crate::ops::{ControlFlow, Try};
 
 /// An iterator able to yield elements from both ends.
@@ -37,6 +38,7 @@ use crate::ops::{ControlFlow, Try};
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")]
+#[const_trait]
 pub trait DoubleEndedIterator: Iterator {
     /// Removes and returns an element from the end of the iterator.
     ///
@@ -131,7 +133,10 @@ pub trait DoubleEndedIterator: Iterator {
     /// [`Err(k)`]: Err
     #[inline]
     #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
-    fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+    fn advance_back_by(&mut self, n: usize) -> Result<(), usize>
+    where
+        Self::Item: ~const Destruct,
+    {
         for i in 0..n {
             self.next_back().ok_or(i)?;
         }
@@ -181,6 +186,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_nth_back", since = "1.37.0")]
+    #[rustc_do_not_const_check]
     fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
         self.advance_back_by(n).ok()?;
         self.next_back()
@@ -218,6 +224,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
+    #[rustc_do_not_const_check]
     fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
     where
         Self: Sized,
@@ -289,6 +296,7 @@ pub trait DoubleEndedIterator: Iterator {
     #[doc(alias = "foldr")]
     #[inline]
     #[stable(feature = "iter_rfold", since = "1.27.0")]
+    #[rustc_do_not_const_check]
     fn rfold<B, F>(mut self, init: B, mut f: F) -> B
     where
         Self: Sized,
@@ -344,6 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_rfind", since = "1.27.0")]
+    #[rustc_do_not_const_check]
     fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         Self: Sized,
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index e791158e259..6fc86550b63 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1,5 +1,6 @@
 use crate::array;
 use crate::cmp::{self, Ordering};
+use crate::marker::Destruct;
 use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
 
 use super::super::try_process;
@@ -69,7 +70,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
 #[doc(notable_trait)]
 #[rustc_diagnostic_item = "Iterator"]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
-#[cfg_attr(not(bootstrap), const_trait)]
+#[const_trait]
 pub trait Iterator {
     /// The type of the elements being iterated over.
     #[rustc_diagnostic_item = "IteratorItem"]
@@ -336,8 +337,10 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
-    #[rustc_do_not_const_check]
-    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+    fn advance_by(&mut self, n: usize) -> Result<(), usize>
+    where
+        Self::Item: ~const Destruct,
+    {
         for i in 0..n {
             self.next().ok_or(i)?;
         }
@@ -385,8 +388,10 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
-    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+    fn nth(&mut self, n: usize) -> Option<Self::Item>
+    where
+        Self::Item: ~const Destruct,
+    {
         self.advance_by(n).ok()?;
         self.next()
     }
diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs
index af02848233d..c8f60defff7 100644
--- a/library/core/src/iter/traits/marker.rs
+++ b/library/core/src/iter/traits/marker.rs
@@ -86,4 +86,5 @@ pub unsafe trait InPlaceIterable: Iterator {}
 /// for details. Consumers are free to rely on the invariants in unsafe code.
 #[unstable(feature = "trusted_step", issue = "85731")]
 #[rustc_specialization_trait]
-pub unsafe trait TrustedStep: Step {}
+#[const_trait]
+pub unsafe trait TrustedStep: ~const Step {}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 24bad799fc8..1076d357070 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -95,7 +95,7 @@
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
-#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
+#![warn(multiple_supertrait_upcastable)]
 //
 // Library features:
 #![feature(const_align_offset)]
@@ -123,9 +123,11 @@
 #![feature(const_index_range_slice_index)]
 #![feature(const_inherent_unchecked_arith)]
 #![feature(const_int_unchecked_arith)]
+#![feature(const_intoiterator_identity)]
 #![feature(const_intrinsic_forget)]
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
+#![feature(const_iter)]
 #![feature(const_likely)]
 #![feature(const_maybe_uninit_uninit_array)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
@@ -241,7 +243,7 @@
 #![feature(unsized_fn_params)]
 #![feature(asm_const)]
 #![feature(const_transmute_copy)]
-#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
+#![feature(multiple_supertrait_upcastable)]
 //
 // Target features:
 #![feature(arm_target_feature)]
@@ -254,7 +256,6 @@
 #![feature(sse4a_target_feature)]
 #![feature(tbm_target_feature)]
 #![feature(wasm_target_feature)]
-#![cfg_attr(bootstrap, feature(cmpxchg16b_target_feature))]
 
 // allow using `core::` in intra-doc links
 #[allow(unused_extern_crates)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 3b026bc0e0f..529f62f4d6c 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -340,9 +340,9 @@ pub macro debug_assert_matches($($arg:tt)*) {
 #[stable(feature = "matches_macro", since = "1.42.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")]
 macro_rules! matches {
-    ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
+    ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => {
         match $expression {
-            $( $pattern )|+ $( if $guard )? => true,
+            $pattern $(if $guard)? => true,
             _ => false
         }
     };
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 427146941ad..9a0fd1f5f51 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -97,7 +97,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
 #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
 #[rustc_specialization_trait]
 #[rustc_deny_explicit_impl]
-#[cfg_attr(not(bootstrap), rustc_coinductive)]
+#[rustc_coinductive]
 pub trait Sized {
     // Empty.
 }
@@ -877,8 +877,7 @@ pub trait Tuple {}
 /// All types that have the same size and alignment as a `usize` or
 /// `*const ()` automatically implement this trait.
 #[unstable(feature = "pointer_like_trait", issue = "none")]
-#[cfg_attr(bootstrap, lang = "pointer_sized")]
-#[cfg_attr(not(bootstrap), lang = "pointer_like")]
+#[lang = "pointer_like"]
 #[rustc_on_unimplemented(
     message = "`{Self}` needs to have the same alignment and size as a pointer",
     label = "`{Self}` needs to be a pointer-like type"
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index 0d25ab1d5e1..2d48e271580 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -121,7 +121,7 @@ impl SocketAddr {
     /// ```
     #[stable(feature = "ip_addr", since = "1.7.0")]
     #[must_use]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
         match ip {
             IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
@@ -141,7 +141,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "ip_addr", since = "1.7.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn ip(&self) -> IpAddr {
         match *self {
             SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
@@ -182,7 +182,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn port(&self) -> u16 {
         match *self {
             SocketAddr::V4(ref a) => a.port(),
@@ -226,7 +226,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn is_ipv4(&self) -> bool {
         matches!(*self, SocketAddr::V4(_))
     }
@@ -248,7 +248,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn is_ipv6(&self) -> bool {
         matches!(*self, SocketAddr::V6(_))
     }
@@ -268,7 +268,7 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
         SocketAddrV4 { ip, port }
     }
@@ -285,7 +285,7 @@ impl SocketAddrV4 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn ip(&self) -> &Ipv4Addr {
         &self.ip
     }
@@ -318,7 +318,7 @@ impl SocketAddrV4 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn port(&self) -> u16 {
         self.port
     }
@@ -359,7 +359,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
         SocketAddrV6 { ip, port, flowinfo, scope_id }
     }
@@ -376,7 +376,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn ip(&self) -> &Ipv6Addr {
         &self.ip
     }
@@ -409,7 +409,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn port(&self) -> u16 {
         self.port
     }
@@ -452,7 +452,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn flowinfo(&self) -> u32 {
         self.flowinfo
     }
@@ -492,7 +492,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
     pub const fn scope_id(&self) -> u32 {
         self.scope_id
     }
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 86aa1e4fd20..c254803fbf6 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -392,14 +392,7 @@ impl<T> NeverShortCircuit<T> {
     pub fn wrap_mut_2<A, B>(
         mut f: impl ~const FnMut(A, B) -> T,
     ) -> impl ~const FnMut(A, B) -> Self {
-        cfg_if! {
-            if #[cfg(bootstrap)] {
-                #[allow(unused_parens)]
-                (const move |a, b| NeverShortCircuit(f(a, b)))
-            } else {
-                const move |a, b| NeverShortCircuit(f(a, b))
-            }
-        }
+        const move |a, b| NeverShortCircuit(f(a, b))
     }
 }
 
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index febe57dc90b..c4b89a63019 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1003,22 +1003,25 @@ impl<P, U> CoerceUnsized<Pin<U>> for Pin<P> where P: CoerceUnsized<U> {}
 #[stable(feature = "pin", since = "1.33.0")]
 impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 
-/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning[^1] a `value: T` _locally_[^2].
+/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
 ///
-/// Unlike [`Box::pin`], this does not involve a heap allocation.
+/// Unlike [`Box::pin`], this does not create a new heap allocation. As explained
+/// below, the element might still end up on the heap however.
 ///
-/// [^1]: If the (type `T` of the) given value does not implement [`Unpin`], then this
-/// effectively pins the `value` in memory, where it will be unable to be moved.
-/// Otherwise, <code>[Pin]<[&mut] T></code> behaves like <code>[&mut] T</code>, and operations such
-/// as [`mem::replace()`][crate::mem::replace] will allow extracting that value, and therefore,
-/// moving it.
-/// See [the `Unpin` section of the `pin` module][self#unpin] for more info.
+/// The local pinning performed by this macro is usually dubbed "stack"-pinning.
+/// Outside of `async` contexts locals do indeed get stored on the stack. In
+/// `async` functions or blocks however, any locals crossing an `.await` point
+/// are part of the state captured by the `Future`, and will use the storage of
+/// those. That storage can either be on the heap or on the stack. Therefore,
+/// local pinning is a more accurate term.
 ///
-/// [^2]: This is usually dubbed "stack"-pinning. And whilst local values are almost always located
-/// in the stack (_e.g._, when within the body of a non-`async` function), the truth is that inside
-/// the body of an `async fn` or block —more generally, the body of a generator— any locals crossing
-/// an `.await` point —a `yield` point— end up being part of the state captured by the `Future` —by
-/// the `Generator`—, and thus will be stored wherever that one is.
+/// If the type of the given value does not implement [`Unpin`], then this macro
+/// pins the value in memory in a way that prevents moves. On the other hand,
+/// if the type does implement [`Unpin`], <code>[Pin]<[&mut] T></code> behaves
+/// like <code>[&mut] T</code>, and operations such as
+/// [`mem::replace()`][crate::mem::replace] or [`mem::take()`](crate::mem::take)
+/// will allow moves of the value.
+/// See [the `Unpin` section of the `pin` module][self#unpin] for details.
 ///
 /// ## Examples
 ///
@@ -1158,9 +1161,9 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 ///
 /// If you really need to return a pinned value, consider using [`Box::pin`] instead.
 ///
-/// On the other hand, pinning to the stack[<sup>2</sup>](#fn2) using [`pin!`] is likely to be
-/// cheaper than pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not
-/// even needing an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`]
+/// On the other hand, local pinning using [`pin!`] is likely to be cheaper than
+/// pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not
+/// requiring an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`]
 /// constructor.
 ///
 /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 123561873a6..2f6b1c74da0 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1951,8 +1951,7 @@ macro_rules! if_not_8_bit {
     ($_:ident, $($tt:tt)*) => { $($tt)* };
 }
 
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic_load_store))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic_load_store = "8"))]
+#[cfg(target_has_atomic_load_store)]
 macro_rules! atomic_int {
     ($cfg_cas:meta,
      $cfg_align:meta,
@@ -3125,8 +3124,7 @@ atomic_int_ptr_sized! {
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 fn strongest_failure_ordering(order: Ordering) -> Ordering {
     match order {
         Release => Relaxed,
@@ -3168,8 +3166,7 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_swap`.
@@ -3186,8 +3183,7 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// Returns the previous value (like __sync_fetch_and_add).
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_add`.
@@ -3204,8 +3200,7 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// Returns the previous value (like __sync_fetch_and_sub).
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_sub`.
@@ -3221,8 +3216,7 @@ unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_compare_exchange<T: Copy>(
     dst: *mut T,
@@ -3257,8 +3251,7 @@ unsafe fn atomic_compare_exchange<T: Copy>(
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_compare_exchange_weak<T: Copy>(
     dst: *mut T,
@@ -3293,8 +3286,7 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>(
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_and`
@@ -3310,8 +3302,7 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_nand`
@@ -3327,8 +3318,7 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_or`
@@ -3344,8 +3334,7 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_xor`
@@ -3362,8 +3351,7 @@ unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the max value (signed comparison)
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_max`
@@ -3380,8 +3368,7 @@ unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the min value (signed comparison)
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_min`
@@ -3398,8 +3385,7 @@ unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the max value (unsigned comparison)
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_umax`
@@ -3416,8 +3402,7 @@ unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// returns the min value (unsigned comparison)
 #[inline]
-#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
-#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
+#[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_umin`
diff --git a/library/core/tests/iter/consts.rs b/library/core/tests/iter/consts.rs
new file mode 100644
index 00000000000..d56687e48c9
--- /dev/null
+++ b/library/core/tests/iter/consts.rs
@@ -0,0 +1,36 @@
+#[test]
+fn const_manual_iter() {
+    struct S(bool);
+
+    impl const Iterator for S {
+        type Item = ();
+
+        fn next(&mut self) -> Option<Self::Item> {
+            if self.0 == false {
+                self.0 = true;
+                Some(())
+            } else {
+                None
+            }
+        }
+    }
+    const {
+        let mut val = S(false);
+        assert!(val.next().is_some());
+        assert!(val.next().is_none());
+        assert!(val.next().is_none());
+    }
+}
+
+#[test]
+fn const_range() {
+    const {
+        let mut arr = [0; 3];
+        for i in 0..arr.len() {
+            arr[i] = i;
+        }
+        assert!(arr[0] == 0);
+        assert!(arr[1] == 1);
+        assert!(arr[2] == 2);
+    }
+}
diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs
index 770b6f7601f..cbb18e79e2d 100644
--- a/library/core/tests/iter/mod.rs
+++ b/library/core/tests/iter/mod.rs
@@ -20,6 +20,8 @@ mod range;
 mod sources;
 mod traits;
 
+mod consts;
+
 use core::cell::Cell;
 use core::convert::TryFrom;
 use core::iter::*;
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index ccb7be68eb1..637cc6e9f62 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -12,8 +12,11 @@
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_convert)]
+#![feature(const_for)]
 #![feature(const_hash)]
 #![feature(const_heap)]
+#![feature(const_intoiterator_identity)]
+#![feature(const_iter)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init_read)]
 #![feature(const_nonnull_new)]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index b2b6d86134b..4b31c552eed 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -823,8 +823,22 @@ pub trait Read {
 
     /// Read the exact number of bytes required to fill `cursor`.
     ///
-    /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to
-    /// allow use with uninitialized buffers.
+    /// This is similar to the [`read_exact`](Read::read_exact) method, except
+    /// that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use
+    /// with uninitialized buffers.
+    ///
+    /// # Errors
+    ///
+    /// If this function encounters an error of the kind [`ErrorKind::Interrupted`]
+    /// then the error is ignored and the operation will continue.
+    ///
+    /// If this function encounters an "end of file" before completely filling
+    /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
+    ///
+    /// If any other read error is encountered then this function immediately
+    /// returns.
+    ///
+    /// If this function returns an error, all bytes read will be appended to `cursor`.
     #[unstable(feature = "read_buf", issue = "78485")]
     fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> {
         while cursor.capacity() > 0 {
diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs
index 7cecd1bbfaa..4e88ab8ff5c 100644
--- a/library/std/src/os/android/net.rs
+++ b/library/std/src/os/android/net.rs
@@ -1,8 +1,8 @@
 //! Android-specific networking functionality.
 
-#![unstable(feature = "tcp_quickack", issue = "96256")]
+#![stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 
-#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 pub use crate::os::net::linux_ext::addr::SocketAddrExt;
 
 #[unstable(feature = "tcp_quickack", issue = "96256")]
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 258919d53a4..99a4e0b5106 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -399,7 +399,7 @@ impl<T: AsFd> AsFd for crate::sync::Arc<T> {
     }
 }
 
-#[stable(feature = "asfd_rc", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "asfd_rc", since = "1.69.0")]
 impl<T: AsFd> AsFd for crate::rc::Rc<T> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index 0a4cefd2095..592e072ad90 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -254,7 +254,7 @@ impl<T: AsRawFd> AsRawFd for crate::sync::Arc<T> {
     }
 }
 
-#[stable(feature = "asfd_rc", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "asfd_rc", since = "1.69.0")]
 impl<T: AsRawFd> AsRawFd for crate::rc::Rc<T> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs
index 94081c8dd31..fcb3bb83485 100644
--- a/library/std/src/os/linux/net.rs
+++ b/library/std/src/os/linux/net.rs
@@ -1,8 +1,8 @@
 //! Linux-specific networking functionality.
 
-#![unstable(feature = "tcp_quickack", issue = "96256")]
+#![stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 
-#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 pub use crate::os::net::linux_ext::addr::SocketAddrExt;
 
 #[unstable(feature = "tcp_quickack", issue = "96256")]
diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs
index 85065984fbb..ea8102c9cc0 100644
--- a/library/std/src/os/net/linux_ext/addr.rs
+++ b/library/std/src/os/net/linux_ext/addr.rs
@@ -4,7 +4,7 @@ use crate::os::unix::net::SocketAddr;
 use crate::sealed::Sealed;
 
 /// Platform-specific extensions to [`SocketAddr`].
-#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 pub trait SocketAddrExt: Sealed {
     /// Creates a Unix socket address in the abstract namespace.
     ///
@@ -22,7 +22,6 @@ pub trait SocketAddrExt: Sealed {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixListener, SocketAddr};
     /// use std::os::linux::net::SocketAddrExt;
     ///
@@ -38,6 +37,7 @@ pub trait SocketAddrExt: Sealed {
     ///     Ok(())
     /// }
     /// ```
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     fn from_abstract_name<N>(name: N) -> crate::io::Result<SocketAddr>
     where
         N: AsRef<[u8]>;
@@ -47,7 +47,6 @@ pub trait SocketAddrExt: Sealed {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixListener, SocketAddr};
     /// use std::os::linux::net::SocketAddrExt;
     ///
@@ -60,5 +59,6 @@ pub trait SocketAddrExt: Sealed {
     ///     Ok(())
     /// }
     /// ```
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     fn as_abstract_name(&self) -> Option<&[u8]>;
 }
diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs
index 318ebacfd7a..e7423dce613 100644
--- a/library/std/src/os/net/linux_ext/mod.rs
+++ b/library/std/src/os/net/linux_ext/mod.rs
@@ -2,7 +2,7 @@
 
 #![doc(cfg(any(target_os = "linux", target_os = "android")))]
 
-#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 pub(crate) mod addr;
 
 #[unstable(feature = "tcp_quickack", issue = "96256")]
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs
index ece2b33bddf..52a0da5bf1a 100644
--- a/library/std/src/os/unix/net/addr.rs
+++ b/library/std/src/os/unix/net/addr.rs
@@ -245,12 +245,12 @@ impl SocketAddr {
     }
 }
 
-#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 impl Sealed for SocketAddr {}
 
 #[doc(cfg(any(target_os = "android", target_os = "linux")))]
 #[cfg(any(doc, target_os = "android", target_os = "linux"))]
-#[unstable(feature = "unix_socket_abstract", issue = "85410")]
+#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
 impl linux_ext::addr::SocketAddrExt for SocketAddr {
     fn as_abstract_name(&self) -> Option<&[u8]> {
         if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None }
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index 272b4f5dcd5..e64569758a0 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -102,7 +102,6 @@ impl UnixDatagram {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixDatagram};
     ///
     /// fn main() -> std::io::Result<()> {
@@ -119,7 +118,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "unix_socket_abstract", issue = "85410")]
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixDatagram> {
         unsafe {
             let socket = UnixDatagram::unbound()?;
@@ -217,7 +216,6 @@ impl UnixDatagram {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixDatagram};
     ///
     /// fn main() -> std::io::Result<()> {
@@ -235,7 +233,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "unix_socket_abstract", issue = "85410")]
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> {
         unsafe {
             cvt(libc::connect(
@@ -523,7 +521,6 @@ impl UnixDatagram {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixDatagram};
     ///
     /// fn main() -> std::io::Result<()> {
@@ -535,7 +532,7 @@ impl UnixDatagram {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "unix_socket_abstract", issue = "85410")]
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result<usize> {
         unsafe {
             let count = cvt(libc::sendto(
diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs
index 02090afc82f..83f0debe676 100644
--- a/library/std/src/os/unix/net/listener.rs
+++ b/library/std/src/os/unix/net/listener.rs
@@ -90,7 +90,6 @@ impl UnixListener {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixListener};
     ///
     /// fn main() -> std::io::Result<()> {
@@ -107,7 +106,7 @@ impl UnixListener {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "unix_socket_abstract", issue = "85410")]
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> {
         unsafe {
             let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index dff8f6e8567..65cb4ae07a5 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -106,7 +106,6 @@ impl UnixStream {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(unix_socket_abstract)]
     /// use std::os::unix::net::{UnixListener, UnixStream};
     ///
     /// fn main() -> std::io::Result<()> {
@@ -123,7 +122,7 @@ impl UnixStream {
     ///     Ok(())
     /// }
     /// ````
-    #[unstable(feature = "unix_socket_abstract", issue = "85410")]
+    #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")]
     pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result<UnixStream> {
         unsafe {
             let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 9fa8f5702a8..345d72ef867 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -308,8 +308,7 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> {
                 BacktraceStyle::Short
             }
         })
-        .unwrap_or(if cfg!(target_os = "fuchsia") {
-            // Fuchsia components default to full backtrace.
+        .unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT {
             BacktraceStyle::Full
         } else {
             BacktraceStyle::Off
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index c080c176a2a..e767b2866cb 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -76,3 +76,12 @@ cfg_if::cfg_if! {
         pub mod c;
     }
 }
+
+cfg_if::cfg_if! {
+    // Fuchsia components default to full backtrace.
+    if #[cfg(target_os = "fuchsia")] {
+        pub const FULL_BACKTRACE_DEFAULT: bool = true;
+    } else {
+        pub const FULL_BACKTRACE_DEFAULT: bool = false;
+    }
+}
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index d2c597664fa..373157bd9e8 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1236,7 +1236,17 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
 }
 
 pub fn stat(path: &Path) -> io::Result<FileAttr> {
-    metadata(path, ReparsePoint::Follow)
+    match metadata(path, ReparsePoint::Follow) {
+        Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => {
+            if let Ok(attrs) = lstat(path) {
+                if !attrs.file_type().is_symlink() {
+                    return Ok(attrs);
+                }
+            }
+            Err(err)
+        }
+        result => result,
+    }
 }
 
 pub fn lstat(path: &Path) -> io::Result<FileAttr> {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 8b80dfc0f9b..54971af644c 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -339,6 +339,12 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
         ""
     };
 
+    // `libtest` uses this to know whether or not to support
+    // `-Zunstable-options`.
+    if !builder.unstable_features() {
+        cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
+    }
+
     let mut features = String::new();
 
     // Cranelift doesn't support `asm`.
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 58729f396f0..0fee094c222 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -1153,6 +1153,11 @@ impl Config {
             config.rust_profile_generate = flags.rust_profile_generate;
         }
 
+        // rust_info must be set before is_ci_llvm_available() is called.
+        let default = config.channel == "dev";
+        config.ignore_git = ignore_git.unwrap_or(default);
+        config.rust_info = GitInfo::new(config.ignore_git, &config.src);
+
         if let Some(llvm) = toml.llvm {
             match llvm.ccache {
                 Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
@@ -1346,10 +1351,6 @@ impl Config {
         config.rust_debuginfo_level_tools = with_defaults(debuginfo_level_tools);
         config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(0);
 
-        let default = config.channel == "dev";
-        config.ignore_git = ignore_git.unwrap_or(default);
-        config.rust_info = GitInfo::new(config.ignore_git, &config.src);
-
         let download_rustc = config.download_rustc_commit.is_some();
         // See https://github.com/rust-lang/compiler-team/issues/326
         config.stage = match config.cmd {
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index ac3843c3344..42d895a3413 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -210,10 +210,13 @@ install!((self, builder, _config),
         }
     };
     LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
-        let tarball = builder
-            .ensure(dist::LlvmTools { target: self.target })
-            .expect("missing llvm-tools");
-        install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
+        if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
+            install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
+        } else {
+            builder.info(
+                &format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target),
+            );
+        }
     };
     Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::Rustfmt {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index f5d680df113..baddc9da48d 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1118,7 +1118,11 @@ impl Step for Tidy {
         cmd.arg(&builder.src);
         cmd.arg(&builder.initial_cargo);
         cmd.arg(&builder.out);
-        cmd.arg(builder.jobs().to_string());
+        // Tidy is heavily IO constrained. Still respect `-j`, but use a higher limit if `jobs` hasn't been configured.
+        let jobs = builder.config.jobs.unwrap_or_else(|| {
+            8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
+        });
+        cmd.arg(jobs.to_string());
         if builder.is_verbose() {
             cmd.arg("--verbose");
         }
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 5feba4e0605..04fdb15f5ac 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -54,8 +54,8 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/
 RUN ./build-clang.sh
 ENV CC=clang CXX=clang++
 
-# rustc-perf version from 2022-07-22
-ENV PERF_COMMIT 3c253134664fdcba862c539d37f0de18557a9a4c
+# rustc-perf version from 2023-03-15
+ENV PERF_COMMIT 9dfaa35193154b690922347ee1141a06ec87a199
 RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
     unzip perf.zip && \
     mv rustc-perf-$PERF_COMMIT rustc-perf && \
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
index 9abfd4e9731..de0fb95efd0 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
@@ -4,7 +4,7 @@ set -ex
 
 source shared.sh
 
-LLVM=llvmorg-15.0.0
+LLVM=llvmorg-16.0.0-rc4
 
 mkdir llvm-project
 cd llvm-project
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index fe3083dc31e..d4d80e8f77c 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -175,8 +175,8 @@ class WindowsPipeline(Pipeline):
         return super().rustc_stage_2().with_suffix(".exe")
 
     def build_rustc_perf(self):
-        # rustc-perf version from 2022-07-22
-        perf_commit = "3c253134664fdcba862c539d37f0de18557a9a4c"
+        # rustc-perf version from 2023-03-15
+        perf_commit = "9dfaa35193154b690922347ee1141a06ec87a199"
         rustc_perf_zip_path = self.opt_artifacts() / "perf.zip"
 
         def download_rustc_perf():
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 29c3afe0d95..989e091a0d2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -426,7 +426,7 @@ fn clean_projection<'tcx>(
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
+    if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
         let bounds = cx
             .tcx
             .explicit_item_bounds(ty.skip_binder().def_id)
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 27010b771d3..d526a8be081 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1502,9 +1502,9 @@ pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
     tcx: TyCtxt<'tcx>,
     item_did: DefId,
 ) -> impl fmt::Display + 'a + Captures<'tcx> {
-    let to_print = match visibility {
-        None => String::new(),
-        Some(ty::Visibility::Public) => "pub ".to_owned(),
+    let to_print: Cow<'static, str> = match visibility {
+        None => "".into(),
+        Some(ty::Visibility::Public) => "pub ".into(),
         Some(ty::Visibility::Restricted(vis_did)) => {
             // FIXME(camelid): This may not work correctly if `item_did` is a module.
             //                 However, rustdoc currently never displays a module's
@@ -1512,17 +1512,17 @@ pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
             let parent_module = find_nearest_parent_module(tcx, item_did);
 
             if vis_did.is_crate_root() {
-                "pub(crate) ".to_owned()
+                "pub(crate) ".into()
             } else if parent_module == Some(vis_did) {
                 // `pub(in foo)` where `foo` is the parent module
                 // is the same as no visibility modifier
-                String::new()
+                "".into()
             } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent))
                 == Some(vis_did)
             {
-                "pub(super) ".to_owned()
+                "pub(super) ".into()
             } else {
-                format!("pub(in {}) ", tcx.def_path_str(vis_did))
+                format!("pub(in {}) ", tcx.def_path_str(vis_did)).into()
             }
         }
     };
diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md
index 72c516c93eb..0281b1c47f8 100644
--- a/src/librustdoc/html/templates/STYLE.md
+++ b/src/librustdoc/html/templates/STYLE.md
@@ -1,12 +1,12 @@
 # Style for Templates
 
-This directory has templates in the [Tera templating language](teradoc), which is very
-similar to [Jinja2](jinjadoc) and [Django](djangodoc) templates, and also to [Askama](askamadoc).
+This directory has templates in the [Tera templating language][teradoc], which is very
+similar to [Jinja2][jinjadoc] and [Django][djangodoc] templates, and also to [Askama][askamadoc].
 
 [teradoc]: https://tera.netlify.app/docs/#templates
-[jinjadoc]: https://jinja.palletsprojects.com/en/3.0.x/templates/
-[djangodoc]: https://docs.djangoproject.com/en/3.2/topics/templates/
-[askamadoc]: https://docs.rs/askama/0.10.5/askama/
+[jinjadoc]: https://jinja.palletsprojects.com/en/3.1.x/templates/
+[djangodoc]: https://docs.djangoproject.com/en/4.1/topics/templates/
+[askamadoc]: https://docs.rs/askama/latest/askama/
 
 We want our rendered output to have as little unnecessary whitespace as
 possible, so that pages load quickly. To achieve that we use Tera's
@@ -30,8 +30,8 @@ contents don't necessarily need a new line.
 
 Askama templates support quite sophisticated control flow. To keep our templates
 simple and understandable, we use only a subset: `if` and `for`. In particular
-we avoid [assignments in the template logic](assignments) and [Askama
-macros](macros). This also may make things easier if we switch to a different
+we avoid [assignments in the template logic][assignments] and [Askama
+macros][macros]. This also may make things easier if we switch to a different
 Jinja-style template system, like Askama, in the future.
 
 [assignments]: https://djc.github.io/askama/template_syntax.html#assignments
diff --git a/src/stage0.json b/src/stage0.json
index 46f70b1ef4b..9250d9c2804 100644
--- a/src/stage0.json
+++ b/src/stage0.json
@@ -17,409 +17,409 @@
     "tool is executed."
   ],
   "compiler": {
-    "date": "2023-01-25",
+    "date": "2023-03-07",
     "version": "beta"
   },
   "rustfmt": {
-    "date": "2023-01-30",
+    "date": "2023-03-07",
     "version": "nightly"
   },
   "checksums_sha256": {
-    "dist/2023-01-25/cargo-beta-aarch64-apple-darwin.tar.gz": "323f3c4c41892765b24201aae83a54fcaef08e47b9b2912a2680528c6ed4f8f8",
-    "dist/2023-01-25/cargo-beta-aarch64-apple-darwin.tar.xz": "2039157d9100ccadf4d3596f5d7b052e10ff997b59ac7619999969794fc51eae",
-    "dist/2023-01-25/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "ac3c88c99aed8d4547f8b0f857ec3538456f10223411580278eed10f6e2be30b",
-    "dist/2023-01-25/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "27b11ea3c67f202e61b5e7394d36bedc7f1b054ca53d68e53ccd7bacf77b4af3",
-    "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "4d6d1d47d34e8042aa978fe5a6b5b8984d6626d38731081db2d5b413d5b844f4",
-    "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "a50e473aa6b6bffd84a719aec602d4bc19f03ccb0ee5f26340eb466501cb2970",
-    "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "a043def73a5c72d515c3d7dabe09022c353b047e7a4e4e13e9b17da9b30f8828",
-    "dist/2023-01-25/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "a63a8915409df4ae5d76d530b46cb7e83b6e6ca79790fa095d899e33773124a0",
-    "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "9c0c413187f1f1e0f1b6f1b66af0bd1b264d94f73439f6df24f476ee1c6c04fe",
-    "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "cb79e76beb989a3e4ffd1461817ad2dd0602aca3bce1a2e54cccc1bbb518a303",
-    "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "d57c5806a13b498768b53a053c7eb17e8becb19ea5fc9561a2a600dafea32056",
-    "dist/2023-01-25/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "33f35d8c2f5fcd5fa7928f2186a8b2417040e01462152430bae978d8d5a661cd",
-    "dist/2023-01-25/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "80ba79da61f82dc760a9dd7bfdfde29fefcab4ae94917cbf5d908332f93061d3",
-    "dist/2023-01-25/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "a8e48c6345b0e195ea58d6237a247b0d20c8d128af1b12813430806b9a340d5b",
-    "dist/2023-01-25/cargo-beta-i686-pc-windows-gnu.tar.gz": "052e2c0ff954d66e40101dc075bdd19fdb0befcbfdbc26dd94093bc4147c65cc",
-    "dist/2023-01-25/cargo-beta-i686-pc-windows-gnu.tar.xz": "94681fbbeb12de4b97b0a5a0206204c41b16c3de1c7c3262e1488f00b22aeb51",
-    "dist/2023-01-25/cargo-beta-i686-pc-windows-msvc.tar.gz": "3c0c2205e97136ac5e13b3c89d745af24afc60e6b5adc24abf22755d8d0007a1",
-    "dist/2023-01-25/cargo-beta-i686-pc-windows-msvc.tar.xz": "9ccf1a81d524fbac3f859c0185421936b97ae565164c12ed32e6a39052eac695",
-    "dist/2023-01-25/cargo-beta-i686-unknown-linux-gnu.tar.gz": "68749447a45ada6bb6e06488e3d58ecca7939d3c77dc40c22f22d7257eae247c",
-    "dist/2023-01-25/cargo-beta-i686-unknown-linux-gnu.tar.xz": "6b8942c01d1b8fd1f1f399b7f63db409a30df240b5aca5cf34e3166adafb5053",
-    "dist/2023-01-25/cargo-beta-mips-unknown-linux-gnu.tar.gz": "7f8fcf5d25353dac5d2cd6ad04b20da19b2dbccd25a977e8122d85724a632392",
-    "dist/2023-01-25/cargo-beta-mips-unknown-linux-gnu.tar.xz": "91d0ec836e2941287ac28a753650e1b7b57364af58fdfedebe1fafea8612f1ac",
-    "dist/2023-01-25/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "171f40046f777d84fe5a4349d3565ad3485fdf075d8fbe194ca31ba2be9eeb1a",
-    "dist/2023-01-25/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "0521be760b2a1e6cc134bbe3473dea01a6d0fbf68b05995f41a75875d489eb60",
-    "dist/2023-01-25/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "ee7c39af31d09a42c5ce1151da6dc1147b5c1aceb0ea94cb3059bac49e72ba2a",
-    "dist/2023-01-25/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "dc8ddfc8bd305c3f1f4d7965b8bbd8b24235ef758c38a32b3d64b5879fab25d2",
-    "dist/2023-01-25/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "4757229750f44b3d523ef7a9c778d923113a8eb8b93ad97ef5e4f23a6f1e6a21",
-    "dist/2023-01-25/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "36911ebbdde86d90bca90b61b1b31f6ab054ff65907ac73a22d5ae09d061c444",
-    "dist/2023-01-25/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "8e4ce0a0743d301d056a1bafb4216ae96fd6cb06ca083216eaf7f3a21514e064",
-    "dist/2023-01-25/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "47e28a41670bbcc7a3787c68dcf72ffe42bfbc3e9f14418871ca814538f88180",
-    "dist/2023-01-25/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "7bcab6e25cd8208eb220839f6adb202dcd382e4bc32fa63b83c40fba330246b9",
-    "dist/2023-01-25/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "650bb4d6b51ef5293164642101395fbf6d9eedcaccccc8ff3e2be032d9e60316",
-    "dist/2023-01-25/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "fc779f539835c1f3e1e7d9c1eed932568a5e731888f766202279e9240dd20e36",
-    "dist/2023-01-25/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "b39ab17c34560266df7dc60b6cf5626758f8b28f7142b916f1f3399342e6e0ec",
-    "dist/2023-01-25/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "7b677b4a2cc59b3baebc1265f8a364879b2195905de1eb20f62b66e2fbfdbb08",
-    "dist/2023-01-25/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bceab89d3ae1ffd25fc155a7b3514c69e3962ce8f7727cc7e7c4b40f0c6eb3eb",
-    "dist/2023-01-25/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "d0522064a1994aa338d12f5ef68635f8804a2cb9151dd67771ae132e65560790",
-    "dist/2023-01-25/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "478fdff509a609e5310c54fa1e0eecbb3870a0636132dbcc71291e150c805828",
-    "dist/2023-01-25/cargo-beta-x86_64-apple-darwin.tar.gz": "cfb5bc9dcf4c85915e5c7e4a29e7f45c4e5de4a3535c75ce7c192c08511e0350",
-    "dist/2023-01-25/cargo-beta-x86_64-apple-darwin.tar.xz": "6b1f48ceebc916f9829f599fc815de2b8724873ce8a22ba058a2a1ac1df46295",
-    "dist/2023-01-25/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "60d119c084899f0a1d7661188756833118bc538d7e7298c72d1452b06e27ef62",
-    "dist/2023-01-25/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "801d03dfab7e8007a97d95c551b3a069e56371fe33fa4682e20fa50a8123bc20",
-    "dist/2023-01-25/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "269bdb128749d234e12b5795b90acc1a91bc0c338ed3be70ab2e62d476fcd055",
-    "dist/2023-01-25/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "88737cc19187a0752e45345eb286a5e9d500f9c71e03bb26737888fe42b350b5",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-freebsd.tar.gz": "146d1af37cce4b6eff9f99bb74ad33f2d91383a2b69dfdbd59ad54fc2dd44c49",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-freebsd.tar.xz": "9466a4417a1ea6a9ab03ea7d05f747a731ed0bf5545148a1c782c797dcff50a9",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-illumos.tar.gz": "f32fcd8a18047646865afc67f92d6edda54fbe3f4e9963aba2095e23295e6ce0",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-illumos.tar.xz": "25431bfe87d8c944225122d21ca4823cefe72b304b10933c628d5d2df13d5f5c",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "cd67e483efd3a9cca57523cee428cd9a5555ff93b057f7fef4178a3e2fd49309",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "45d578c09399495b67ac38358e4251e3d7a20e988428a1a5a1e39387d2664da8",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "f66eb2cf2c637b4822e2c326b4a57d63eb3c0b517ddb69ff57a45001bc0a110f",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "7a0817ef29d6511d4fd9dbbdf3e9a92635f076d9b0633cb55b325cebeee4efb9",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-netbsd.tar.gz": "1330a1b4f975b1d96692bdc4a6392ca87e8e99982768acefc2815e386b6f4e77",
-    "dist/2023-01-25/cargo-beta-x86_64-unknown-netbsd.tar.xz": "919e25bd54133f4a8cbbf09218415ca7a5041298b32181fa566c5d4a8bfd8b90",
-    "dist/2023-01-25/rust-std-beta-aarch64-apple-darwin.tar.gz": "3dcf5c58141e44d1c84f33f58ca4dd99edd277ef15a69fc6b94fbe7c67a27483",
-    "dist/2023-01-25/rust-std-beta-aarch64-apple-darwin.tar.xz": "a651af6487e2f3246075b984fffb4072338a559ff8e6c373289a6242c0ca3ea7",
-    "dist/2023-01-25/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "5e3d5aa50784ee63c6df03b07ac92649f76c40ac6fb49c24d97896814002697c",
-    "dist/2023-01-25/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "0ae7440c74cee87c25757159a5749014eecf77b2bcee7e1e71eb9249f917d725",
-    "dist/2023-01-25/rust-std-beta-aarch64-apple-ios.tar.gz": "a47acbecb37786773c5d80da5990298c5facad11151c9991796eedf80472b1d5",
-    "dist/2023-01-25/rust-std-beta-aarch64-apple-ios.tar.xz": "9168f9b1cea16a213249a1c452a59719234c145045ddc6ae1752ce4bdf02be41",
-    "dist/2023-01-25/rust-std-beta-aarch64-linux-android.tar.gz": "54fad0afeead88e1f33eaada03b14710052c6fa0b7130dd87463d3670f1d9fb3",
-    "dist/2023-01-25/rust-std-beta-aarch64-linux-android.tar.xz": "5fdd761ca88de80754cf3e1221db141204f79e6c2aa57c72c0879af3b87dd0f4",
-    "dist/2023-01-25/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "27196acc8f1ab9d6843b673835927c16d6730a8daf96b1f05959884ac53232fe",
-    "dist/2023-01-25/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "0ea12b5fade681173aa4795399710cf5ff21d58f5f2fe54eb8d2c7516ef387b8",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "7bd0d57ba438868635726bad30fea7a52a5c429e77329bf2977805872deb1be2",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "8520674b4e10a6948b25dc0c58369e921a68c48a7b961bae510ac36e5c29cfe8",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "67c5668ce3427245821e53ea976201ebc23d1cb3c1a35a0d725d935de303e8a6",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "38236c5e562995e1aadd25151513580a2a7c7828df3baec0e0cccc0f6a856c2a",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "a5453d21e3620701a957208c573d718872c3909c2c4f9e83be33e14d36677cda",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "751928d0f640e3b77e2fde9cda623c3e9b3bca7de742100fc1f48388e4d22d8d",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "5a036c4d9cbda730e6f2af8c4912506659d1e3065b4d72050cc5b18e442105ea",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "2adfb04a0700dd3503527a80eb5ee71733b0fa2dbe974650d450d4bc3b5c8b0e",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-none.tar.gz": "a92fa3278a98de5ab93d1f487863453dbe60bb31158d027aaaef85adf1f62924",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-none.tar.xz": "1c0e523505aa9dbc07ec867ff8527dde29a706868bb55694d62e31924429e235",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-uefi.tar.gz": "4adaac4b13c8d8170b59913230ac9e313ae48400b314d2ce10c138631626728e",
-    "dist/2023-01-25/rust-std-beta-aarch64-unknown-uefi.tar.xz": "2a2178e4e55f35ea5147f66d36450f9694416c0fbae9b776f39f405a1ab31cbb",
-    "dist/2023-01-25/rust-std-beta-arm-linux-androideabi.tar.gz": "17e4384d3a229bc452897e26400016c70912feb7e6ac2991a256829c5b391148",
-    "dist/2023-01-25/rust-std-beta-arm-linux-androideabi.tar.xz": "e57afb560be9a93faf5f0f852eac5cf5b16e2c05383d995a4e6a249367ee4567",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "d5a7c8f2fd9c3a1baa573b805334e5446605d2aa4589262f67e321c0590ef19e",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "1e62c48781111afd20fb1e015a4f611c3a3301762fd9e64e49beeb6f2bd14c8d",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "9e62d990466900818533af63479758f01f6e914d6ccb7910639c6fbbd49ae803",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "e685b0f2acf33c2eb58ac1e1a526787ee9df2f0bd1a1850581cc681c41a3ef0e",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "7a02618c26f17076add562a9f8792d170fe60190d1868703936e37df3af882e4",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "d8988dd528dcc19742b703d44dff4ebcef71cec66eaae39768434d77e53557eb",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "882e8f09cf68f135a29e64d0eb50727e4ac56939c4cfbcc3d369b928be442099",
-    "dist/2023-01-25/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "7d9b1ebaf89cad6024f07543519dde11da15eab0e2de3df88543156e4a44c48f",
-    "dist/2023-01-25/rust-std-beta-armebv7r-none-eabi.tar.gz": "a7e73661652b1feb9b1f50d271ebeba2938c169c8add96add8a26ded3d8468f5",
-    "dist/2023-01-25/rust-std-beta-armebv7r-none-eabi.tar.xz": "2a80ab44cb2f2b9769f52b6ddc5ffa4c8994092b18a7fb3125cdfaecb4e1a578",
-    "dist/2023-01-25/rust-std-beta-armebv7r-none-eabihf.tar.gz": "f70b0f86c783cc771700dc1f59c43e53b0de2d57775fef5854cd97fde4406b11",
-    "dist/2023-01-25/rust-std-beta-armebv7r-none-eabihf.tar.xz": "07214e7295be853fc7859481fcf94a4b20cc3bc2c022bf1783ddea56e30f92de",
-    "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "72be8b0740b14edda6656d2b5cffc69dea01f9bad7fcc9202586a901376116b2",
-    "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "42fb2607f1c7402f4d32be981cb5c0755be2e36fd0296b3b2753eecae98e5cc3",
-    "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "ae9ec6f3c3444e5b14103db8c04b95597705fe44c68c253c75383b47da4094de",
-    "dist/2023-01-25/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "1e0f7f1ccf9e4f6cc010a096d01f3e6056f1d4b0d319f5699dc67cad2f889d4a",
-    "dist/2023-01-25/rust-std-beta-armv7-linux-androideabi.tar.gz": "6e8b70d2606902b369dfc263ee25343fa3c71c4081f03066822e9a2a260ac573",
-    "dist/2023-01-25/rust-std-beta-armv7-linux-androideabi.tar.xz": "e3f9052bc831ca0a9b38a3da3be846113c6ab2c4f320ecdba489f0eddfc7e47c",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "e858e836806f3641c2f1074e63ce88771cdf135bca36d7c0d3dec0d1a4c98f8e",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "becfe9addbca5bf2123d12e70007c16c036c79fb299de2ce8da067d0f21b0f74",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "eef38b595752add74cf3bd29326116e33a0945115d08ced77e603c5bb46e72c0",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "77e5cf7b344e590b9a15b2c160473f7c212304f624ed9aea8c7a8fd5e0fd787c",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "2a70ffd7f8f3289e005c0f72e2c127a44f8f014628df7ac01b4b0ae2fc61a9c9",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "97e2ae0072d5ae01644eda9a0c3438e78da27bb2f78d843fd626d3db36a6090b",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "7a30075e86bbd33241120dcf078b31ca9ec1877788db2c5700f4752cd447b587",
-    "dist/2023-01-25/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "2c1dfbc1361f030a3a116936f3e43e2c3adae2529feffc98a76e78fdad3572d9",
-    "dist/2023-01-25/rust-std-beta-armv7a-none-eabi.tar.gz": "aafe7ae2fc49e2c4ae9e1e008700f399f397dfca05d624dac4999f6c733ae2cb",
-    "dist/2023-01-25/rust-std-beta-armv7a-none-eabi.tar.xz": "d4bde0e0db35cb07134f6a94eee24e4359478dec9054e8a3802440eed68f60b7",
-    "dist/2023-01-25/rust-std-beta-armv7r-none-eabi.tar.gz": "fe83fe1f0b051838767589ecc9c17915441a44cd77226c9be26e9a63951bce2c",
-    "dist/2023-01-25/rust-std-beta-armv7r-none-eabi.tar.xz": "94eee8d1125537ebe1002c424c686c50996c03ed31d0a1275d49fd7ef0420ae1",
-    "dist/2023-01-25/rust-std-beta-armv7r-none-eabihf.tar.gz": "6ea9fca06fdb82026505c85a7bf7ad8be01926096be63c6cf20c5625c42df7dd",
-    "dist/2023-01-25/rust-std-beta-armv7r-none-eabihf.tar.xz": "70459483493bbb4cb2cc4b2af0cb012c01c47afc214643a588cf894a028a0ceb",
-    "dist/2023-01-25/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "27d86df76c05de73d0ff9542d6904f03ecbd2cedd3a9d6a9cb654dcb78363514",
-    "dist/2023-01-25/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "24b5a81721fe20849bdf075d39a99c0e80a21178327f9fa96b21649c99486213",
-    "dist/2023-01-25/rust-std-beta-i586-pc-windows-msvc.tar.gz": "3740517ab4573f77d5812c9b9c04fe63eacd29e56ea7ba5c5f335ad66026bd30",
-    "dist/2023-01-25/rust-std-beta-i586-pc-windows-msvc.tar.xz": "6c4e780249dcf8b306f8fab3fddd232724248b2670113dfc14c7823781d669f5",
-    "dist/2023-01-25/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "15fc95314219ac5b38f44a4ec3568fbb4ce66d7ff7b63cdf1fb7a8b058f2933c",
-    "dist/2023-01-25/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "b1a5ffd05afd400760002da124a8e5c86d091db574bf1ccf255d86b2515789e8",
-    "dist/2023-01-25/rust-std-beta-i586-unknown-linux-musl.tar.gz": "ef3551edc72cb79e776c7792346352eb858f3e3f7ee1c261b47ef974e52d9a2f",
-    "dist/2023-01-25/rust-std-beta-i586-unknown-linux-musl.tar.xz": "0e1a8e0ababab458af0a329e14398274fa55bf0e6ce2b2a0a515e5f6d12d6f34",
-    "dist/2023-01-25/rust-std-beta-i686-linux-android.tar.gz": "74a26b7fee3e0b95f4f0e065bcac58b865abd5f9abe14e42b2263bb0b87aee69",
-    "dist/2023-01-25/rust-std-beta-i686-linux-android.tar.xz": "c7df97d2322f5f331d349e35091ab5a61fae8dfc16781f1a74849c7c1e150293",
-    "dist/2023-01-25/rust-std-beta-i686-pc-windows-gnu.tar.gz": "396ca6747252adc4e6d41764df00418de22c22ee77823836c4fa3f1bd7cae869",
-    "dist/2023-01-25/rust-std-beta-i686-pc-windows-gnu.tar.xz": "4536de17560a21d543f81f6bdb25581a3b145b792531590a6ba35464e95c6389",
-    "dist/2023-01-25/rust-std-beta-i686-pc-windows-msvc.tar.gz": "da11b2338bacffa3940497b20fbb2544c0846696925d59cf9d7cf4514dedbb81",
-    "dist/2023-01-25/rust-std-beta-i686-pc-windows-msvc.tar.xz": "5bd5cd665f9e3d92f26998694c12b1f0e53df8ca9ef305c4cc48dd81bbe181f8",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-freebsd.tar.gz": "b1553f92e0d0891717635136ad698a017c6aaab07a58183284752ff5480b37bf",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-freebsd.tar.xz": "d6d2a550d36028e5adf62b875fccbae2f78546828de880e5bea33effca22edbd",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "3d9f9c3108d45f95ebd12c284147111155cd3714caa555548111fb6791c7ef1b",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "a4d9ee2238037d3ca5d4a9dd51c04737ecc2a12dc0be1e2996bbe46d7c1cebb9",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-linux-musl.tar.gz": "9380bbf6ac2d745d1b7c3207c2cdacdd7bef0ff225e3ee5f22e46d826835b17a",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-linux-musl.tar.xz": "517232f4e831f5305e836cc0666adef721c1b68fae80617a57bfb56405e343b9",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-uefi.tar.gz": "1e6bfe0d160e3650a1a453de57f51673a6e04f9348f361fe08d2e96fa89d058c",
-    "dist/2023-01-25/rust-std-beta-i686-unknown-uefi.tar.xz": "f19c1458ef1386540cffca6cf7485ad22c38f0e9ee8a62e26a4e10eeeddb2a36",
-    "dist/2023-01-25/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "6169b653843ce79f799a99fc7f147bf8315688214dc47a64aed792f5ca274ffa",
-    "dist/2023-01-25/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "7f5e0f0e02c51dd88b9b819d1ae370e922eacf2523dd0ae664cbd8d79b7cdffe",
-    "dist/2023-01-25/rust-std-beta-mips-unknown-linux-musl.tar.gz": "124c50ad3ca4da2c97a5e96599762d7fad6701d0193b4a1ba3249c3a67d349ab",
-    "dist/2023-01-25/rust-std-beta-mips-unknown-linux-musl.tar.xz": "0a07005e369def1cbc8d49cd2904a1fd60c23771eca700e9b4abc49d2edf74a6",
-    "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "5278c6eab22d49d033595f8b98cccfcb89fa8827ef3a8ce487e78c9f74452d2b",
-    "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "206a55c0e4fb54ccfe2f372888bf42212352d56a7f1b3ba6628aec130b325573",
-    "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "f64069192d200f852e82735e239cb678fae027a7120e9d79c136aa4a3887bdb1",
-    "dist/2023-01-25/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "b31af554724c4582494548efda53dbef35db5cd3609104550ab2eee1bcb3f327",
-    "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "8445183d07e397b5bcd0f45fbb1b58ff22dc0901d0a1a3637761929f6b0e0364",
-    "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "5919f229d0ca138205def6752109056c989493c3a2a241cbd891bfdd84f8c7f0",
-    "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "c72e51c7b1a5720dd74a923fc2ce1caaff1da484c063b50f96bcf84db529326f",
-    "dist/2023-01-25/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "9a11cb1d587e2389531edff732c205a653e43bc62132cf697cb9fd04842558df",
-    "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "682fe8fe1e3dad08190e8c42fb2df8fc734a42df081c59d0b30f4cc9f5fcef8d",
-    "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "7eee1fff997cd847aac8d6c61cad4bc572d3069dbe59ce2a06c39d6b63346d34",
-    "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0b5c68bb95668394dda1c910cf99835007271b5598d4652c7c6b974c6c0b2acd",
-    "dist/2023-01-25/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "411c8552901b80720a3bca0707eef475a7ad1650d34cda0b29fedfa9fc9b1852",
-    "dist/2023-01-25/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "187fef84302125e38937cf390bdf26d40ef98c6d06fd5893db8adceab3e75f04",
-    "dist/2023-01-25/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "83ce613db91a23549e4a1e1d5e4c24ad3ca7ddfb586b45d25e2bd85e67a19390",
-    "dist/2023-01-25/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "785bdd67b22af15637696a03b6a4a917f8195049a4bda14a88dc48e6c3101a5e",
-    "dist/2023-01-25/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "df034c1d2baea51f6756e1efef58db81cda5e795691c3a7175cb3b61edd8f33a",
-    "dist/2023-01-25/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "24d020c96db72a49c39dca1546a683d4d2134718dafbd74fb846dc77b30cf78e",
-    "dist/2023-01-25/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "a798a58bf5723f86b08a11c92f901cee246c5a0af06c4f7e08b303c7fd6c0354",
-    "dist/2023-01-25/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0c383e01f53b5bf85301c46978493e94aef2eba98a966ea283771de7829ea492",
-    "dist/2023-01-25/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "61040426e2eb9950a3487109977ebfe66c134f5394c95847df222ff24c61563b",
-    "dist/2023-01-25/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "ef44851d420b5ee0cc3351084c9bc645e4caba447c8dd737840315687547657d",
-    "dist/2023-01-25/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "5cb083baabc7f33c515f2dbdaafd49465c85888d97af68dbd2bcd08a3e70e016",
-    "dist/2023-01-25/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "96bd2d16b470e6377c9c2894b24e77d9f7b51dd54d5369dc361791153a9d1519",
-    "dist/2023-01-25/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "93af94b167327c431158be466ff47b3aab8a77319bf7bed8bdbdedb4633a8e67",
-    "dist/2023-01-25/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "57071d1f70a444a1b4b26b2a579e6c6324522893de60be9e97fe281e8878f276",
-    "dist/2023-01-25/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "a75b8cbf062d1c6fcd8b2089c83f82b75247ced44793272ec56849c4448389f9",
-    "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "195fe88c1b4b77cb12f566e27a9d3ff25ed2edf5f26be9b3b3dd0a88ac6f5e3c",
-    "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "76884a90032874b98b0f4f873818dd90befc91d2ed96945120a1ce5a6a80c4e6",
-    "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "017a6896b2b0e534c1c80f13eca4a3a570560800a117ea2d6b4ae0e6d665a969",
-    "dist/2023-01-25/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "ac712a5b5cf3cd2eb2ae3825e75a5d84c5a899f86a104195b200711da15e9e53",
-    "dist/2023-01-25/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "405fd311dec82db95adea38b3ec0e53454aca72bafd58f7960f8be25b50f9bc6",
-    "dist/2023-01-25/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "0a3c8988561da39a817a3dba8115237f1c4ab6642f1925f52b7398102184ec7a",
-    "dist/2023-01-25/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "65b8a84d7355f889de036b1ce760068c2b81d73b43e5f7da29f9706ae1806a89",
-    "dist/2023-01-25/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "1c8843868742c36a5e9f6839275b4ad2b8a45f587f18f798448a674e0b0841cd",
-    "dist/2023-01-25/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "b225da38b37554abb5a7f098be013b2e5971f9f34c634661d3244dad3ef1315f",
-    "dist/2023-01-25/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "78018c4b996f7fd8bcaaf6073c84a3180250840263b54cc68ff6d195855b0727",
-    "dist/2023-01-25/rust-std-beta-sparcv9-sun-solaris.tar.gz": "468853e0d54a486aa0a25dd9fd2ab47c08e48c6aa47838c350c108738d7ca812",
-    "dist/2023-01-25/rust-std-beta-sparcv9-sun-solaris.tar.xz": "c59fec4162cbd9204d73f7aada19aa459e23f3ed73584203d83d52439a982382",
-    "dist/2023-01-25/rust-std-beta-thumbv6m-none-eabi.tar.gz": "326a3fe4191366ad170f44bfe726d80954024b1a3c7560d75da77bd16b44cafb",
-    "dist/2023-01-25/rust-std-beta-thumbv6m-none-eabi.tar.xz": "9c59dca2473fc377b65ce74cda0a3a064cf9fe07b1fb1eca0a4641b6de397d0a",
-    "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ba2a8bd5d55ee9eefb6f5a5bae987822bf763783ac0374b97c823cfbcced622f",
-    "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabi.tar.xz": "e8b7df90ffd190d0122d20d4c070f42273bab2da67745f831934fbc09730f34f",
-    "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "183f0945d1df7a68c45bed842991486ffee21a03313e60e89746ac4122ca348e",
-    "dist/2023-01-25/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "039816d5dc555e28fe45183a09a77a6357ce571111041740d0f95e89489b7cf6",
-    "dist/2023-01-25/rust-std-beta-thumbv7m-none-eabi.tar.gz": "22c48ee80a14149c2635eb344f74ec5765bcc5b7eb0fa1c7ad55b25c016c0934",
-    "dist/2023-01-25/rust-std-beta-thumbv7m-none-eabi.tar.xz": "a690f9227a3587f5dc143ab86a1ea7c83777a36b1ff18e877801c73745ff80cf",
-    "dist/2023-01-25/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "16978fed1307ce642c4c9b0acfb09d9dc532b64a72d25e2d1f3ab3afbcb673b9",
-    "dist/2023-01-25/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "c1cb59f61a45cb2a842d235762d244a4f4b2f078bc9cd1fe6ef5c632c665573d",
-    "dist/2023-01-25/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "7d005cc7f199344bf7ecbcb5d3a4acc8ef42cb61d18fa091fe001872a69ab4bf",
-    "dist/2023-01-25/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "cb567b761f1d78188538e1a5cf4f01aadd641dfec3e8c1a3e2ff2d5e7b930070",
-    "dist/2023-01-25/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "c7c83022f3772e1f7af9e8883a1082695f17956ad4b2d4b8fafeb2a8b9ec6ee7",
-    "dist/2023-01-25/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "392e9bdc0d84e9b9ab83f7118abd07ca39df9fb5a8482f6c9a1bb8969db2c1b5",
-    "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "97f59b364d4a3491f612217f455b1e7285691e12e73e42d4e7a074c301a973f6",
-    "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "4935afc5e64589ca8f06d3b8bda2ccb89901a60334b50c45be0b760d6f9f58a8",
-    "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "eb165b5f5924a077c563d7e8e2eef96eff9398432748070b87f4baf0d04388a3",
-    "dist/2023-01-25/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "9c2bf943142fb554fe2332cd7d12ebd568b8b59e06df73e45ad35da27400757e",
-    "dist/2023-01-25/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "bbd4bb99dbf9b8a178ae767962877bbe8dbd73175e68db654d7eb208c0f10cff",
-    "dist/2023-01-25/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "265ef776729a591e3867947eb23384aeaf02887a2f03f893bb21489bac1aff88",
-    "dist/2023-01-25/rust-std-beta-wasm32-unknown-unknown.tar.gz": "177edb18d11154664c510f27fc02b566c40320b5604587975b0897a70647be3d",
-    "dist/2023-01-25/rust-std-beta-wasm32-unknown-unknown.tar.xz": "7105e29d9a6540ec629a8844407b84624efed5e2a2642a5fc18fa8d73ad5356e",
-    "dist/2023-01-25/rust-std-beta-wasm32-wasi.tar.gz": "d13a3c25523c269b2515d254558af46bb35fe24d796bdd00aafcc84c63f3ac69",
-    "dist/2023-01-25/rust-std-beta-wasm32-wasi.tar.xz": "97ee2ec6214ffc91e46e4e590acc8dc4e69a7a935a64a0e2af31940d745e2ac1",
-    "dist/2023-01-25/rust-std-beta-x86_64-apple-darwin.tar.gz": "d184abb149484d78b713cd1d0f94db958dc4ac182eed453178f669c44856c823",
-    "dist/2023-01-25/rust-std-beta-x86_64-apple-darwin.tar.xz": "e3c448e63d87842f42f99390d7d0ed18c13e03a226967e8f2e9ef8c764d10318",
-    "dist/2023-01-25/rust-std-beta-x86_64-apple-ios.tar.gz": "04c884f5f4c4a6d1dfb0941b62e16ec5516d42e6ecdb7b3b86f23994b8c7b295",
-    "dist/2023-01-25/rust-std-beta-x86_64-apple-ios.tar.xz": "6a3c0e72376a2f1654e7ac08dc5e38794a91b432450c7bf978be97ed10f1fa61",
-    "dist/2023-01-25/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "fc41a378f93c5bf1280c52d21f495924c2e76925f609356b8d27e43d0650d2ab",
-    "dist/2023-01-25/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "ab6bd497938262cae110bf9f39cc94f5ef1ba831db19e63b4d60c8fef7f8dc90",
-    "dist/2023-01-25/rust-std-beta-x86_64-linux-android.tar.gz": "d990e089f838d0158fa2ba3ea08153edb48f4346e682f0fdcdfed1b37a186b2d",
-    "dist/2023-01-25/rust-std-beta-x86_64-linux-android.tar.xz": "0b6e71cdcef8c32e649dc209dbe9bc30a0864aba4fc85d0d615ff5c405204f6b",
-    "dist/2023-01-25/rust-std-beta-x86_64-pc-solaris.tar.gz": "3cc30012778b45a27dc6c92f5cb0955461dbd1aba130c191c20a510d29bf2c00",
-    "dist/2023-01-25/rust-std-beta-x86_64-pc-solaris.tar.xz": "0e3f033b01d1223d9f55c86497c9625c4de36953b6c269ca622c96b2fce09afe",
-    "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "18a61cd3593bc67eeb93b615c4585e18495128cd4f50933776705c6ff5cf1616",
-    "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "8bf3998dfd69a17354dd79dea20220f405a2a116842d3813fe033cfa5a6aafdb",
-    "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "76137f8246ad53adaf26d739c91dd3bc5820697a0c1d2af0937328bb5e6536b9",
-    "dist/2023-01-25/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "2febd8119b376da8f2b1baf3ca63b97d11a17e1a766986ff1d6dffc522cb0081",
-    "dist/2023-01-25/rust-std-beta-x86_64-sun-solaris.tar.gz": "b5769729f089ea5cd5fb5ba1995a0e18dcef21425b69b7e952d42c5bdf0253c2",
-    "dist/2023-01-25/rust-std-beta-x86_64-sun-solaris.tar.xz": "a8593120f87887738390e0ec9ff1d72a743a77dc17a33276e7bec7b04f45442e",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "269fec46599b8839f3a81c6cc85fbca7a7e86cb661e5cbcbffb853ba674ae1cb",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "20c2d1d3e64f56f00c237ae261d5880a7fd7c6f1e2360dc7fa0039b3ea932c66",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "d64735ce43c75d7c741f9cb7754812f09e21706be8bd0931d72b09916d312844",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "f501f199bfe1120901e919a14684e57f0723b59ffb5cad79f501834a63df5570",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-illumos.tar.gz": "a80058880e7441e2cd6bb77a7a284902d15dc21d8f0b37f2af3b3da31f07f9f4",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-illumos.tar.xz": "17d07564595b2dbc9eecc8271d3332bef81c7a57138559740c606d2181777f89",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "0e4c01e6438fc005ba7177d33cc0dba8646eb51a47da06b079ef9fc2e264f052",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "1f95934a853b0ce1f4bc50ac86b1ae74a34acbae8a64903faf6f7ba63e49051b",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "431fa66d45ff345f1fb2e279eb52ab24757ed3971f049f9a04a63b228a417f59",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "6901b028b8df3d09e994387a810d3a74b873d2ff5fcf93c1d49bf7c3521a506b",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "a22d8f960e3d15886f893dd4e137becf9c84b1bb2ce500d574e5cc85f43b2b64",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "1fa467a1334a1cea4af8b27f7fc186eabf3a8f26091ae29b501bec6b2564b98e",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "50f2c04d4ee499959f52546af600c40b16a5627bb9adddeab819519231cf1efe",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "69084f5bf6e22d6ba232d2040bfee15b00418ab20980c716602a19134ee54bcd",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-none.tar.gz": "5a8b98fce343e17fdfd2f3f9b4f810097cdf12430e02d65b3d1042e273f1ddae",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-none.tar.xz": "d5db956978faa532d822609d475599c12507e5b67ac73b9a9194afb7449b9b7d",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-redox.tar.gz": "3c4f69556a6ed2c64fd6274bfa17ff489b5e0c9f1f8d6884fe31c28c39e15d89",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-redox.tar.xz": "feb6456b55a38b83755b281e039941d97659947b289ac2750fd3b3588cf43fd3",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-uefi.tar.gz": "81e795c668369a3947d4d69aeb4f823c8446b09ae18c6fdc800d54aae514f27e",
-    "dist/2023-01-25/rust-std-beta-x86_64-unknown-uefi.tar.xz": "5c51b99639e5f67e01fe37a868dae17da4ff11d755434b189cc4ae81453826ac",
-    "dist/2023-01-25/rustc-beta-aarch64-apple-darwin.tar.gz": "9d6277d58b9a679d47eb80d1132d590102f632d5fdb85ba54ef653b2e602c6d3",
-    "dist/2023-01-25/rustc-beta-aarch64-apple-darwin.tar.xz": "6a49fa544dd3bc4d657ae064863b760935977674e6c837f6a7f84dc1c9dbe95a",
-    "dist/2023-01-25/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0536b525d92007041a4d5f4b57601bcc17e1257f44eddd1e4630fbda8b5ea2e8",
-    "dist/2023-01-25/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "35621c50a8e1ce5591dfdf95b4f5e17e60478309348e67f6e3bf767b57c494ba",
-    "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "feb0c0534f2f78500a25906fb6f0bd5772574fbfbd23b6abea807f074905905a",
-    "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "fb269a472ef44aad092259352bb55b24dafc56459eacb7300fd7db0bbc5a96c1",
-    "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "98514e08e1a21f94028df39496e802f5b6379414dad4e7069253cd8b3f961c43",
-    "dist/2023-01-25/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "b01b5ef23232834174ea31bbf402fd4652769a7fac5b522ac28e53c469389b60",
-    "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "d638873a2fe3bb666174b4270a44da25a9f7f05f0a2544598556485661b51d66",
-    "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "7bd32b738a280b6d42fb925b5c7cd8b4ca660285ae77cf27b0ed6eafb0b0237c",
-    "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "8ed861c6ccc085030bb0947119746df3c83b9971e7b7c0ca43a8133700f985bc",
-    "dist/2023-01-25/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "f4ffb8ec45475b96815eccb657d9a5f443e8067a2f7b50a18eaf80c8a9cd1944",
-    "dist/2023-01-25/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "e6a809e4e255e265aa54ac730655569e93b0227037e5eebe2995e6ed13c4a2fd",
-    "dist/2023-01-25/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "0849a22e9d82c3cacfb39c5067106767bc40380e231842e968770b7d79dc9376",
-    "dist/2023-01-25/rustc-beta-i686-pc-windows-gnu.tar.gz": "348a94bb0048a2de0764ea5ebc83a6578d1f63f4edf8d6627cd346345cb3beda",
-    "dist/2023-01-25/rustc-beta-i686-pc-windows-gnu.tar.xz": "02885355eefef4a901522a441c376a59521ff91889dd6e2438cfe5869360ad7f",
-    "dist/2023-01-25/rustc-beta-i686-pc-windows-msvc.tar.gz": "56d6b9b2d0e8eb13a568b60f2b5284cbdb3efcbc921d6c318408c58d12c6ee11",
-    "dist/2023-01-25/rustc-beta-i686-pc-windows-msvc.tar.xz": "bcf405c76b2aebb76ca70595ddbe5de1faf8c34320b08cd4839db7f46dc9dc7c",
-    "dist/2023-01-25/rustc-beta-i686-unknown-linux-gnu.tar.gz": "6b5c11f41bdb8a7b596ac92bfe18e7a2410a7fc77fe7ca7036e72c563b9e41c0",
-    "dist/2023-01-25/rustc-beta-i686-unknown-linux-gnu.tar.xz": "7291ffdbce495b5d0ca017730495300a72d3341170d099b3c8abda5cb9ed190c",
-    "dist/2023-01-25/rustc-beta-mips-unknown-linux-gnu.tar.gz": "6005076b8cd38020a02cd2720e8c67491d31f50465d62d9f5148d93feb4eb198",
-    "dist/2023-01-25/rustc-beta-mips-unknown-linux-gnu.tar.xz": "1b421c2addb488faefec78cdcbbaf03a9c45640f4ba6740bbb1afbece3e30ba0",
-    "dist/2023-01-25/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "2d1f7463d3922238c189c5f669b8f4e80f85f389f5edca000b63ebf041fb4222",
-    "dist/2023-01-25/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "29dcad8e598e6b79730a53146d3d8ceb5acd0029a83216060ece931d149e9a97",
-    "dist/2023-01-25/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "c3e1527a463155bc9ed2c3eb65217c72fd067bbd316432a16a2777a444e7eb9a",
-    "dist/2023-01-25/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "8a031c5830bb8168c1e20426082c0783fa52310b22a28c5fbb5b1214adcf3bd5",
-    "dist/2023-01-25/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "5c1af72641cb7bf514f936def835ebccfa908434f9e26e6d3cf65756d68fe24d",
-    "dist/2023-01-25/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "40a95925bb98eadd7b49be71dd9fa76abf09fc16bd2d6707e3206cf7e7f9b9ce",
-    "dist/2023-01-25/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "2dfea875b3b5f3405f9df83fd5a5144b8fc93a90ba17a3ffcb437c934a9772e8",
-    "dist/2023-01-25/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "2c23590890472f2ed15df449a33188bbc7d3dc8755e8929861ccdfeb24ee0909",
-    "dist/2023-01-25/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "0b31cad32717c5c7a75069bfaa32fab82d0eb75190b0d34d2e09c221def5f7a5",
-    "dist/2023-01-25/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "939feb641d84aa98e46934c3896adee94169d8e5d8d2d97065e904aa1eac16ad",
-    "dist/2023-01-25/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d031874dccc1fc029196bc49f7713805226be2ac03a17fc38dc2f40c7f807093",
-    "dist/2023-01-25/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "8b6f367822b14dfd341d711c4736e00ac1fcc914a3c5214209742f2543bba880",
-    "dist/2023-01-25/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "6fb98f6c504ff7278af6f840e39d1236b7209a35a3f5dc78d281c59a2264b525",
-    "dist/2023-01-25/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "1e5a16e7c67bad200e3f051aa959cd9123ad26e15443128ee9ce28151b28e7ba",
-    "dist/2023-01-25/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "c8bbed9a7319e601e9e53461665201f89aceca9bc72dcdd1e3206110d535c6c4",
-    "dist/2023-01-25/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "05af8b1637b522af7ac981d133eaf88c157a7d4ed414ce53c13bbca0667510dd",
-    "dist/2023-01-25/rustc-beta-x86_64-apple-darwin.tar.gz": "ead6472d2644ffeb7f27252e0445aa27b9cb028dc982da011069975767711249",
-    "dist/2023-01-25/rustc-beta-x86_64-apple-darwin.tar.xz": "3777d00c129c51b8980afc2ba1b1605f58490ec4d5203609d260e05ae5801182",
-    "dist/2023-01-25/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "5871e7fa9b9af9af9ccc405866774db110dc5ba8b66649c87f546139c383cea1",
-    "dist/2023-01-25/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "9804f9a57acfa97db3a33fa7f77f5a8ced7d6b9e5013e61aa76287dfe45d9223",
-    "dist/2023-01-25/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "3a7387c88e4a17e331d8f8800e6be0cf113242edb2b760fcff0dcd2ff97c1ca8",
-    "dist/2023-01-25/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "12becb176b75b9274a44ccb22a4859fb8cb52df2cf954011c7294d22dc2e8721",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-freebsd.tar.gz": "262df9ec15e8b14d1a2959f9d386717147af17612ae92762916e9e195ac83c7f",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-freebsd.tar.xz": "2647f9420cc4b2a2a94b32ef6c7d88285bb50c3b04bbd29bdc11f6e5fb8f9c4f",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-illumos.tar.gz": "82875b6f60bbdea438f0da1a162c30d236fdd32124296a83510954f89dfbb20d",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-illumos.tar.xz": "19bd296d5c116bdb620e50b6fba3c7d5a5e978f26a8f1be1afec1c6854408d2c",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "45b8d74f203b66d25a15e59db755918d0954a3338f08236664007de2478e2438",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "c047becdba71a802c1d06b31e5c3dce8efb11a9daa299e1cd03a0f9f6b48cbf9",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "a649445f1676acafc59b4808211aa669c9fb8093cabb7007432d0ae2f6e21239",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "b6ed06a8df0de6b64099fba4d1ca9478e0802dfc086308f425692ee40faa8d2a",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-netbsd.tar.gz": "d939bd071f42aa7657297110be68dd9d2aad840272bf881a1fdc82053914f970",
-    "dist/2023-01-25/rustc-beta-x86_64-unknown-netbsd.tar.xz": "5671084575291d8c4ef2ed0930b22815d6810e2378fb98ca5a0738faa76b525b",
-    "dist/2023-01-30/rustc-nightly-aarch64-apple-darwin.tar.gz": "f634a282a8388aff57d988616f17f2c511253a02d45193b03fa87167448a8cd9",
-    "dist/2023-01-30/rustc-nightly-aarch64-apple-darwin.tar.xz": "4fd6a4ec8665ba71ccf3ac7d08f9010b4e130ce496bc62548d36170786f213ab",
-    "dist/2023-01-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "5b7fc325745b2f1e22b1a58ead8163314c3ec06f4a30483bf7ddfb57f811a2d4",
-    "dist/2023-01-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "4aa8d587ebd53bbd11c33f263991328576977d801d5b6eccf56147301ea0f52e",
-    "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "7838bf7da92539b0329be0b9b80f0738df3617e982f539326a6a99892eb905f1",
-    "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "636af094f94de9baa3edd5f9e1b7655e0bb7f6f23d24d6f389a3abeab7360e00",
-    "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "51b8a8a06244ee37d2c37e84154ff87132b4f90a1e62a8c9454ed5ea5c296c1f",
-    "dist/2023-01-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "cc18ce5f4f461a830c725ca8ddccda17bd726374198c487810eab8d36a8f7c98",
-    "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "e2d7b96bf5e2feb47019c63067dbb1627bf26ac4e730774d29ea9f6967edae3a",
-    "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "0483f07f1a53949c2f04e2766f53fe9138ce126059f650ac61215e6a84c5fd57",
-    "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "d3ad417041c432438f1ed56a2324ab412dca7631a74da03e0bc72cd28e69f197",
-    "dist/2023-01-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "f029fafa0635efec9065d76780f003e2c4220c7b6ea4b426ebcb57d943403998",
-    "dist/2023-01-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "dd2ee13ccea00c23ca2f90872c7c31a3a1ef008962db9cf8066acc130bca778f",
-    "dist/2023-01-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "dc23fa4c0268a7227e0f9e4941376ffc4c64c0614622f442da10dbb75e014dd4",
-    "dist/2023-01-30/rustc-nightly-i686-pc-windows-gnu.tar.gz": "d4b02e59373fe60ba06e979f784bf1b8c94ca4a5ee471ed83814623db9e14af6",
-    "dist/2023-01-30/rustc-nightly-i686-pc-windows-gnu.tar.xz": "5355e1bfdddd2a56dd0c882fc492e4d571e5b29636d381e848102e996ca9b680",
-    "dist/2023-01-30/rustc-nightly-i686-pc-windows-msvc.tar.gz": "02a43fb72394837461770c1b472afb534ac03bac9cf23bfdbba8227cf879dabe",
-    "dist/2023-01-30/rustc-nightly-i686-pc-windows-msvc.tar.xz": "78cbe74bd0f7029b01e3aeb451ea6bbc1656db1fb4a80caac4cc27b6e0144b79",
-    "dist/2023-01-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "7fa9a3e3d70a6c15bfd00a0b5a83d73f4e952862b8ef1d6837d3598c4cee8752",
-    "dist/2023-01-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "76b3abe5c532785ab80804461204280e6d853773c62956f283f5dc88130e310c",
-    "dist/2023-01-30/rustc-nightly-mips-unknown-linux-gnu.tar.gz": "2aa78ea99fceb90e568f6c46881623f5088afeaf47ba204abf2ef755397e84eb",
-    "dist/2023-01-30/rustc-nightly-mips-unknown-linux-gnu.tar.xz": "6abe1f28662aca904b1fd91e46e0441ba7b4f66f1e7757cab93a0d73012b36fc",
-    "dist/2023-01-30/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "3afadbbe1b073ee2a81609c87c3d88a5d7344765b970b8c48dcdfe539c5ba540",
-    "dist/2023-01-30/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "f1eb22696c376dfea266090320e7a941986f8de2176b6ceb6dc0f0452994ae4a",
-    "dist/2023-01-30/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "c7f548350e118d4281a8a6ac8044c19eb1583683490b0ea6fb9f5f27f5e3873a",
-    "dist/2023-01-30/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "aad40926a20ac8bda9e534d63e180adfa355e9df22a1068310cf9ae667ffd0ad",
-    "dist/2023-01-30/rustc-nightly-mipsel-unknown-linux-gnu.tar.gz": "4778f49dceea661baaf641531946dda47d8ddb7f801cc63afbec37a86d45a0f4",
-    "dist/2023-01-30/rustc-nightly-mipsel-unknown-linux-gnu.tar.xz": "1ba09bcefaf5ed5a3029230ebc3e9cad33626b38553451b952ef215c68a98e34",
-    "dist/2023-01-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "6efe1f619ad49c94b3e6fef2a51893cec88ecacf31d963576e6343e8a050d20d",
-    "dist/2023-01-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "971fdc824861c98bf223fb2c733e780cf87c90f3a5646561f4e35fa8cd068c7c",
-    "dist/2023-01-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "10741ef62e00541a85747db16f830c71ffa1dce036a95bc43df433e450f96602",
-    "dist/2023-01-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "b8bc80ee97c54e428c51f56e30cdd610fb07f41bead0409b089fe56237bb0421",
-    "dist/2023-01-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "f8f52abf57943895d34ffe2157f863bbdabaf804969baa2624e38a13648d43de",
-    "dist/2023-01-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "7dfb9af100df05b558c873b5440c532d28de44fbf8c7d933c29481eef6693539",
-    "dist/2023-01-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "9454d78432ce8ad61f8cfbe448654d8acddda9c596c36c7863631c638aba949f",
-    "dist/2023-01-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "c69f1b0062aaf566d6610e6b19335ed002a281aa65b34c1be001a875b85f76d2",
-    "dist/2023-01-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "92184254f00348bfaa7f40f8a07b585eeb6dabc02e4dff3351cb395b354a930a",
-    "dist/2023-01-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "b41eff99cf9b9851ffbf496ba6dc892d5dfd124da68c91db66d6fb77b19370d4",
-    "dist/2023-01-30/rustc-nightly-x86_64-apple-darwin.tar.gz": "8d901d7c2ed293a9e2d2fb8849edee50e6f6e3c5a049fa91cfb13f8f16571b7e",
-    "dist/2023-01-30/rustc-nightly-x86_64-apple-darwin.tar.xz": "d472dc97f3242d243f584efe113f23e62ac1f53677fb3b3cd1749adb65a6635c",
-    "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "9259adfb75f90cd43c99f253aaf4b242afe941c4075eabc6bce824c3337b4d2e",
-    "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "e42b3e9a462004296e53ed3e71403caff98b3718ff15508d913e0a25ad02ea3d",
-    "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "82f615142be1fed6ffd5c9a6f2d1d3fb73ebf32801348cf6279991c0a76b771c",
-    "dist/2023-01-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "2a4e2aad343062379334ee1a73b657656e0c03f0490c901806c864ea8a38ebe1",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "2a8fa3a6a104bd35de9a83d98786e7acb7614e0b830336adda30e8d1f1cade69",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "37327a8b756918c25cb799f2e5742a07145e4c1e424442a5d975e99aff1f303d",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-illumos.tar.gz": "8be0295e8b89b6e8f465b0825b0625232c7624cb897efe3e0bf4da222799349c",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-illumos.tar.xz": "8e515082490a64d83771131f4fa5fba8b021d205b56149459e2f2da7584407e3",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "c105e3dabdc7bebebadc6ffa5b6f3f962057948cdac6647cd5adf16d66982701",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "09b82ca24ff847e000aed1b2eaca74cdf0f6e533bd6655eaa302281eb7037163",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "e77d81b158b53a94065cd90f68e26dd12d156084b02c53c51172e02c4db58c1c",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "613c7eab1b998aec0673e1781e3ed78c4d038b449d879c11254b1b6d4345e34c",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "ac8c53be048049118af9fd9d356dcc69ddfaafcd52020ea93703c94d6167b367",
-    "dist/2023-01-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "28b1c8adfffa7863bcd8a46ef407044d06fc16b29f7b6f42072fcbfbdc779e79",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "f7e585d9016a012e2cde4d7e0899e52e1c410c53ed9caf6db22d13f6791ffb0f",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "bdea28e1700f34dc0a6e57db5f73caf6c8d1671a8356cc51096f8155f58690c8",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e9988193283871e678a0d0e08cfb5bdab37d43cb0bec0e5f63a12a38c164936b",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "30d1bad2b730589f9d75ca3e2d410d0f9c90707526ed6a66edac92a19eb3716c",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "7c6c93fa25193360e28a90269439b28465b6693b6ce68ff2eb1c4209c36a9d60",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "4c8331d14ab428b922135690b433f97acd37291e1801635252ab5da849d42180",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "0fb5372bf4cc0b6388194021dc7b6a539bd413e89058c05cdc42c1dfe8d92edc",
-    "dist/2023-01-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "0e2452ff037698781157c30c5fd67f552e897feb1d86b7b074c195c70a6a1a3a",
-    "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "6c079c2dde918cf2d9f029dfb3a2a9bebba2504dfe97c5fdc0ef79022415b9f0",
-    "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "5ab6fa16d7aaca7e6e36caea8e11b916c089dccb511f79b7f69bba667edabc50",
-    "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "7b919c9132269fcde24559af58d3d2fee56d93308d731d891f89dcee193bbbdb",
-    "dist/2023-01-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "53d7c7d03b64526e013c11c49519a63f51562f9682039479c377c92529e5e026",
-    "dist/2023-01-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "c19265cc3a85cd296a85b450e2f4e4b5f3646aa70d6c70dfdfe9ef222fd72136",
-    "dist/2023-01-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "66159d87fd85a4534104da3f7f5c0a14403960ff2c836eb72e35bed6a1ebde32",
-    "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "be84f8558d15dcc802f399f44f0de58e93b28e99cf62e38c0d6e6078a8d73102",
-    "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "b4e8f18335aa3cba092df29c3aadef79c0b88e00f563604467cb2485e10cced6",
-    "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "43ce7581f50e05c775b39a6a6d297d6e8c56a40f5a5817ae4d996d319fbe96c1",
-    "dist/2023-01-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "2ca2b20996f1a4cbdb619393a3f544ada208caaf381748ee997a70139e52a591",
-    "dist/2023-01-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "229fb281ec100e68445b5a402a3d39a0947475054c4f043d55ab2e33bd3d2a57",
-    "dist/2023-01-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "65326115afcf1c8e07cfcb9ed294a1e5a136b998557cd60b4cb976520f84cfe1",
-    "dist/2023-01-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "337bdf61237c8e47909c3f14b5c8fdf3b8b14f2b265e6da45cd6b4d8180d0afd",
-    "dist/2023-01-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "d683349af8320d6bc9f16021fc8937920d70e99cf668ce64cad962705dd20ea5",
-    "dist/2023-01-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "08a1ae9e61ef097c5d5ce83e5d2bdda62e72d07b4dd21aad286413c619fefa1a",
-    "dist/2023-01-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "cc3f1f86997c5ccf5607c8f873c916d1158da76ff971d75e36ed8e3a87c86924",
-    "dist/2023-01-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "f4b7084fc67cf17b3cf1d36136aa03aa5b6af188d311684b15395f05104181f6",
-    "dist/2023-01-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "2ab645d5117606f2c7e8decbeae1d8855ec7ba53051144ba4783efee2c58d91d",
-    "dist/2023-01-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "cfa8baa60cc59ac2750f799d33b06eb399d330f318783907717a9e360fd7d85f",
-    "dist/2023-01-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "bf24570425c064aaef31788bbabd6c4938c9323eca2dedf2ac9084d125623544",
-    "dist/2023-01-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "f5437d81735fa67ef24c7b561d1c720395f5d8d4ddcfd88364717a7ed9b96a7d",
-    "dist/2023-01-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "8e19c3c95d6445e1ef9b1735191f0d0bc33802bcfa138a9d676d9b266adab17c",
-    "dist/2023-01-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7fd91c2ef7e26c08854c91969d167d1c97538d7678c6ed7914eb0f67290d8d5d",
-    "dist/2023-01-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "9e8ada358580b396054278972d532ce2044550071036e9da2eab598e2953a03a",
-    "dist/2023-01-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "eec8b1c24ccaea22eed7708e61bd32bac0850d0dff2b06f1a15a95ab86385363",
-    "dist/2023-01-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "215f1f3bdd8f347af5969c66ff7f7cbf39753ae483e75e689ac581f9d35a64df",
-    "dist/2023-01-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "39460814c429b6a57ce72fafa583d04190053f2c2ce995c8bcb0799ecb7f8bd5",
-    "dist/2023-01-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "6bd08db8702f2fcd9f4cd19a1d977962c84856f748552a96b564e5a77cf2fdfc",
-    "dist/2023-01-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "81d6335fa1265cdf99682503cfb236b914fa17d45f967e456ddbeb12bae2dcbf",
-    "dist/2023-01-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "d36b7517efac2c4a34a1055411f779c386c7a566e4eec408dbc8a319f67f5451",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "1a34ec058cb45189c4062ad2a00ab33387a54716f75005d9959cf0691d06ae50",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "a2fdcb7cc9fe7819699f511d52da0e8ed4e55ba42c63e7b1d61512e4e14e5c29",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "95e3f080394d2e4f9916f17c9cf5137d032da847d9ac1c04519b31177fb1618e",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "c306895982f92c24559b18f8ff9e011e8722c3310e5f70010fd04b0d044c49bb",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "36331cd76f8e918b73ebf6d9095efd0a07cc9f084f194f74c881c14fbc6e8a77",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "2e7caa7209e52a9df17254b17f1930afd5ae973826ce3293f29b8b878aa13042",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "dec92f2c27f785f8ae0db18c2e8a9db87e1ae8addb4302f5cbe9f745cd92c4f2",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "a8fef2e56d9d2be9072c17d75e7ac695eb8fc266fc35e1055fbb25757e6db29d",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "9b5f93f00f61def125436332e4b709bdfe74c441995bae49c0d482f24bd9f8f1",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "4f82313dce2e1315bd0d3ebf95f33bbdf7275c59205b0910bbc92d41c47c7c22",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "69efa04956d9bcf177a3bd9ba9541fa681b39416a1b7dd2b18415b72311897b9",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "0c3c33d744ec05e96298d0bdb9890654ab9ce3e9013b9af14c78683560456820",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "cba8b1f086c544d79aa09ac954374f44d5e7d38ad9bbc2f9e84723d0088592e5",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "ce73d1d03b62931d6eb9508b701e9dacc08b98b484af3daa79ae600c4883a9f4",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "87e1018a3ee4f781b3c1b471fcdf80ebd70096ed58b29db00ad97573626294f4",
-    "dist/2023-01-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "c6896ee319403ebb5c909b13feabc7411e3aa80523ef1bc84c8aae181514c923"
+    "dist/2023-03-07/cargo-beta-aarch64-apple-darwin.tar.gz": "ec2466b2212a7453ae902b85f7b1879fa9d37275f21972aef488e8b4ca04e195",
+    "dist/2023-03-07/cargo-beta-aarch64-apple-darwin.tar.xz": "5eaa63f70f842836dc847059ec188d5c1dbcdaf77116dc08ba6421eb09706c12",
+    "dist/2023-03-07/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "5514aa4051d8c6ff9b7e334a4cbc8b2ad5ad8db0b9853a693ae998888df0070d",
+    "dist/2023-03-07/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "47b4cdc96afb1796e8ddbf4fed4868d08bfc8fe90c5f517f7c4d8539d89ca827",
+    "dist/2023-03-07/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "514ed7e95642daaff551b31af9f6b8e1afd301d4a3197574c4296dd938f7f98d",
+    "dist/2023-03-07/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "0a3f61fc865330e5a9e1f37a59226a6660995ccae8610e742c2ea42a7b8f9b9f",
+    "dist/2023-03-07/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "838c7a9cfdf76e3e2a0e9c2ad37124eb029ea2f0e015640c7c9ca5f45fe1c260",
+    "dist/2023-03-07/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "1ee5a28da6b8f7fc5f98b8214ed2dda28769dc345c9ffc8046ef644f69fd0382",
+    "dist/2023-03-07/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "3ac81e710ff821e206148d998654044d0b3092d929da3a1d3a5ffa2ada00d922",
+    "dist/2023-03-07/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "64891e59a7e8c94011f98849d37a056535966966f753b923ffcf8ceccacfaf03",
+    "dist/2023-03-07/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "fcab9d5fddbe72db02964adf9fcc13e5acc67f0f65bcdd3bc325aa9f0c223acd",
+    "dist/2023-03-07/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "2bfaf117eb512e53c4f01765d198b3647fc0058d7f77721b58cfab5e72b1f7ec",
+    "dist/2023-03-07/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "dd955a4f258603e5cb5c85473fb6bfeace54cbc2345d99dc9d8fa7f984bcd915",
+    "dist/2023-03-07/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7b19dbf54ff04009209d505a97bf66327a87ad6ac8a9be4aa26be3d38fec52db",
+    "dist/2023-03-07/cargo-beta-i686-pc-windows-gnu.tar.gz": "88e8e79c154a34596740b85030c16a27d62defef5db8eefad0b3d4397e7222af",
+    "dist/2023-03-07/cargo-beta-i686-pc-windows-gnu.tar.xz": "a996fac21b8198632a3bb3746549f6a36bd7c2b12d9820b7af64a5ffe8074df5",
+    "dist/2023-03-07/cargo-beta-i686-pc-windows-msvc.tar.gz": "3b8834bf152ecf2bda797475d7d556746e2a1374c61e4ab2ff81b41bbff3a87f",
+    "dist/2023-03-07/cargo-beta-i686-pc-windows-msvc.tar.xz": "2fee05bf93a16004f4f8fde437918a44874a9495c1e45d954a1098c104249bd2",
+    "dist/2023-03-07/cargo-beta-i686-unknown-linux-gnu.tar.gz": "544ce4096e455c5259c4577feddaf5a6ec34e6a8bec2710e74f8910f60c1da1a",
+    "dist/2023-03-07/cargo-beta-i686-unknown-linux-gnu.tar.xz": "2f39706fa21cb08d8bfe6a32a5a3314742ddf040bb42e844d5b3f8d0d29fd39f",
+    "dist/2023-03-07/cargo-beta-mips-unknown-linux-gnu.tar.gz": "7f60d7a0d60e06fb4530291f1e64956cfc7c92bd034b63d1ebdedbeb9f7bca17",
+    "dist/2023-03-07/cargo-beta-mips-unknown-linux-gnu.tar.xz": "3c6d8de9f254edd01461235f14e89c7b863da84f338e3a842921dc092db4d82a",
+    "dist/2023-03-07/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "2c0ef292ecd4bf27e74323ae5fa7bd6c6395d70f4adc4e6d4228c266fb87be7d",
+    "dist/2023-03-07/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "1886d8e978dddefff73f758e7c1d28964209dc986195cd39bd8d3d34197cde52",
+    "dist/2023-03-07/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "125a9a8a6d57f1694ed5bef51d9d351da3bbf0ff1ac631641cc5046098385536",
+    "dist/2023-03-07/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "851654268ac5ce9d1f3dae9228464bef01771244945653ff7e9f8d7a52761813",
+    "dist/2023-03-07/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "46a3bd35af46f6b59b610bbc596233bb428c2b8387f95d3e308565d57e6ca276",
+    "dist/2023-03-07/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "d941bb502be268962400e78005b30ac4a5975ab012e2cb7fb631b002a7e116ec",
+    "dist/2023-03-07/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "3853bfc5c0734f3f92e0d7cd07583729d3e67f7ec3b496b5349ac690ee3632e5",
+    "dist/2023-03-07/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "17a0c76f33244ca66c942cd6054e343a395d27437d69f166471f0aee8c404a55",
+    "dist/2023-03-07/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "b37f9c476ae9fe802bdb0fc449657c90a567033f4df382befeee1517f53db05a",
+    "dist/2023-03-07/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "b315d765b176f90a5c74c102687ea8b54ea94d5a772ad03741aa3297a5466562",
+    "dist/2023-03-07/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "e84ef7a7b4fb7b504e6a0ae335432430ad9f4db356650c738e0db676ce672321",
+    "dist/2023-03-07/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "3b830e1077a195e2048b621a1ace2c0470135ae5821f83113a16bdd449dc9828",
+    "dist/2023-03-07/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "db373e61134b7f9340b5d8dfa24fb989e3acadb90b4d27008c08715720cfeba5",
+    "dist/2023-03-07/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bb7d046253f1fcf98f8ef9b33820793579a09d201ae1bb5616302bcf7103453f",
+    "dist/2023-03-07/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "495c5d11852010647d15d54352052ca932034d77f3ac3bd9bf605d52c37fb47a",
+    "dist/2023-03-07/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "002d9a037a9de13d0e99f695bbb8f9177e14df2e6309917a7d728023dcaa1640",
+    "dist/2023-03-07/cargo-beta-x86_64-apple-darwin.tar.gz": "9c93e76966a317d2dbb673345c33269b67d6db101114275424a50f5e4c3b7a89",
+    "dist/2023-03-07/cargo-beta-x86_64-apple-darwin.tar.xz": "0ac70e1699e2684fcaff30d4330d04795f3f9579226dc1dd0ecefaed9efa24de",
+    "dist/2023-03-07/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "8ad0af38dac9c0a49d73691d7f62487c8c72a378ff4fbb7f380fd106600ce836",
+    "dist/2023-03-07/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "e1c263909d66c14d5b835d2d8ba9df9d1f54750a85b79c4163483126594f71fc",
+    "dist/2023-03-07/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "684b44e6cb7b2ea6feb8a5f768f138b7c3c3819ba5f146461ffa860e4ba2ee0d",
+    "dist/2023-03-07/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "194037a4e7a035becdf8540532625e7a3d2e5e9a75c093713467d16f2c630fda",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-freebsd.tar.gz": "b19ed2a67bc6d654520c2ceda0d1a8e0128a0d042a72cb6506eaf975c3665bc1",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-freebsd.tar.xz": "2773155eb716d1cde85c8ee7fe87f534decf08cb92d4812463a8f5f45b5cf4b9",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-illumos.tar.gz": "3d97d07c075c7473645b71391fdecb6b8a43af42f15ccce0bc13146624f3d9e7",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-illumos.tar.xz": "6266332b1a18e851cd4cf618c1ba5a8162c06c8ceffa3a6e619cbfaf5c8f2914",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "6e0ca0e10d1243e81768f1760f268aa2ce1dcf4f79a718a44e09b92ae5b2c87a",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "84aa0a73dd6d3ab9d5efb10e0480dedb864341124c19b35040239af27fcd8651",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "6de4590228b94c6c62fec90da7f5579fef16cddd30d4bad29ac39e40081818be",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "317b64417648885b08064543e0dea13d1062e682224b3b866c12ac6abeda1648",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-netbsd.tar.gz": "aad64656cc4b9915bfe5ac780ac935964a13481a9070ca31f58d5b8c1750e40b",
+    "dist/2023-03-07/cargo-beta-x86_64-unknown-netbsd.tar.xz": "0ba3f47a551b38c83106003c775539b7384c9bbfa4cae28923e63e28a32227da",
+    "dist/2023-03-07/rust-std-beta-aarch64-apple-darwin.tar.gz": "b3f00164840826f89eb930445cac0afa2ebda2153195574b91ff4dcd286042c1",
+    "dist/2023-03-07/rust-std-beta-aarch64-apple-darwin.tar.xz": "c94d3fe8dfaf35f88d557a37e3aa1da8999b5e2e022f85f1bc0ae7ed5218a3ef",
+    "dist/2023-03-07/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "3f43a002c0c099eedf12c2d2d3e1bee3c8ea345368e89cedd5918705f37086d5",
+    "dist/2023-03-07/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "891547f5c2d06ef95f272f829438b0d5c9f34d9e1e7d068dbb0a5d31c685658c",
+    "dist/2023-03-07/rust-std-beta-aarch64-apple-ios.tar.gz": "c1fe0f8fb661dec65dd7a13b038deae93d4b66f0e0988a0a72374e9945915612",
+    "dist/2023-03-07/rust-std-beta-aarch64-apple-ios.tar.xz": "1f65f0ae9685aaf14805b63111ddae27c8e9b39cc88cb3a5347ad9e93d863581",
+    "dist/2023-03-07/rust-std-beta-aarch64-linux-android.tar.gz": "9fc988f57fb6a0530a338cd3a0a87925b095e9a2f3887f87231c9414828241c5",
+    "dist/2023-03-07/rust-std-beta-aarch64-linux-android.tar.xz": "2aab2cc1377391588db019a231d8f989de79342a630625a4e7c2fee560549668",
+    "dist/2023-03-07/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "4527b7439a0419e96b8c59735fbe98d8628985b63ce64c24749273b625012c39",
+    "dist/2023-03-07/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "80badae3069223541e3092b07331eab3330bd66a21522037fece15314085c513",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "6f7141d28b549d6cf6f64a5944a4748db730d865a9bb1f3a344cd19cd45269d1",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "87f97fad69b53a36354c17abfa58edbaaf86d1db071a53fa96e9822c4f0a7846",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "8decda618f8cf30f51b8f26861baab0f53824af6cfa965af585f0653771d113a",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "dd140223ec842ebe4c69ec6aa2966b97dacdd9ce112490e310f374134188d0c4",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "4aa6ad6fbfb9bea40c5b4c3fdae8f79feeaeca71f0848c1e9281650d4b5880e5",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "2d62f25f3c16704f2f52b8bf2fb505b5f8e3a3e44ae3971b0a3081fdd5932bc3",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "87982e6e6e3865d520fa35994948c7b82c4fc9f698b4e1316e0ab0bbff3d7455",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "815a45384be320225b438be952d798ddcbfc223d7629ce8e106499f626c170f7",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-none.tar.gz": "041d4a16c7e6ea18f76b119e069630636716c5f7c2f38e0fdfe69062da9cd942",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-none.tar.xz": "227e8434ac0f294bdb102d4aad6c6b1425f148f2bf8eac9473f522e4e8851d15",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-uefi.tar.gz": "a1f6c1268c3e28e78f43f2a922ff2d260466f4e2888555c122fb490ba28d8f53",
+    "dist/2023-03-07/rust-std-beta-aarch64-unknown-uefi.tar.xz": "68f46477d721677d2faf0091aad1d2f72387bdf1e5590dead06eec51390e9906",
+    "dist/2023-03-07/rust-std-beta-arm-linux-androideabi.tar.gz": "d1bdca54a9807d058a26f2999fc82ae474e6d5f8cb555196f6583130c81bd6ee",
+    "dist/2023-03-07/rust-std-beta-arm-linux-androideabi.tar.xz": "8cc49d1e16181848d73d617914d664b45cc42fc8bf80d3bca7ca69fe1a4fe7ee",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "b09c3776268888966d3752dc614e677c821731593ef757ce45fcd6f6b1b28bdf",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "7d43314c408514ece5f3ab6929f906bb224336171c3fe41a5b980afedfbeb172",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "9493fb7c2cf30e0c986babd8ec41e3c626373d4e62f8558dacd01cfb85dec04a",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "9c833f219410f9e6e77451e4af1a355685831dbeaa99006ac814801883a17312",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "8e9c3045dbf1fba7e54b8d34bbc3ed8a95b6c984ebee0123690889455d963f87",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "54f7f9a2baf29a5fbc41b6624a4ae0f056e10f0dbfffffcd08377dc6888ca85f",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "3f214ab1da499c6a64bc5bc54fb9e95becb318b469531e4d9f7b234f5456dcff",
+    "dist/2023-03-07/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "3e4c0742356393a07cbcc6502e1d1f9a3187921c67d4d554bc3c95bb9e4e226f",
+    "dist/2023-03-07/rust-std-beta-armebv7r-none-eabi.tar.gz": "25f7466a419353fd7e4c9a3771df8f0a64e689d3c38f18e297a6a2c670174d9b",
+    "dist/2023-03-07/rust-std-beta-armebv7r-none-eabi.tar.xz": "42c713261708e90fcab6dd2b8d5b2df4387a33c829bc981f502622d5ca352ac4",
+    "dist/2023-03-07/rust-std-beta-armebv7r-none-eabihf.tar.gz": "31b240296f2e72dbeb3facf395486e8f8ac0b0b5f10a389ed4e6dd803821afac",
+    "dist/2023-03-07/rust-std-beta-armebv7r-none-eabihf.tar.xz": "c33a7bb47b94f8d5c716e4d6b43bf17395bbe9611762a01a5763dda4e725c64d",
+    "dist/2023-03-07/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "509cdcdc107051d7cbc8f02874445a9cb2f0dcd3190cfabd68615b8883b8f32e",
+    "dist/2023-03-07/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "01fb58ffd2cb6257f25d290cbd25be8bf216c18ccbfd97a42317d9e442008d4c",
+    "dist/2023-03-07/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "19ada8a7b1178056008f3168dd854994d6dc0fd32facebef915891b5a7fe83ae",
+    "dist/2023-03-07/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "5925328b29a9a54536ea7de55442f4bcacce4b2ec01c69e7c8d5e7f109f5dcab",
+    "dist/2023-03-07/rust-std-beta-armv7-linux-androideabi.tar.gz": "bd569b576ad68f20d0352e5ae9a7ea0008941f879dcf1cd57f14b7eb7fddb95f",
+    "dist/2023-03-07/rust-std-beta-armv7-linux-androideabi.tar.xz": "c483223f7abed0c145b9c94a6630a1d4caf26720cd451cb4b70971f1f907d6cc",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "84a1ea166b81fe2cc673beac5831ee182a303c5166279af33478a730a1987086",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "fa04a59350792a59c8b62800002f5f6e013710d96e3e9d3a6787b1c3b668569c",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "a605160aeef9a5d60bb83376d816112c621f753e4f16907481aeeea27568da77",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "d6f3e091217d657a259f7392acf26aa7cc2a7692028412bb97cd26cb7f31b34a",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "ce179ad977098491c2dd27d57d7dc5a71b9b450b07d36c19e55c0cf9961d3888",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "fdfa1b894ef5d1afe7cf9790de3077632d4fe693464d19ede5d6b377ff09a73d",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "673dae7f6d71cf984b69e0bf22b8f50a8597d5c6304ac0fc613ad5116c4a8fa7",
+    "dist/2023-03-07/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "9bd8bd07be4488f6828ce4b5456bcfe49bd9ae416cbb859c9b1460334ac9f4fa",
+    "dist/2023-03-07/rust-std-beta-armv7a-none-eabi.tar.gz": "b571a28b02107adc227fe02878064f44e5d23bcc91b530f57b4dfa43a4c3ec1c",
+    "dist/2023-03-07/rust-std-beta-armv7a-none-eabi.tar.xz": "854433b082a6bad442c1b9cc9708357b779cbcb84de65f832cfcba06a6088157",
+    "dist/2023-03-07/rust-std-beta-armv7r-none-eabi.tar.gz": "04c1479778038948f30d2fa87a18562939569422fe57e91659f9f0a5e8ca7f5a",
+    "dist/2023-03-07/rust-std-beta-armv7r-none-eabi.tar.xz": "38d52dc26074ebd93e6a61dbb0c934a66f32dd1113cdd9d32e4d5829ce62e188",
+    "dist/2023-03-07/rust-std-beta-armv7r-none-eabihf.tar.gz": "14e4707dc514aec378e1aae2949231ee3bbe216164a794e7e6d233db54f13459",
+    "dist/2023-03-07/rust-std-beta-armv7r-none-eabihf.tar.xz": "c0bf08f5d378955ba15441b5229d1ef202e6d071a243ae7fb34b9f1724fd90cf",
+    "dist/2023-03-07/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "d9468e5a056478482cb9a85a63aba6d1987026275ed0c8ef64fe7a84ee5e35f6",
+    "dist/2023-03-07/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "77262a746f577b0e6f9b6c1aa338f90eeaf8221ad70f5ca93500459c1749f3b3",
+    "dist/2023-03-07/rust-std-beta-i586-pc-windows-msvc.tar.gz": "2c8c95b80e43acb921674d4a9b2986d89dc008e5977a6a05e820adfd385f55ca",
+    "dist/2023-03-07/rust-std-beta-i586-pc-windows-msvc.tar.xz": "9573dbb30fd7a24d4d7e831f51e6c05c76d856d545ce4601f4e91b784c348355",
+    "dist/2023-03-07/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "f1861d5b7875a81a11a98a6cde90fe958d1819517de21e377cd05b58eb5dde27",
+    "dist/2023-03-07/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "f8e816f9ca02c3cc515d07d5b5cecc8c5dcee64b8deb1bc1ab249010664d1cef",
+    "dist/2023-03-07/rust-std-beta-i586-unknown-linux-musl.tar.gz": "614a80336890ab422366caf16c73c26a7982c2369393a40633eb925113e93306",
+    "dist/2023-03-07/rust-std-beta-i586-unknown-linux-musl.tar.xz": "e8dbf05a3964ce39dc4c732c5a4bce60cea1764c151b1ed4333e0da858659050",
+    "dist/2023-03-07/rust-std-beta-i686-linux-android.tar.gz": "34df9ba98cbb7fef8624e921045110d0b4623028a611f5819bc79aef9e611024",
+    "dist/2023-03-07/rust-std-beta-i686-linux-android.tar.xz": "bef0d789d8d66d0eb69970ee23e4cc966f655efde901db13a4fc9d02c875848f",
+    "dist/2023-03-07/rust-std-beta-i686-pc-windows-gnu.tar.gz": "c86ba5a55d449af72a4450566a9152edac5fb43ab03d1385779bb4ab62255f7e",
+    "dist/2023-03-07/rust-std-beta-i686-pc-windows-gnu.tar.xz": "8dfab1eb07c9391be73cdefd892f6d7ca72be99a7fda5528906343108c5b5503",
+    "dist/2023-03-07/rust-std-beta-i686-pc-windows-msvc.tar.gz": "99c56608131dbab4775a35ea16d50149af37ea57ef0c0dd52bec2639dc3bfce6",
+    "dist/2023-03-07/rust-std-beta-i686-pc-windows-msvc.tar.xz": "1983fae15ae3e5480efb1cbd0fd0509e863eecdc456e50899bdc6cfc2da580c1",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-freebsd.tar.gz": "4652d56693b3432446ebeb5b52399b27d95066c0085a24a4ff5b96a2116cef95",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-freebsd.tar.xz": "a89a970a699864eda563170f41210ae3692059f8b141d532172907ca1456e8a4",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "0d6b69445aa064ad6c53a26b52011b4533e83c7398a9ff4a10c29bd2c5f1673a",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "4cd1770586a92192da3aa4fa8a846412db8377fe04ce5502792c67d8d3bf9278",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-linux-musl.tar.gz": "b7c0385692fb7218dc16e3935b6181beeaea1adb731a5ca2dc876a3fa825dfbd",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-linux-musl.tar.xz": "92c608fd3be1bf98ce343f4b42e187fa1182560bfe10a2c3110037b0600f611c",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-uefi.tar.gz": "97703dfc96fadd27af79faec3b9b14f5e64549870c5451e8ca5023dc97a7253a",
+    "dist/2023-03-07/rust-std-beta-i686-unknown-uefi.tar.xz": "7470fc83530b83ad3bae30e7185ca54811f97629ef64b70d3fc2fb757639abf7",
+    "dist/2023-03-07/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "54f2ff0de486ab6e6ed6dae72d798e1fcd4653b7df1f8d4127eb6a6396572081",
+    "dist/2023-03-07/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "fb3c1a6daec2ae77de369ef6bd93955d67e70b7b2799a286d2332f5b7d46b715",
+    "dist/2023-03-07/rust-std-beta-mips-unknown-linux-musl.tar.gz": "4af2c66e9e2b3d4003a47aa638177b256db683f7945fd4cf02122c144736045d",
+    "dist/2023-03-07/rust-std-beta-mips-unknown-linux-musl.tar.xz": "8f3f4385b4a6fb9f8cbeec20b7f7b794d1374221bcab5c2a5aa59d94acdd6855",
+    "dist/2023-03-07/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "ae14ec5c0ea8629de6b8db2a83a4ceb08be6475a07c89abbd8697f72f9d46427",
+    "dist/2023-03-07/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "e2ddff933278d45c9e2d4e6734babd3b6a1e104325d814c8faecc4a51d197a96",
+    "dist/2023-03-07/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "d67f7fdfbffcdb4daf134209ae62c051959ef5b450ce12f6ff87b5d7f2d69c7f",
+    "dist/2023-03-07/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "f5ecb43d0445a03d4677b3a8997f899938755c877bad2262dd88f1c5b2960c1b",
+    "dist/2023-03-07/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "9a9b36ce50e1167259c43d5dd8669ca26831bf7d2df6162395df6f22b3c3b7cf",
+    "dist/2023-03-07/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "966d074243e8bdbacbe85fbeae546d9d65b3579015abf18a458798f16ad6c940",
+    "dist/2023-03-07/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "a64b67a50418e8ced6333075541a30f7272fe11f11160969c92efad447c94ebe",
+    "dist/2023-03-07/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "f2fee3ae76bb483871b23a4ec1cc22cd89193e087d5389362385d21ddd162392",
+    "dist/2023-03-07/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "f659bb468e1e4a44288953e654808452f1b08bc7acef546b72e0b31fb3552503",
+    "dist/2023-03-07/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "7be5f817c2cca408804be8f0168e60a407d6088b3758688d2e8a79662b26b340",
+    "dist/2023-03-07/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "2c988d57deb6d9f88a6ff4180b41a65bd2a69722b6d3dd7a80ecc3bfc1ebda0b",
+    "dist/2023-03-07/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "8e852cb52c7189a5de0274bc592a720ab1d657f39dd689aea0c11cc8d45b7441",
+    "dist/2023-03-07/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "24db414fdf589e5c686e0c1441b061d82b480a305cf7926d7a54f3ce6bcc48da",
+    "dist/2023-03-07/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "f4a90b86b5cfd448c5b7c1b29b99c0f016d64deeee7bfb98048d8b0215f15174",
+    "dist/2023-03-07/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "9c04535d6ad8a823e94e98e3d8aa300ae7181501dfb9819ddbe072ffefe2df98",
+    "dist/2023-03-07/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "121faf0e67f1fbf609b6f2746c343b2a7fb7efaf0a7129a9d867e8d8c52d5816",
+    "dist/2023-03-07/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "013b5968c15c7257932ea79c8df23dafdc20606a4dd6e7b7f784d56d59831835",
+    "dist/2023-03-07/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "26abe47cc533337847c021c08fcb88ec77152b5a33500ab948fc45c8bdab23ee",
+    "dist/2023-03-07/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c72d7e9f58640933bbe5dc1cd7b0ba87f5080ed397099d04cacad992a989199a",
+    "dist/2023-03-07/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "4ef96cf7f4ad93c41b69e9f6a48937cdfb307d7ec65ab2f475707680f638848a",
+    "dist/2023-03-07/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "b4d5fabcc593313b41bbe1a4a201d2acd23f07ce249b6414bb5fb940df519d90",
+    "dist/2023-03-07/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "537d209c9ea5a7d7750206612b353d33d54a5c55af45c4e8e4f113c6d561cd5b",
+    "dist/2023-03-07/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "8307dd2783e0ccefb27cd645ab53717c851e91c5c5a2e466bc2ebe00f23afeef",
+    "dist/2023-03-07/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "f2bb8932f9d2a0e51caf64367bb34d1c30456863d3933c766c69be50c0474ff5",
+    "dist/2023-03-07/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "300892f31875cbca564b54124e85fada8af945247c3a31049e6000494f3a633f",
+    "dist/2023-03-07/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "ebeb2d2bdace58faca8f5d8d3e06581c30f18ac7e0e096d03fd4444a7ca9b7b4",
+    "dist/2023-03-07/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "62d9e27a3c321bed86839ce6a492e28aa51b1d70bd1b0ff0d6cf8784ee78c8de",
+    "dist/2023-03-07/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c876705073fa8735fb3b89453a4cb00c3324d3e8ee570acf3bab21ab0ec0d240",
+    "dist/2023-03-07/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "97751b6d399463e9dbdae41979d0e6405d0faf90ee859d2bb87787a4146420e4",
+    "dist/2023-03-07/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "cde9469f915b2f37537da5a596ab75eeeff64affd5f26619cd59dab06c03b13a",
+    "dist/2023-03-07/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "000796b94967c2285fa240542063743d389595aa64a58a64145ca093ae505222",
+    "dist/2023-03-07/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "3ce3f15333e074060c6fc97f40bc2d41d582744df97c1e4630839a34397e793e",
+    "dist/2023-03-07/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "8a44c200db94509b83ea2bcf3b5ca7b8ff1f3c7aa0c9b7942ee3047b619aa161",
+    "dist/2023-03-07/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "6484f92b2d2793c47f1665d4c0bb93fe64359a3cafb658957bd3ffa33c3753b2",
+    "dist/2023-03-07/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "d60be45093cbbd1269be0dc0e73ccded00a9b72b65fde8c8c5fb72d79cdcdcf9",
+    "dist/2023-03-07/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "8b46c3bb7a74116d8dfa69fa46cc70b4771c6a28d73c501bc935573e1d06cd20",
+    "dist/2023-03-07/rust-std-beta-sparcv9-sun-solaris.tar.gz": "5caf2b9c9dd509ef50840484b577b6ddac2cda32519b75a97053de85340439df",
+    "dist/2023-03-07/rust-std-beta-sparcv9-sun-solaris.tar.xz": "bc00a55394520283826011467d9f27c74369d47e3d5bd0f9c7b7cc2f2cf74cac",
+    "dist/2023-03-07/rust-std-beta-thumbv6m-none-eabi.tar.gz": "38ab6ccd205e1ae9c7599482927bfe42096ad02cef8660bc9aae345b1081e723",
+    "dist/2023-03-07/rust-std-beta-thumbv6m-none-eabi.tar.xz": "7d605918c0bf111a02fec102de688bee0f2f18e3583c004571710421741224f8",
+    "dist/2023-03-07/rust-std-beta-thumbv7em-none-eabi.tar.gz": "cc7b6933e5f16bc828b446289c561d9810a977a322bdd9e406fa9c5b3e3e925f",
+    "dist/2023-03-07/rust-std-beta-thumbv7em-none-eabi.tar.xz": "d42fffb2fb88bac3090a9d99bfb91405f9bac5b09b88b286f74a85deb31adb2d",
+    "dist/2023-03-07/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "63619f93d1047979d90cc37f6903d4d34c28c793f5d07d448b8f818049c0694c",
+    "dist/2023-03-07/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "3f9735ea8a2b340803e95d55bbd1d510b501e4cd5844a9334ee9cda5733f17cf",
+    "dist/2023-03-07/rust-std-beta-thumbv7m-none-eabi.tar.gz": "73581e242b9f002eb36dcf05594859419cbe77393a8b21e8e1f447aaad05b0d0",
+    "dist/2023-03-07/rust-std-beta-thumbv7m-none-eabi.tar.xz": "f582f14891696a51458b3fea2db8ad883012aab40a5d8cfe97b420d0ad7ab901",
+    "dist/2023-03-07/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "5036157df192a76a3bc5084e9c4e53d9151871c1bd86851c361a08d09779cb0e",
+    "dist/2023-03-07/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "6b85161caf4a45bdaff3f5428fc41b7bc81a216484c755b7cab297a4914b7c7f",
+    "dist/2023-03-07/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "b749800ef87d357cc010ba46305d6603a40f7c52be3c1778e6a88a2956b89bc2",
+    "dist/2023-03-07/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "622dcf6bfae396ddf89dd0935a3269cc4f86f5ccc7c83982a75b915600f19733",
+    "dist/2023-03-07/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "7ec9e547fc95900efd3f04cb6f76213be5da762d997c85e8ea8434cbc0c0eebd",
+    "dist/2023-03-07/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "358fca90a80aeefdcd829aa6d3a027d81ceec010cc42aef971285c7d31699fd6",
+    "dist/2023-03-07/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "4d87df24f8c466cf2193eec458ce4033926088004d88b3ec4b9c74ed1d137a8a",
+    "dist/2023-03-07/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "65ded045c0615432a6017524c24da2e66b3ecd83e8869e382a00f2407fd06441",
+    "dist/2023-03-07/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "f8e081253423ac6fb29d502267e8fc22a3409965bebdd331dd00420ba609511c",
+    "dist/2023-03-07/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "c69a893777fc2acc407832752ea51d4bad5c4741c4a256172e4ebddeb5f939a7",
+    "dist/2023-03-07/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "28a8d21a98af1f950bb3f62d6fd124bc2fab0c0c27a419c1fcc1a84d31191b8c",
+    "dist/2023-03-07/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "b0a774faa4acdbff7d7581617da76e759e073a8d75b435373d9737c4300a178b",
+    "dist/2023-03-07/rust-std-beta-wasm32-unknown-unknown.tar.gz": "2a785745d3129a25441572d221a30d4108a35abf3bd73a387a5d65a5df82ff18",
+    "dist/2023-03-07/rust-std-beta-wasm32-unknown-unknown.tar.xz": "b5a50098ad047748644c7f510cb2682c52499d12f02a1e94c59a4f904c8002e6",
+    "dist/2023-03-07/rust-std-beta-wasm32-wasi.tar.gz": "265fa8b315a5d39a35fb8d32d5e46c3c66f9608992a3d708ac90437818cfed45",
+    "dist/2023-03-07/rust-std-beta-wasm32-wasi.tar.xz": "26839f3ed020dbda8ba893492cf504d565e7e1af7cfec5ad76053443d1022839",
+    "dist/2023-03-07/rust-std-beta-x86_64-apple-darwin.tar.gz": "8322910f96d5e206fc3ad237b4cf456e9fc2be0cbb00a57bfc2625126fe84d12",
+    "dist/2023-03-07/rust-std-beta-x86_64-apple-darwin.tar.xz": "3b1d0288890649121ed4487ec6ef5986913bcad5d224e8fed6feb5fcf56a3b2c",
+    "dist/2023-03-07/rust-std-beta-x86_64-apple-ios.tar.gz": "ea0a805d90b4b18c0b525faf4eedd2827d1f009d3c7a5cdc084db60c54e86d72",
+    "dist/2023-03-07/rust-std-beta-x86_64-apple-ios.tar.xz": "86bbc9cb184cb3c18a0afa1b982e951ee1e2569fca23ae7f85efd29f26e21983",
+    "dist/2023-03-07/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "f6bab7e24104f142c62f6d12585725bca24496d45888b22b07d2cc50f2f7f11a",
+    "dist/2023-03-07/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "20a1ae7636cc1dd9daec73818ecba60c60162d2a016822f1d3e828f55fc4ef9a",
+    "dist/2023-03-07/rust-std-beta-x86_64-linux-android.tar.gz": "78e7cae3d09a115fdd447bac210a78595076c37287b6dc142f9c363d207e16f5",
+    "dist/2023-03-07/rust-std-beta-x86_64-linux-android.tar.xz": "f37fcdc813462bcd94b0a06e38e665da9e5c1b5704cd029a23498c003a0df0a2",
+    "dist/2023-03-07/rust-std-beta-x86_64-pc-solaris.tar.gz": "afb0facbc35bc80c9f23ba59b9367c95b907c944aa5e1eff0fcf9687ca1089cb",
+    "dist/2023-03-07/rust-std-beta-x86_64-pc-solaris.tar.xz": "c771fd343a9a2073a8170730936153698d94aed87aa15b52a04075a6bfedd4ba",
+    "dist/2023-03-07/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "c753b3450a584ec7614e20fe308653c2451cc1910de76da663ee5c53a451004b",
+    "dist/2023-03-07/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "0d072a92ee2d33dd6b6122d273ba8cdbbc7dbc4cf090ca7abbe08fbfb16d5f86",
+    "dist/2023-03-07/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "de23d40c1aefa660f1411bb0c17da4f16b093244c0d515861b0866aed1e06b07",
+    "dist/2023-03-07/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "6f7b6070ae06074f338fc9eae327bf219389b5f88ee7ae07eb1e290d277b0f8f",
+    "dist/2023-03-07/rust-std-beta-x86_64-sun-solaris.tar.gz": "f2d68b5119525110c29dbd19a747f3ad632f45facee5c437e6796a2a213c52d3",
+    "dist/2023-03-07/rust-std-beta-x86_64-sun-solaris.tar.xz": "2da196278cc5a2eba2400d5d2b13fe74b65e9daefda0a6231684baaf76982147",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "c922f51ac5c80630d9cf2b1a0f770bcd1c1d74180a716b9852d37a6621035c38",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "b6ae7c3cd80b12537d0802444be97acf9be5072c058d025ced07398b0651f45c",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "2fa8a0fcba9ecd4ac6c47b22091a4f58708f96197f95dcc8075e80a4256fdb0e",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "025575e750bc2e1b43e7bf288a87059c96629d0d7290a57cfd0e31f2d0efb9aa",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-illumos.tar.gz": "8cfc61094c5ea8eec46131c17deaa8dfaa900f75300b996abd167f527defbb3f",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-illumos.tar.xz": "2e7c57376dbf890dc7d6bb7a0b555ee791b147aea4924882a3a94f9b75347f43",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "4840a693353f759d2d9e3fa40df97f200f27106159a9b126698a6ce07c3a117c",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "9a13a8c8e16028d0e07608da8fbd0ea5b51d9d425230712adcbac679ef5fef9d",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "0ac015df12c5212ac61b5a691d982a4fd64a8f77653b3d41e47da974abecda9f",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "bc12d3599f60a5860a15958ea7d4dc537d64802a23bc75e37a7381d875d3de2d",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "10ae35f994f504db3f58f098e8af9bc15f0c8e878b0af8487b6975846dcaf5ee",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "6d46f12168472f6a82980987d02b7e646a0814219c809ce04c352048be0a2981",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "978d7e3df8d6a16af9461eed0fdf79745c8a3ac91dc7e53ac4670e1991916e59",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "f936f6d186df0efcbf1655e7d2436bdebf5cd56ff811802c9ff753f20f38579e",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-none.tar.gz": "9c76650dd06c6d679716e4215259720ff5abed7731621617b9a785bb1c1f3c88",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-none.tar.xz": "4ec0d0b2dc4d163db2967df2f16dfd822adba2d85e85fcb21984c84377b4a5c2",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-redox.tar.gz": "701342db468d8bd5c08b962adf3b2c34d83a10fe81936d3b91937b5667e3f5e9",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-redox.tar.xz": "1c32cbb84bf8f967de3fe71e63c3c0d28c799276d9c2b5f2b3afbe87e57f026a",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-uefi.tar.gz": "51492e36780f026b1485d2c0394bc232d8825f3317fd438b1f8eaf9b8d50712e",
+    "dist/2023-03-07/rust-std-beta-x86_64-unknown-uefi.tar.xz": "33e46267265e9ec7394932b197c598d48147a119bd7346614714590181c84884",
+    "dist/2023-03-07/rustc-beta-aarch64-apple-darwin.tar.gz": "16927a64c3e0737274ebe4c8e6423977d5f2d684751f678fd2dc5c6a6020ab4b",
+    "dist/2023-03-07/rustc-beta-aarch64-apple-darwin.tar.xz": "66f758933129e0b1856b477f364e04187316227b4853aee8a5f95f6c7ad60fac",
+    "dist/2023-03-07/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "10a7cd771929aee13937bab01ad1e6d19998cc4ef58816ad8306539140fe3dfc",
+    "dist/2023-03-07/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "1d9ce8c7728b1831ce564df9a8ee9502ddcfd83c764d0f8c5b941a9beb570fb9",
+    "dist/2023-03-07/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d75924fdcaa76b064d018e612457a4f960536c51767f46fe20d5e90d41424d45",
+    "dist/2023-03-07/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "1956f0965e3065a5901f935c42b10e07783ca33a2a8b6f182a5104edc4d73a01",
+    "dist/2023-03-07/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "40fbf2a72485dadf04eaf2a128f631c02542cb53f0d2b2c26369e8b8ee08463a",
+    "dist/2023-03-07/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "cb7f9812a09ec7397ccb67f36484ce22425446940b65cdc4c72e823a6fab5ec1",
+    "dist/2023-03-07/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "bc95e80e02e822913eadf5319253e7422615468db1c9627d394992319c3e4d5d",
+    "dist/2023-03-07/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "5b089b4b531cbd43909518093f6cfb1e5d4df138ede86ef7cc0e0e1053a43452",
+    "dist/2023-03-07/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "030d2ec4494c9139966cbb833c1616a78b973f10409defbb39f936652ef97449",
+    "dist/2023-03-07/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "2b2a728780b1bd30ec0cbcf014cb8914ed423a46a97f330c23b7386d8aec2ab7",
+    "dist/2023-03-07/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "2406baa5db6a46e51c79201fde893089ad16f31a17b117509774ee76f16bcdad",
+    "dist/2023-03-07/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "d121bf988fe4225d1cee4b452a0d5aa1620c990456dd9002c0af179802dc33c8",
+    "dist/2023-03-07/rustc-beta-i686-pc-windows-gnu.tar.gz": "eb5d4ae35799c3ddacc77e946b9fe8c1ba88f193c14c58ff23ee7ad89bdc6d9d",
+    "dist/2023-03-07/rustc-beta-i686-pc-windows-gnu.tar.xz": "1aeb85967f6de2267024abab0bb46dec4ce3bd06e687af39745cb556c37a82fb",
+    "dist/2023-03-07/rustc-beta-i686-pc-windows-msvc.tar.gz": "be2b29bd8ac4214eb5dff5f51c30cabfe859bc02b994c87cb139af50889abced",
+    "dist/2023-03-07/rustc-beta-i686-pc-windows-msvc.tar.xz": "1c097877d03021b975f2968bda73301a541b7989eb217537ffa3ae079e576c5e",
+    "dist/2023-03-07/rustc-beta-i686-unknown-linux-gnu.tar.gz": "3066f0d3b0e0319c8e9bfcc2215bb16729611563cedb976de0356a050ea68357",
+    "dist/2023-03-07/rustc-beta-i686-unknown-linux-gnu.tar.xz": "3908a8675f8b5743ce407e12cd0a32f0144db9b38bb49f05c47e855973d1e8c8",
+    "dist/2023-03-07/rustc-beta-mips-unknown-linux-gnu.tar.gz": "7aad6a6e37fb7f4fe835c2bbe7d1deb36ef973b7c94f3969b003812f87a92ff0",
+    "dist/2023-03-07/rustc-beta-mips-unknown-linux-gnu.tar.xz": "29e434023a1d94aaa5003723e2bcd31588d674f2ae243109e34f8e88e141c58c",
+    "dist/2023-03-07/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "4b2e92cd5a01df031060d03d088829056039951ce8b7edd9549944a6f567e07e",
+    "dist/2023-03-07/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "7e82c3f1a6d5175e452abd4f321469063cb2007f9f33cb3302a5745f985aefb5",
+    "dist/2023-03-07/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "b9fb2eb2f43b7479efb227964141f3beb29db829f449830ee41ac83280366ac7",
+    "dist/2023-03-07/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "c4eedd1aa5ac1532387a3091525d9d94fa7979002e0399b351bdd8d3bd064475",
+    "dist/2023-03-07/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "03685364b7750002a9a88717170c4330052c0838de82727734ebcb2d8b0466bc",
+    "dist/2023-03-07/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "13834ad521e7a3439c56dac58a548f816a60cc2b4f0d25952fb610b0245cd141",
+    "dist/2023-03-07/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "840a15c851f96e9b6b662d0b39c947b922e54195b07822ab6b1e13d5c8206a32",
+    "dist/2023-03-07/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "5721cb8347f4e9e546a59cec5c89ff548a2dbe867e27107678da6862a435781f",
+    "dist/2023-03-07/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "bb0c56acb9bb9940e970f23649f0d41338950f2e1c97cbca5e2de673069dca54",
+    "dist/2023-03-07/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "89c102653c6d4f562ad32fbc2d1b82ef38917528a7da6a3219f7b232dac62fcd",
+    "dist/2023-03-07/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "7ca86f54a307ec8e4751a58d541745c900813ef9b355ba21442629ef6d965ea1",
+    "dist/2023-03-07/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "c88a9c0581a8e3d119c57b9825ea8052e448871ed9c64f7530528e7fc833acaa",
+    "dist/2023-03-07/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "48f8abaffc106eba05c903ec250aeff17a71efa88702459da0ba8be58e62c8c4",
+    "dist/2023-03-07/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "04c176b55b9fdb2fc123e1e012fb8e2dc3bee74861b6cfedf2c1ffbbb3320293",
+    "dist/2023-03-07/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "a908e7f868fcd71050f57e08d15648cd6da04a0f9d150d87739349fb9c87a515",
+    "dist/2023-03-07/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "75062df65fbf89ab1d5344a3471e2c6322f9124fb447b32f634fb6d41695d5c7",
+    "dist/2023-03-07/rustc-beta-x86_64-apple-darwin.tar.gz": "df5224bb128f668474b9702457f5a349144b3148f44ae77109c7ad78800a4c42",
+    "dist/2023-03-07/rustc-beta-x86_64-apple-darwin.tar.xz": "9d27f437e483025cbdb69804f05138ebf181dceda8d32a676ea72ea4f27e69c3",
+    "dist/2023-03-07/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "a7f05d2072c3d3eb7ea88c09ec24a2ce0007ad31df5d3405c6766a68f2fd8ff4",
+    "dist/2023-03-07/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "5e6477ac67b7db05caf15704541db112846415523c483df123d5f566e33afae4",
+    "dist/2023-03-07/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "3a9fd984f8a6673494859dce2dda6be7293effdc3ff7b4620b1078ba346150eb",
+    "dist/2023-03-07/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "5a12779df3e03ecb9ec334c02245f4dd779a4763ee789a9d6c72c244fed5b444",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-freebsd.tar.gz": "dd04e308e72a9cee60db732a17f12e1acbf279fd07efc232648087b765338f44",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-freebsd.tar.xz": "1dd44474ba9956abcdb0aa9d50c39fc7dcc3a78cd56450009bf4ee10cd94ef2e",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-illumos.tar.gz": "0db8082563772e480dfa71851182fd8a45cf6776d486e02204d92af0784c86a6",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-illumos.tar.xz": "eef088e452e105bffe4d28d38d1eacd4982253f0d59cdeb1f406068961699e0c",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "b767ffb06f21b1be530d79a81d8550680d15fd511de5cafae6da9da71017362b",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "d62e8956025dca9d6a9259cc8a35c6d364d161648adb91b50f1fe7e2aec5eb1b",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "aeb32342fc36171ae54b8677348dee02b10207bc85da773a1c7bacfac5e736fb",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "b051ffe45858f1ae2e60461183e4181a1b5c3fa4b349788416fb80b3e3fe39ea",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-netbsd.tar.gz": "2e5ed0ad450602ce32de9509e5317b1b205d4b715f716befb0389f6f6ad94cda",
+    "dist/2023-03-07/rustc-beta-x86_64-unknown-netbsd.tar.xz": "9347db918ca8139f0d816f297d327f48039f02e1d9d9f443fc0f46fb260c8901",
+    "dist/2023-03-07/rustc-nightly-aarch64-apple-darwin.tar.gz": "034c90c20d39fd2384b03ad2a756d3ca28a7447423bd709a0ade19374aa0fb05",
+    "dist/2023-03-07/rustc-nightly-aarch64-apple-darwin.tar.xz": "89d6d968fd5e55a950a798f06a09e1a776cf11dccc94b8123c21c55ebf55e9b7",
+    "dist/2023-03-07/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "809733a64b50a7c9c637afb442e45c4424a0fec96d921cfb0c8a7b30fa52edf7",
+    "dist/2023-03-07/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "03057ff6c4ae76618edea292f49abfcdcad09615a6164186348aba218936c3f0",
+    "dist/2023-03-07/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "e34521e27196fae399e0cbec28700ac409a829cf365bf5b9a7dc5530af61b93e",
+    "dist/2023-03-07/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "e17a9773d58ff0f48cce6c86326cbc33c4e0e8ce08f1a6d475481af9771ae6d6",
+    "dist/2023-03-07/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "01fffcbc734b7de28773a658178534a2cd4d262b156161abd6e5d1d471b45181",
+    "dist/2023-03-07/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "84c0c9d65f00f259df87e78bbe03d0f31075e70b71c587ca580e63604ee654e9",
+    "dist/2023-03-07/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "215cc518a7caacd106ffaaf28f709d1ddb3b4595acdf8574866d4e351576330d",
+    "dist/2023-03-07/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "f50d088adf616f3c25d095254b93d9032a41e5c6a3906afee959b223d6205dfe",
+    "dist/2023-03-07/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "a902efadc47040841653e67f918814a16242312c79ef11c10d69ba9999473c88",
+    "dist/2023-03-07/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "d608e664a5ce02b246b6b00910bdcb5f09e565e41cefbbb8efc579ac9a73c810",
+    "dist/2023-03-07/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "9e8151095f851f71c1d72d41e4ac63ee0dcc81d0f172ce9df4143b6499047aff",
+    "dist/2023-03-07/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "285530c33e600a4df44fd06abeac8e48aa5c084386c4cbe78e797c54f85d01ec",
+    "dist/2023-03-07/rustc-nightly-i686-pc-windows-gnu.tar.gz": "c0e245e17691d38d9f69164e5d9e02d08b5c2355f6fa9cea4bacf50af672c67f",
+    "dist/2023-03-07/rustc-nightly-i686-pc-windows-gnu.tar.xz": "d0c0e699cde96fb23ad5bcc7a8dbf94c86271404b72055bd3382eb29ae4ea85a",
+    "dist/2023-03-07/rustc-nightly-i686-pc-windows-msvc.tar.gz": "b083a065a973394293c11369199385a96d79a6cac5c9d695848e7ac2e51507af",
+    "dist/2023-03-07/rustc-nightly-i686-pc-windows-msvc.tar.xz": "b819b9af08383249f99f0137b636ac42ce84e3e5220c9e0fc1d9e0d348dca54f",
+    "dist/2023-03-07/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "7337d5bc52c0e18c24546b04777ac24461b34e31a59d7df1611f70aee483528f",
+    "dist/2023-03-07/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "efaae84475ddb1845fca470d6d77d842da4e2ad0cca0b2c1e9210c6fce3ff08c",
+    "dist/2023-03-07/rustc-nightly-mips-unknown-linux-gnu.tar.gz": "bd12029bcf9539959c9c9451093cf51ed9db6c7e26b9b9a3bf8617e481b9f094",
+    "dist/2023-03-07/rustc-nightly-mips-unknown-linux-gnu.tar.xz": "b9ea393526c68b9b502d81387cd4a1db7eeddad61467d2442be7c30d210727d8",
+    "dist/2023-03-07/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "997b37b199cc270b5a832aa608d18e0005a510efb587f154f899a22fb7f13639",
+    "dist/2023-03-07/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "e66332078213bf0cce845605d2f7faf28d859e3a98d12d61737ef782a9bdb187",
+    "dist/2023-03-07/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "8a7cbbeb0a9f82333068b51c49d33f694d91da327b1169bc44e9d570840d48d8",
+    "dist/2023-03-07/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "5eb5e2e270a4a475ef2933fe34c764dc6cfaaae423b0d1acb5313fda970f98ba",
+    "dist/2023-03-07/rustc-nightly-mipsel-unknown-linux-gnu.tar.gz": "3140ecca2db80b80118a08cc3fc7ac2989054338525bcc1fe0e2ef1fb5f742bd",
+    "dist/2023-03-07/rustc-nightly-mipsel-unknown-linux-gnu.tar.xz": "0432d418a81564af612a5dac562d7f4d72d7a18ac25260ad183609380efb6bc5",
+    "dist/2023-03-07/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "5be5fa12eafd82618c1f3f611351f23af1150c48b5e02f80f5b4252ec45c11dc",
+    "dist/2023-03-07/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "c288c46b8f077ee604d6de6286dc908086383be91ba17700c3f6273d064c6d82",
+    "dist/2023-03-07/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "de3fe2a9c4c87c5d622a1375dd4fd68064bcd2e5c36dbbc92b95ee42c8ad839e",
+    "dist/2023-03-07/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "b2fbb76cc9e323d0e61d927d7aceff561074b6dbf9907ed3c8dfd867d1308bd8",
+    "dist/2023-03-07/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "f16e202e7e2cfc3a47a0eddd5271fd3a9b7bac5f3c476ce619a249b88cc3ef0b",
+    "dist/2023-03-07/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "61a1cc7f9ce2e8d8ce62165ae7e8b8a53d5c78265641553305130f7a66c706ea",
+    "dist/2023-03-07/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "25ed59822afbd23edc354adb7e3bc361be9170ddd44fb15d7434e7240a66637b",
+    "dist/2023-03-07/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "fdadf6c8d04b99094385b4678015f23da571c3cc134b99e96c3964b15d91d9fe",
+    "dist/2023-03-07/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "b84099f98efd9554a005f8b6d8f15dc9bcd60f9f37856174306873631fa7597c",
+    "dist/2023-03-07/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "608f5a3a1628306618126f94349171566d9a38f14f58875ec1b1e990bd7b1b20",
+    "dist/2023-03-07/rustc-nightly-x86_64-apple-darwin.tar.gz": "4d8b094bf5c608b55e5b618838dafff4b701be093d42aea388c998c2676b226a",
+    "dist/2023-03-07/rustc-nightly-x86_64-apple-darwin.tar.xz": "f11249dc7fd5d208b10b9ead00dc8baa410ce92f61f597e3a550c138e9145413",
+    "dist/2023-03-07/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "db689e50dbef48555609217d09205cd1e397770469a82a9c0ad1f2cf1dd1643b",
+    "dist/2023-03-07/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "36160f7b9a98a463d4e62ed18ff59f5aa34aedf25cf7a7bbd1e4f93dfbfc4a60",
+    "dist/2023-03-07/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "0b10bbbf73fa9a9524746b080d44bcb29d31f013ab809b4c06a71e626f637b4a",
+    "dist/2023-03-07/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "a96259b26388fbf7907df887aacd8059f87207b46bb84ca9b87c460040a17d21",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "0327b112309ab37508c5bd814a77a50e8eb86b19705758ee0a3c09cc560f89cc",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "a7715f358798fc2f78ae6cb08b46f58ad577b91d0aa286893f8f51fda6b2de57",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-illumos.tar.gz": "ed8d664f8609211b3eff0a606f1d5b5f46eb8ab0095df626a26c3abccc518fab",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-illumos.tar.xz": "10badd3e994e93bf48ff1aafc7c056ac525afd12ac4761c0be7af94e361faad5",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "77b7bf994db683057ce94871fb288a24ba41d9a8f5441dfa9a39f3e772f295e3",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "738db7237b08938d978a00b5b972f4c52f36a128ba103ddb67318a905c7e2d27",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "50c57bbf49ec12092dad9de0e559c18f2049de07a0edac4b596a71a2f25a5e0f",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "31af1fbb0f1288e6d7b8eb594cb1936257603038c1ce8b89399056f5d3e1e9c4",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "0a9e395f0b74cc945458d4ad4176567e86cfded1a594eaa485baadb4794dcb64",
+    "dist/2023-03-07/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "26ff4a12db2b583e2e0b87aeb3d3eb9d1edc3478bfd40ffeb7ebdbfb8d8b2987",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "498c7ca27319868d6d2cfb9448b516de1a12076523f092d6c0df10848ba73ff5",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "eec9591d608e13c34fc8108fe976ae2085d688416d82c71bf18f3b00e35a1442",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e9822c7e59218e75af96657bc8a5c3a20c77209f6f1d8861c626aabe7ba9a61d",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "dbad704c1fcfbd8562f366017c514aa90874de6028a9b41764ab7d78a72df6bf",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "5529210f57a0128889c19491846ff7c6f214d3a81d0619ee8dbd840f5f6f84a7",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "d59160d2f737322d401e864ae6b7be47f784a334c7cb378a0bbc2769e975945a",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "ab98e6c8fa7998065e0aaf211559d71405cc6e1910e3799889a27bdeea8c620f",
+    "dist/2023-03-07/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "04ca84fc64c1d211bd29f99b278d9072babbd1e0e9009d9f6f8f1b05f93a70ca",
+    "dist/2023-03-07/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "e80942fde81d3b54c4d0fc73576eebcda215535e4d80093f2a68f434958c0d9a",
+    "dist/2023-03-07/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "a9f10f9a51d3e3564f40c65f6d50c8ef67b4e074981f06f4d3b66aa398883f42",
+    "dist/2023-03-07/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "a5566343b6e3abadb152cd4a325735830aa9a60d5f2f87ef1aff66bbde276b14",
+    "dist/2023-03-07/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "9682e6c4a153d5083b0b360ed9248772da89f05f1142a6f297fc67218b60f298",
+    "dist/2023-03-07/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "51c14ab7679c23825e3a5b9637035768fd43f1e2787a12e431699710f4324998",
+    "dist/2023-03-07/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "f44893b879649a288c77b826e7e10202a2d3a5b8a8b123d8a030e69671a3ac43",
+    "dist/2023-03-07/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "7d5a0e567d8efd65b06b4a75ddc50e7bc2e36b42abaeab15147e970688c0bd07",
+    "dist/2023-03-07/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "541d5cb3d7beff1c0f9f2ea4a521303a372c2b6f4476d76bcfce4974a2753dfa",
+    "dist/2023-03-07/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "ccc65022f10cf0d7b8228806742c5163cd77edfcc2624894b96b2c9d6d974da4",
+    "dist/2023-03-07/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "fccfae7200edd30cd1b6083d00a400641b77e0a4a6e3bf2573710964c896c0d1",
+    "dist/2023-03-07/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "eed06879dacc571c289745a943de9bde2e39bee79ab5a5de0304fdc00e116855",
+    "dist/2023-03-07/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "cb1ed1cf09ce5cdbec931ea27b6fccd37b63108c780ae21c1756c68e0415c59b",
+    "dist/2023-03-07/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "b0681834694c5aa27c404d2328a5ce3e3dcc8a0b146fcd9d47113655cf94c948",
+    "dist/2023-03-07/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "a246b3e7c6ad436ad7523607bcf3a1fc42a66dd9da6a401fdaba5724fdf6801c",
+    "dist/2023-03-07/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "fa5b4d24c046b01b981fb81540155af5677490f2ac151418fa7791ec0f5aed56",
+    "dist/2023-03-07/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "b28148883461e905440ba25f755dc6a46c393a69a4cea48044e376fb90caa44b",
+    "dist/2023-03-07/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "ff37f00813b2ef0c206fb66cd383f87a089fad6a3746a9d62b27109557eb0097",
+    "dist/2023-03-07/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "2132cfd61404cfdad4e21ad95066836c77863756d46abc1fd2b702f46b3c7fac",
+    "dist/2023-03-07/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "89d1e41fd9bdd76c15faba83abfa1ffdadfffb6cd1b49c18e2d1333856296ee3",
+    "dist/2023-03-07/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "2353107ac3875f9cdf690b6684941c2def1c240416208dee58f58e78eefbd96e",
+    "dist/2023-03-07/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "b6e0882de92b73d540d22df393750646487dcf12c11b0bdad01265ce5cd6275f",
+    "dist/2023-03-07/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "c64967a706e7448f97d40b50356672b03f2731fde3488084007bbe7cd07409a6",
+    "dist/2023-03-07/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "d7d829f5a23aa25b320cd4f4c12d2db11d7e36c67a9396de7426933169159b62",
+    "dist/2023-03-07/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "1080d035d29fb9f8e1c007796e38164261ba19d4362b847d571eb7d3a6281d5c",
+    "dist/2023-03-07/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "874d841241b37072a6fb6c8d70f0afc9535ffb47793270b3a2a5c96ba46b7ec2",
+    "dist/2023-03-07/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "7ede80fb9a1aa27380d764d04e587a30fb6aee36138b145e32d518cbe8ec95b5",
+    "dist/2023-03-07/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "e1ec7d8b92740b0dff06e9424ac8d08b64e4aa85c5e8d46f9234fdeab5ad5e44",
+    "dist/2023-03-07/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "9058714e2f253ca681b24308a59bee006f636dff0b7571ebdf7c7687233b5a2f",
+    "dist/2023-03-07/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "6087e0abf78f2cb49240314cd31aa9bbfca02eb4918db4a2aaaa6758e8364560",
+    "dist/2023-03-07/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "2c775b1d4e2f3218a1d51f8ac79c63e8c2eabc46106e2a38d5bd1febcba7d12b",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "3a14e2b54773816cfdee1a835d2f758abfaacef36af6a7744c464b0ce5713c8b",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "3f6f7e5b9180f0114781b776a7f1bca72b208ddd102a9e44cebcd501eea7a31b",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "c92bf50f2a729af4b045184cd984bde0d97979cf8ae35975a1eaad5d8ae04195",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "c62b8f4862d0f8c38b890408c014be5d6d245f2a49d6f31a80c9447bbed4d8b4",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "8452a8704cb04ce2deef2cce2d9f2be066c5bd35aef323877ebef6f8f739710d",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "e694bb8697679196246f13031a9eef5129b0441a8c93c0292382b21cefab39a7",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "37f7ecfc0ba9314b2ec46ce202973cd7e36062a88070427ced9ffed3ad96c685",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "7aef4412810218743a85f1c7cce423394a327a708d31441441050bc1fcae0d80",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "70701d0bc637c282436e9ef6f18dadcb8068305ac64b1abb802bbc5054ff042c",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "2d8e170259a254cf6b1c5749a681040db70e2603b7231082483f03e2714765ba",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "7241cab5f93fc338fbb07acd2d38e2fa8615c4e6ebb0a53f51ac60c23838845f",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "2742e08cf5900ad3002809c632b8b8962325699307943ba2bafa0931204cc787",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "576c17a72e47fc743d60818bbfefe17c0223eb979cfed3046bf4797e6c2a6d26",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "25026a50665f53b7ac3e1e08b3a5a3a526411c8c18be6d64df6ab23ee0819b64",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "773679226499447a48cd823d324fc906a1d93f3fb5abc137920aa67ece410de9",
+    "dist/2023-03-07/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "53c88668c3c9ab6df7f3cace825a45616909bb28628ee8636a8ce86b77cf4bb5"
   }
 }
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index d1d2db27c6f..fe28c526be3 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
             Finite
         },
         ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
-        ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
+        ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
         ExprKind::Call(path, _) => {
             if let ExprKind::Path(ref qpath) = path.kind {
                 cx.qpath_res(qpath, path.hir_id)
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index b1bc10802e1..f0a1b1dfe56 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -124,8 +124,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t
 #[allow(clippy::too_many_lines)]
 fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
     match expr.kind {
-        ExprKind::Box(e)
-        | ExprKind::Unary(_, e)
+        ExprKind::Unary(_, e)
         | ExprKind::Cast(e, _)
         | ExprKind::Type(e, _)
         | ExprKind::Field(e, _)
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index b33a2478172..04225beeb70 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -321,7 +321,6 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
                     self.has_significant_drop = true;
                 }
             }
-            ExprKind::Box(..) |
             ExprKind::Array(..) |
             ExprKind::Call(..) |
             ExprKind::Unary(..) |
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index 5201da52bbf..67618f7038a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -33,10 +33,6 @@ struct SortByKeyDetection {
 /// contains a and the other replaces it with b)
 fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool {
     match (&a_expr.kind, &b_expr.kind) {
-        // Two boxes with mirrored contents
-        (ExprKind::Box(left_expr), ExprKind::Box(right_expr)) => {
-            mirrored_exprs(left_expr, a_ident, right_expr, b_ident)
-        },
         // Two arrays with mirrored contents
         (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
             iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident))
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 79c1ae4861e..e3712190e67 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -127,8 +127,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         | ExprKind::Type(inner, _)
         | ExprKind::Unary(_, inner)
         | ExprKind::Field(inner, _)
-        | ExprKind::AddrOf(_, _, inner)
-        | ExprKind::Box(inner) => has_no_effect(cx, inner),
+        | ExprKind::AddrOf(_, _, inner) => has_no_effect(cx, inner),
         ExprKind::Struct(_, fields, ref base) => {
             !has_drop(cx, cx.typeck_results().expr_ty(expr))
                 && fields.iter().all(|field| has_no_effect(cx, field.expr))
@@ -234,8 +233,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
         | ExprKind::Type(inner, _)
         | ExprKind::Unary(_, inner)
         | ExprKind::Field(inner, _)
-        | ExprKind::AddrOf(_, _, inner)
-        | ExprKind::Box(inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
+        | ExprKind::AddrOf(_, _, inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
         ExprKind::Struct(_, fields, ref base) => {
             if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
                 None
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index 87f966ced0d..ae7d19624ba 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -213,8 +213,7 @@ fn is_self_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, mut expr: &Expr<'_>, hir_
     }
     loop {
         expr = match expr.kind {
-            ExprKind::Box(e)
-            | ExprKind::AddrOf(_, _, e)
+            ExprKind::AddrOf(_, _, e)
             | ExprKind::Block(
                 &Block {
                     stmts: [],
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index e2d90edec5a..e12681c0a0c 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -380,7 +380,6 @@ impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> {
             | hir::ExprKind::Assign(..)
             | hir::ExprKind::AssignOp(..)
             | hir::ExprKind::Binary(..)
-            | hir::ExprKind::Box(..)
             | hir::ExprKind::Call(..)
             | hir::ExprKind::Field(..)
             | hir::ExprKind::If(..)
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index f31c3fdb095..bc4adf1596d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -395,11 +395,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 }
                 self.expr(field!(let_expr.init));
             },
-            ExprKind::Box(inner) => {
-                bind!(self, inner);
-                kind!("Box({inner})");
-                self.expr(inner);
-            },
             ExprKind::Array(elements) => {
                 bind!(self, elements);
                 kind!("Array({elements})");
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 43f0df145f0..d3a6929f67e 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -112,7 +112,6 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
 /// Get the search patterns to use for the given expression
 fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
     match e.kind {
-        ExprKind::Box(e) => (Pat::Str("box"), expr_search_pat(tcx, e).1),
         ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")),
         ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")),
         ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1),
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index ee2f816f181..babbc7294a1 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -199,8 +199,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 },
 
                 // Memory allocation, custom operator, loop, or call to an unknown function
-                ExprKind::Box(_)
-                | ExprKind::Unary(..)
+                ExprKind::Unary(..)
                 | ExprKind::Binary(..)
                 | ExprKind::Loop(..)
                 | ExprKind::Call(..) => self.eagerness = Lazy,
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 0603755f8a9..3a6d23ca5c1 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -249,7 +249,6 @@ impl HirEqInterExpr<'_, '_, '_> {
                 both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
                     && both(le, re, |l, r| self.eq_expr(l, r))
             },
-            (&ExprKind::Box(l), &ExprKind::Box(r)) => self.eq_expr(l, r),
             (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
                 self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
             },
@@ -628,7 +627,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_expr(j);
                 }
             },
-            ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
+            ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
                 self.hash_expr(e);
             },
             ExprKind::Call(fun, args) => {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 85bf28b708b..44cb5d5756a 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -133,7 +133,6 @@ impl<'a> Sugg<'a> {
 
         match expr.kind {
             hir::ExprKind::AddrOf(..)
-            | hir::ExprKind::Box(..)
             | hir::ExprKind::If(..)
             | hir::ExprKind::Let(..)
             | hir::ExprKind::Closure { .. }
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index d27a20bd4df..86a93f64fb7 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -600,7 +600,6 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
                 helper(typeck, false, e, f)?;
             },
             ExprKind::Block(&Block { expr: Some(e), .. }, _)
-            | ExprKind::Box(e)
             | ExprKind::Cast(e, _)
             | ExprKind::Unary(_, e) => {
                 helper(typeck, true, e, f)?;
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a127875b55d..4d9010d3c4b 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -278,13 +278,15 @@ impl<'test> TestCx<'test> {
             Incremental => {
                 let revision =
                     self.revision.expect("incremental tests require a list of revisions");
-                if revision.starts_with("rpass") || revision.starts_with("rfail") {
+                if revision.starts_with("cpass")
+                    || revision.starts_with("rpass")
+                    || revision.starts_with("rfail")
+                {
                     true
                 } else if revision.starts_with("cfail") {
-                    // FIXME: would be nice if incremental revs could start with "cpass"
                     pm.is_some()
                 } else {
-                    panic!("revision name must begin with rpass, rfail, or cfail");
+                    panic!("revision name must begin with cpass, rpass, rfail, or cfail");
                 }
             }
             mode => panic!("unimplemented for mode {:?}", mode),
@@ -384,6 +386,20 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn run_cpass_test(&self) {
+        let emit_metadata = self.should_emit_metadata(self.pass_mode());
+        let proc_res = self.compile_test(WillExecute::No, emit_metadata);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        // FIXME(#41968): Move this check to tidy?
+        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
+            self.fatal("compile-pass tests with expected warnings should be moved to ui/");
+        }
+    }
+
     fn run_rpass_test(&self) {
         let emit_metadata = self.should_emit_metadata(self.pass_mode());
         let should_run = self.run_if_enabled();
@@ -393,17 +409,15 @@ impl<'test> TestCx<'test> {
             self.fatal_proc_rec("compilation failed!", &proc_res);
         }
 
+        // FIXME(#41968): Move this check to tidy?
+        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
+            self.fatal("run-pass tests with expected warnings should be moved to ui/");
+        }
+
         if let WillExecute::Disabled = should_run {
             return;
         }
 
-        // FIXME(#41968): Move this check to tidy?
-        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
-        assert!(
-            expected_errors.is_empty(),
-            "run-pass tests with expected warnings should be moved to ui/"
-        );
-
         let proc_res = self.exec_compiled_test();
         if !proc_res.status.success() {
             self.fatal_proc_rec("test run failed!", &proc_res);
@@ -2913,10 +2927,11 @@ impl<'test> TestCx<'test> {
     fn run_incremental_test(&self) {
         // Basic plan for a test incremental/foo/bar.rs:
         // - load list of revisions rpass1, cfail2, rpass3
-        //   - each should begin with `rpass`, `cfail`, or `rfail`
-        //   - if `rpass`, expect compile and execution to succeed
+        //   - each should begin with `cpass`, `rpass`, `cfail`, or `rfail`
+        //   - if `cpass`, expect compilation to succeed, don't execute
+        //   - if `rpass`, expect compilation and execution to succeed
         //   - if `cfail`, expect compilation to fail
-        //   - if `rfail`, expect execution to fail
+        //   - if `rfail`, expect compilation to succeed and execution to fail
         // - create a directory build/foo/bar.incremental
         // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
         //   - because name of revision starts with "rpass", expect success
@@ -2940,7 +2955,12 @@ impl<'test> TestCx<'test> {
             print!("revision={:?} props={:#?}", revision, self.props);
         }
 
-        if revision.starts_with("rpass") {
+        if revision.starts_with("cpass") {
+            if self.props.should_ice {
+                self.fatal("can only use should-ice in cfail tests");
+            }
+            self.run_cpass_test();
+        } else if revision.starts_with("rpass") {
             if self.props.should_ice {
                 self.fatal("can only use should-ice in cfail tests");
             }
@@ -2953,7 +2973,7 @@ impl<'test> TestCx<'test> {
         } else if revision.starts_with("cfail") {
             self.run_cfail_test();
         } else {
-            self.fatal("revision name must begin with rpass, rfail, or cfail");
+            self.fatal("revision name must begin with cpass, rpass, rfail, or cfail");
         }
     }
 
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 138a69974e1..b71f48e4644 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -54,8 +54,8 @@ jobs:
             # contains package information of crates installed via `cargo install`.
             ~/.cargo/.crates.toml
             ~/.cargo/.crates2.json
-          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
-          restore-keys: ${{ runner.os }}-cargo
+          key: ${{ runner.os }}-cargo-reset20230315-${{ hashFiles('**/Cargo.lock') }}
+          restore-keys: ${{ runner.os }}-cargo-reset20230315
 
       - name: Install rustup-toolchain-install-master
         if: ${{ steps.cache.outputs.cache-hit != 'true' }}
@@ -106,8 +106,8 @@ jobs:
             # contains package information of crates installed via `cargo install`.
             ~/.cargo/.crates.toml
             ~/.cargo/.crates2.json
-          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
-          restore-keys: ${{ runner.os }}-cargo
+          key: ${{ runner.os }}-cargo-reset20230315-${{ hashFiles('**/Cargo.lock') }}
+          restore-keys: ${{ runner.os }}-cargo-reset20230315
 
       - name: Install rustup-toolchain-install-master
         if: ${{ steps.cache.outputs.cache-hit != 'true' }}
diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md
index 476075e9c91..bcdb623b090 100644
--- a/src/tools/miri/CONTRIBUTING.md
+++ b/src/tools/miri/CONTRIBUTING.md
@@ -129,18 +129,15 @@ development version of Miri using
 ./miri install
 ```
 
-and then you can use it as if it was installed by `rustup`.  Make sure you use
-the same toolchain when calling `cargo miri` that you used when installing Miri!
-Usually this means you have to write `cargo +miri miri ...` to select the `miri`
-toolchain that was installed by `./miri toolchain`.
+and then you can use it as if it was installed by `rustup` as a component of the
+`miri` toolchain. Note that the `miri` and `cargo-miri` executables are placed
+in the `miri` toolchain's sysroot to prevent conflicts with other toolchains.
+The Miri binaries in the `cargo` bin directory (usually `~/.cargo/bin`) are managed by rustup.
 
 There's a test for the cargo wrapper in the `test-cargo-miri` directory; run
 `./run-test.py` in there to execute it. Like `./miri test`, this respects the
 `MIRI_TEST_TARGET` environment variable to execute the test for another target.
 
-Note that installing Miri like this will "take away" Miri management from `rustup`.
-If you want to later go back to a rustup-installed Miri, run `rustup update`.
-
 ### Using a modified standard library
 
 Miri re-builds the standard library into a custom sysroot, so it is fairly easy
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 1086d0481c8..b70f7e0e556 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -15,6 +15,8 @@ for example:
   or an invalid enum discriminant)
 * **Experimental**: Violations of the [Stacked Borrows] rules governing aliasing
   for reference types
+* **Experimental**: Violations of the Tree Borrows aliasing rules, as an optional
+  alternative to [Stacked Borrows]
 * **Experimental**: Data races
 
 On top of that, Miri will also tell you about memory leaks: when there is memory
@@ -225,6 +227,26 @@ degree documented below):
   reduced feature set. We might ship Miri with a nightly even when some features
   on these targets regress.
 
+### Running tests in parallel
+
+Though it implements Rust threading, Miri itself is a single-threaded interpreter.
+This means that when running `cargo miri test`, you will probably see a dramatic
+increase in the amount of time it takes to run your whole test suite due to the
+inherent interpreter slowdown and a loss of parallelism.
+
+You can get your test suite's parallelism back by running `cargo miri nextest run -jN`
+(note that you will need [`cargo-nextest`](https://nexte.st) installed).
+This works because `cargo-nextest` collects a list of all tests then launches a
+separate `cargo miri run` for each test. You will need to specify a `-j` or `--test-threads`;
+by default `cargo miri nextest run` runs one test at a time. For more details, see the
+[`cargo-nextest` Miri documentation](https://nexte.st/book/miri.html).
+
+Note: This one-test-per-process model means that `cargo miri test` is able to detect data
+races where two tests race on a shared resource, but `cargo miri nextest run` will not detect
+such races.
+
+Note: `cargo-nextest` does not support doctests, see https://github.com/nextest-rs/nextest/issues/16
+
 ### Common Problems
 
 When using the above instructions, you may encounter a number of confusing compiler
@@ -337,9 +359,11 @@ to Miri failing to detect cases of undefined behavior in a program.
 * `-Zmiri-disable-data-race-detector` disables checking for data races.  Using
   this flag is **unsound**. This implies `-Zmiri-disable-weak-memory-emulation`.
 * `-Zmiri-disable-stacked-borrows` disables checking the experimental
-  [Stacked Borrows] aliasing rules.  This can make Miri run faster, but it also
-  means no aliasing violations will be detected.  Using this flag is **unsound**
-  (but the affected soundness rules are experimental).
+  aliasing rules to track borrows ([Stacked Borrows] and Tree Borrows).
+  This can make Miri run faster, but it also means no aliasing violations will
+  be detected. Using this flag is **unsound** (but the affected soundness rules
+  are experimental). Later flags take precedence: borrow tracking can be reactivated
+  by `-Zmiri-tree-borrows`.
 * `-Zmiri-disable-validation` disables enforcing validity invariants, which are
   enforced by default.  This is mostly useful to focus on other failures (such
   as out-of-bounds accesses) first.  Setting this flag means Miri can miss bugs
@@ -401,6 +425,9 @@ to Miri failing to detect cases of undefined behavior in a program.
 * `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
   value from a load. This can help diagnose problems that disappear under
   `-Zmiri-disable-weak-memory-emulation`.
+* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the Tree Borrows rules.
+  The soundness rules are already experimental without this flag, but even more
+  so with this flag.
 * `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
   `4` is default for most targets. This value should always be a power of 2 and nonzero.
 
@@ -415,7 +442,7 @@ Some native rustc `-Z` flags are also very relevant for Miri:
   functions.  This is needed so that Miri can execute such functions, so Miri
   sets this flag per default.
 * `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
-  enables this per default because it is needed for [Stacked Borrows].
+  enables this per default because it is needed for [Stacked Borrows] and Tree Borrows.
 
 Moreover, Miri recognizes some environment variables:
 
@@ -481,120 +508,8 @@ binaries, and as such worth documenting:
 ## Miri `extern` functions
 
 Miri provides some `extern` functions that programs can import to access
-Miri-specific functionality:
-
-```rust
-#[cfg(miri)]
-extern "Rust" {
-    /// Miri-provided extern function to mark the block `ptr` points to as a "root"
-    /// for some static memory. This memory and everything reachable by it is not
-    /// considered leaking even if it still exists when the program terminates.
-    ///
-    /// `ptr` has to point to the beginning of an allocated block.
-    fn miri_static_root(ptr: *const u8);
-
-    // Miri-provided extern function to get the amount of frames in the current backtrace.
-    // The `flags` argument must be `0`.
-    fn miri_backtrace_size(flags: u64) -> usize;
-
-    /// Miri-provided extern function to obtain a backtrace of the current call stack.
-    /// This writes a slice of pointers into `buf` - each pointer is an opaque value
-    /// that is only useful when passed to `miri_resolve_frame`.
-    /// `buf` must have `miri_backtrace_size(0) * pointer_size` bytes of space.
-    /// The `flags` argument must be `1`.
-    fn miri_get_backtrace(flags: u64, buf: *mut *mut ());
-
-    /// Miri-provided extern function to resolve a frame pointer obtained
-    /// from `miri_get_backtrace`. The `flags` argument must be `1`,
-    /// and `MiriFrame` should be declared as follows:
-    ///
-    /// ```rust
-    /// #[repr(C)]
-    /// struct MiriFrame {
-    ///     // The size of the name of the function being executed, encoded in UTF-8
-    ///     name_len: usize,
-    ///     // The size of filename of the function being executed, encoded in UTF-8
-    ///     filename_len: usize,
-    ///     // The line number currently being executed in `filename`, starting from '1'.
-    ///     lineno: u32,
-    ///     // The column number currently being executed in `filename`, starting from '1'.
-    ///     colno: u32,
-    ///     // The function pointer to the function currently being executed.
-    ///     // This can be compared against function pointers obtained by
-    ///     // casting a function (e.g. `my_fn as *mut ()`)
-    ///     fn_ptr: *mut ()
-    /// }
-    /// ```
-    ///
-    /// The fields must be declared in exactly the same order as they appear in `MiriFrame` above.
-    /// This function can be called on any thread (not just the one which obtained `frame`).
-    fn miri_resolve_frame(frame: *mut (), flags: u64) -> MiriFrame;
-
-    /// Miri-provided extern function to get the name and filename of the frame provided by `miri_resolve_frame`.
-    /// `name_buf` and `filename_buf` should be allocated with the `name_len` and `filename_len` fields of `MiriFrame`.
-    /// The flags argument must be `0`.
-    fn miri_resolve_frame_names(ptr: *mut (), flags: u64, name_buf: *mut u8, filename_buf: *mut u8);
-
-    /// Miri-provided extern function to begin unwinding with the given payload.
-    ///
-    /// This is internal and unstable and should not be used; we give it here
-    /// just to be complete.
-    fn miri_start_panic(payload: *mut u8) -> !;
-
-    /// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer
-    /// points to. If this pointer is invalid (not pointing to an allocation), interpretation will abort.
-    ///
-    /// This is only useful as an input to `miri_print_borrow_stacks`, and it is a separate call because
-    /// getting a pointer to an allocation at runtime can change the borrow stacks in the allocation.
-    /// This function should be considered unstable. It exists only to support `miri_print_borrow_stacks` and so
-    /// inherits all of its instability.
-    fn miri_get_alloc_id(ptr: *const ()) -> u64;
-
-    /// Miri-provided extern function to print (from the interpreter, not the program) the contents of all
-    /// borrow stacks in an allocation. The leftmost tag is the bottom of the stack.
-    /// The format of what this emits is unstable and may change at any time. In particular, users should be
-    /// aware that Miri will periodically attempt to garbage collect the contents of all stacks. Callers of
-    /// this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC.
-    ///
-    /// This function is extremely unstable. At any time the format of its output may change, its signature may
-    /// change, or it may be removed entirely.
-    fn miri_print_borrow_stacks(alloc_id: u64);
-
-    /// Miri-provided extern function to print (from the interpreter, not the
-    /// program) the contents of a section of program memory, as bytes. Bytes
-    /// written using this function will emerge from the interpreter's stdout.
-    fn miri_write_to_stdout(bytes: &[u8]);
-
-    /// Miri-provided extern function to print (from the interpreter, not the
-    /// program) the contents of a section of program memory, as bytes. Bytes
-    /// written using this function will emerge from the interpreter's stderr.
-    fn miri_write_to_stderr(bytes: &[u8]);
-
-    /// Miri-provided extern function to allocate memory from the interpreter.
-    /// 
-    /// This is useful when no fundamental way of allocating memory is
-    /// available, e.g. when using `no_std` + `alloc`.
-    fn miri_alloc(size: usize, align: usize) -> *mut u8;
-
-    /// Miri-provided extern function to deallocate memory.
-    fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
-
-    /// Convert a path from the host Miri runs on to the target Miri interprets.
-    /// Performs conversion of path separators as needed.
-    ///
-    /// Usually Miri performs this kind of conversion automatically. However, manual conversion
-    /// might be necessary when reading an environment variable that was set on the host
-    /// (such as TMPDIR) and using it as a target path.
-    ///
-    /// Only works with isolation disabled.
-    ///
-    /// `in` must point to a null-terminated string, and will be read as the input host path.
-    /// `out` must point to at least `out_size` many bytes, and the result will be stored there
-    /// with a null terminator.
-    /// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
-    fn miri_host_to_target_path(path: *const std::ffi::c_char, out: *mut std::ffi::c_char, out_size: usize) -> usize;
-}
-```
+Miri-specific functionality. They are declared in
+[/tests/utils/miri\_extern.rs](/tests/utils/miri_extern.rs).
 
 ## Contributing and getting help
 
diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh
index 60450d09815..ef52a37fe31 100755
--- a/src/tools/miri/ci.sh
+++ b/src/tools/miri/ci.sh
@@ -62,8 +62,8 @@ function run_tests {
   if [ "$HOST_TARGET" = x86_64-unknown-linux-gnu ]; then
     # These act up on Windows (`which miri` produces a filename that does not exist?!?),
     # so let's do this only on Linux. Also makes sure things work without these set.
-    export RUSTC=$(which rustc)
-    export MIRI=$(which miri)
+    export RUSTC=$(which rustc) # Produces a warning unless we also set MIRI
+    export MIRI=$(rustc +miri --print sysroot)/bin/miri
   fi
   mkdir -p .cargo
   echo 'build.rustc-wrapper = "thisdoesnotexist"' > .cargo/config.toml
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index 0c0bbbc7020..1073ff499ba 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -6,8 +6,8 @@ USAGE=$(cat <<"EOF"
 ./miri install <flags>:
 Installs the miri driver and cargo-miri. <flags> are passed to `cargo
 install`. Sets up the rpath such that the installed binary should work in any
-working directory. However, the rustup toolchain when invoking `cargo miri`
-needs to be the same one used for `./miri install`.
+working directory. Note that the binaries are placed in the `miri` toolchain
+sysroot, to prevent conflicts with other toolchains.
 
 ./miri build <flags>:
 Just build miri. <flags> are passed to `cargo build`.
@@ -281,8 +281,9 @@ find_sysroot() {
 case "$COMMAND" in
 install)
     # "--locked" to respect the Cargo.lock file if it exists.
-    $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR" --force --locked "$@"
-    $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR"/cargo-miri --force --locked "$@"
+    # Install binaries to the miri toolchain's sysroot so they do not interact with other toolchains.
+    $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR" --force --locked --root "$SYSROOT" "$@"
+    $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR"/cargo-miri --force --locked --root "$SYSROOT" "$@"
     ;;
 check)
     # Check, and let caller control flags.
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 53ec1ba0821..18c2561242a 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-c4e0cd966062ca67daed20775f4e8a60c28e57df
+511364e7874dba9649a264100407e4bffe7b5425
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index a2caeb97297..6fe3fa7fb1b 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -32,7 +32,7 @@ use rustc_middle::{
 };
 use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace};
 
-use miri::{BacktraceStyle, ProvenanceMode, RetagFields};
+use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields};
 
 struct MiriCompilerCalls {
     miri_config: miri::MiriConfig,
@@ -317,6 +317,8 @@ fn main() {
             miri_config.validate = false;
         } else if arg == "-Zmiri-disable-stacked-borrows" {
             miri_config.borrow_tracker = None;
+        } else if arg == "-Zmiri-tree-borrows" {
+            miri_config.borrow_tracker = Some(BorrowTrackerMethod::TreeBorrows);
         } else if arg == "-Zmiri-disable-data-race-detector" {
             miri_config.data_race_detector = false;
             miri_config.weak_memory_emulation = false;
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 9f6cbe7f3c7..ed958329f95 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -11,6 +11,7 @@ use rustc_target::abi::Size;
 
 use crate::*;
 pub mod stacked_borrows;
+pub mod tree_borrows;
 
 pub type CallId = NonZeroU64;
 
@@ -230,8 +231,10 @@ impl GlobalStateInner {
 /// Which borrow tracking method to use
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum BorrowTrackerMethod {
-    /// Stacked Borrows, as implemented in borrow_tracker/stacked
+    /// Stacked Borrows, as implemented in borrow_tracker/stacked_borrows
     StackedBorrows,
+    /// Tree borrows, as implemented in borrow_tracker/tree_borrows
+    TreeBorrows,
 }
 
 impl BorrowTrackerMethod {
@@ -258,6 +261,10 @@ impl GlobalStateInner {
                 AllocState::StackedBorrows(Box::new(RefCell::new(Stacks::new_allocation(
                     id, alloc_size, self, kind, machine,
                 )))),
+            BorrowTrackerMethod::TreeBorrows =>
+                AllocState::TreeBorrows(Box::new(RefCell::new(Tree::new_allocation(
+                    id, alloc_size, self, kind, machine,
+                )))),
         }
     }
 }
@@ -273,6 +280,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
             BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val),
+            BorrowTrackerMethod::TreeBorrows => this.tb_retag_ptr_value(kind, val),
         }
     }
 
@@ -285,6 +293,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
             BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place),
+            BorrowTrackerMethod::TreeBorrows => this.tb_retag_place_contents(kind, place),
         }
     }
 
@@ -293,6 +302,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
             BorrowTrackerMethod::StackedBorrows => this.sb_retag_return_place(),
+            BorrowTrackerMethod::TreeBorrows => this.tb_retag_return_place(),
         }
     }
 
@@ -301,6 +311,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
             BorrowTrackerMethod::StackedBorrows => this.sb_expose_tag(alloc_id, tag),
+            BorrowTrackerMethod::TreeBorrows => this.tb_expose_tag(alloc_id, tag),
+        }
+    }
+
+    fn give_pointer_debug_name(
+        &mut self,
+        ptr: Pointer<Option<Provenance>>,
+        nth_parent: u8,
+        name: &str,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
+        match method {
+            BorrowTrackerMethod::StackedBorrows => {
+                this.tcx.tcx.sess.warn("Stacked Borrows does not support named pointers; `miri_pointer_name` is a no-op");
+                Ok(())
+            }
+            BorrowTrackerMethod::TreeBorrows =>
+                this.tb_give_pointer_debug_name(ptr, nth_parent, name),
+        }
+    }
+
+    fn print_borrow_state(&mut self, alloc_id: AllocId, show_unnamed: bool) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
+        match method {
+            BorrowTrackerMethod::StackedBorrows => this.print_stacks(alloc_id),
+            BorrowTrackerMethod::TreeBorrows => this.print_tree(alloc_id, show_unnamed),
         }
     }
 }
@@ -310,6 +348,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 pub enum AllocState {
     /// Data corresponding to Stacked Borrows
     StackedBorrows(Box<RefCell<stacked_borrows::AllocState>>),
+    /// Data corresponding to Tree Borrows
+    TreeBorrows(Box<RefCell<tree_borrows::AllocState>>),
 }
 
 impl machine::AllocExtra {
@@ -328,6 +368,14 @@ impl machine::AllocExtra {
             _ => panic!("expected Stacked Borrows borrow tracking, got something else"),
         }
     }
+
+    #[track_caller]
+    pub fn borrow_tracker_tb(&self) -> &RefCell<tree_borrows::AllocState> {
+        match self.borrow_tracker {
+            Some(AllocState::TreeBorrows(ref tb)) => tb,
+            _ => panic!("expected Tree Borrows borrow tracking, got something else"),
+        }
+    }
 }
 
 impl AllocState {
@@ -341,6 +389,14 @@ impl AllocState {
         match self {
             AllocState::StackedBorrows(sb) =>
                 sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine),
+            AllocState::TreeBorrows(tb) =>
+                tb.borrow_mut().before_memory_access(
+                    AccessKind::Read,
+                    alloc_id,
+                    prov_extra,
+                    range,
+                    machine,
+                ),
         }
     }
 
@@ -354,6 +410,14 @@ impl AllocState {
         match self {
             AllocState::StackedBorrows(sb) =>
                 sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine),
+            AllocState::TreeBorrows(tb) =>
+                tb.get_mut().before_memory_access(
+                    AccessKind::Write,
+                    alloc_id,
+                    prov_extra,
+                    range,
+                    machine,
+                ),
         }
     }
 
@@ -367,12 +431,15 @@ impl AllocState {
         match self {
             AllocState::StackedBorrows(sb) =>
                 sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, range, machine),
+            AllocState::TreeBorrows(tb) =>
+                tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, range, machine),
         }
     }
 
     pub fn remove_unreachable_tags(&self, tags: &FxHashSet<BorTag>) {
         match self {
             AllocState::StackedBorrows(sb) => sb.borrow_mut().remove_unreachable_tags(tags),
+            AllocState::TreeBorrows(tb) => tb.borrow_mut().remove_unreachable_tags(tags),
         }
     }
 }
@@ -381,6 +448,7 @@ impl VisitTags for AllocState {
     fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
         match self {
             AllocState::StackedBorrows(sb) => sb.visit_tags(visit),
+            AllocState::TreeBorrows(tb) => tb.visit_tags(visit),
         }
     }
 }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
new file mode 100644
index 00000000000..97bbdee1d44
--- /dev/null
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
@@ -0,0 +1,592 @@
+use rustc_data_structures::fx::FxHashMap;
+
+use std::fmt;
+use std::ops::Range;
+
+use crate::borrow_tracker::tree_borrows::{
+    err_tb_ub, perms::Permission, tree::LocationState, unimap::UniIndex,
+};
+use crate::borrow_tracker::{AccessKind, ProtectorKind};
+use crate::*;
+
+/// Some information that is irrelevant for the algorithm but very
+/// convenient to know about a tag for debugging and testing.
+#[derive(Clone, Debug)]
+pub struct NodeDebugInfo {
+    /// The tag in question.
+    pub tag: BorTag,
+    /// Name(s) that were associated with this tag (comma-separated).
+    /// Typically the name of the variable holding the corresponding
+    /// pointer in the source code.
+    /// Helps match tag numbers to human-readable names.
+    pub name: Option<String>,
+}
+impl NodeDebugInfo {
+    /// New node info with a name.
+    pub fn new(tag: BorTag) -> Self {
+        Self { tag, name: None }
+    }
+
+    /// Add a name to the tag. If a same tag is associated to several pointers,
+    /// it can have several names which will be separated by commas.
+    fn add_name(&mut self, name: &str) {
+        if let Some(ref mut prev_name) = &mut self.name {
+            prev_name.push(',');
+            prev_name.push_str(name);
+        } else {
+            self.name = Some(String::from(name));
+        }
+    }
+}
+
+impl fmt::Display for NodeDebugInfo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if let Some(ref name) = self.name {
+            write!(f, "{tag:?} (also named '{name}')", tag = self.tag)
+        } else {
+            write!(f, "{tag:?}", tag = self.tag)
+        }
+    }
+}
+
+impl<'tcx> Tree {
+    /// Climb the tree to get the tag of a distant ancestor.
+    /// Allows operations on tags that are unreachable by the program
+    /// but still exist in the tree. Not guaranteed to perform consistently
+    /// if `tag-gc=1`.
+    fn nth_parent(&self, tag: BorTag, nth_parent: u8) -> Option<BorTag> {
+        let mut idx = self.tag_mapping.get(&tag).unwrap();
+        for _ in 0..nth_parent {
+            let node = self.nodes.get(idx).unwrap();
+            idx = node.parent?;
+        }
+        Some(self.nodes.get(idx).unwrap().tag)
+    }
+
+    /// Debug helper: assign name to tag.
+    pub fn give_pointer_debug_name(
+        &mut self,
+        tag: BorTag,
+        nth_parent: u8,
+        name: &str,
+    ) -> InterpResult<'tcx> {
+        let tag = self.nth_parent(tag, nth_parent).unwrap();
+        let idx = self.tag_mapping.get(&tag).unwrap();
+        if let Some(node) = self.nodes.get_mut(idx) {
+            node.debug_info.add_name(name);
+        } else {
+            eprintln!("Tag {tag:?} (to be named '{name}') not found!");
+        }
+        Ok(())
+    }
+
+    /// Debug helper: determines if the tree contains a tag.
+    pub fn is_allocation_of(&self, tag: BorTag) -> bool {
+        self.tag_mapping.contains_key(&tag)
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub(super) enum TransitionError {
+    /// This access is not allowed because some parent tag has insufficient permissions.
+    /// For example, if a tag is `Frozen` and encounters a child write this will
+    /// produce a `ChildAccessForbidden(Frozen)`.
+    /// This kind of error can only occur on child accesses.
+    ChildAccessForbidden(Permission),
+    /// A protector was triggered due to an invalid transition that loses
+    /// too much permissions.
+    /// For example, if a protected tag goes from `Active` to `Frozen` due
+    /// to a foreign write this will produce a `ProtectedTransition(Active, Frozen)`.
+    /// This kind of error can only occur on foreign accesses.
+    ProtectedTransition(Permission, Permission),
+    /// Cannot deallocate because some tag in the allocation is strongly protected.
+    /// This kind of error can only occur on deallocations.
+    ProtectedDealloc,
+}
+
+/// Failures that can occur during the execution of Tree Borrows procedures.
+pub(super) struct TbError<'node> {
+    /// What failure occurred.
+    pub error_kind: TransitionError,
+    /// The tag on which the error was triggered.
+    /// On protector violations, this is the tag that was protected.
+    /// On accesses rejected due to insufficient permissions, this is the
+    /// tag that lacked those permissions.
+    pub faulty_tag: &'node NodeDebugInfo,
+    /// Whether this was a Read or Write access. This field is ignored
+    /// when the error was triggered by a deallocation.
+    pub access_kind: AccessKind,
+    /// Which tag the access that caused this error was made through, i.e.
+    /// which tag was used to read/write/deallocate.
+    pub tag_of_access: &'node NodeDebugInfo,
+}
+
+impl TbError<'_> {
+    /// Produce a UB error.
+    pub fn build<'tcx>(self) -> InterpErrorInfo<'tcx> {
+        use TransitionError::*;
+        err_tb_ub(match self.error_kind {
+            ChildAccessForbidden(perm) => {
+                format!(
+                    "{kind} through {initial} is forbidden because it is a child of {current} which is {perm}.",
+                    kind=self.access_kind,
+                    initial=self.tag_of_access,
+                    current=self.faulty_tag,
+                    perm=perm,
+                )
+            }
+            ProtectedTransition(start, end) => {
+                format!(
+                    "{kind} through {initial} is forbidden because it is a foreign tag for {current}, which would hence change from {start} to {end}, but {current} is protected",
+                    current=self.faulty_tag,
+                    start=start,
+                    end=end,
+                    kind=self.access_kind,
+                    initial=self.tag_of_access,
+                )
+            }
+            ProtectedDealloc => {
+                format!(
+                    "the allocation of {initial} also contains {current} which is strongly protected, cannot deallocate",
+                    initial=self.tag_of_access,
+                    current=self.faulty_tag,
+                )
+            }
+        }).into()
+    }
+}
+
+type S = &'static str;
+/// Pretty-printing details
+///
+/// Example:
+/// ```
+/// DisplayFmtWrapper {
+///     top: '>',
+///     bot: '<',
+///     warning_text: "Some tags have been hidden",
+/// }
+/// ```
+/// will wrap the entire text with
+/// ```text
+/// >>>>>>>>>>>>>>>>>>>>>>>>>>
+/// Some tags have been hidden
+///
+/// [ main display here ]
+///
+/// <<<<<<<<<<<<<<<<<<<<<<<<<<
+/// ```
+struct DisplayFmtWrapper {
+    /// Character repeated to make the upper border.
+    top: char,
+    /// Character repeated to make the lower border.
+    bot: char,
+    /// Warning about some tags (unnamed) being hidden.
+    warning_text: S,
+}
+
+/// Formating of the permissions on each range.
+///
+/// Example:
+/// ```
+/// DisplayFmtPermission {
+///     open: "[",
+///     sep: "|",
+///     close: "]",
+///     uninit: "___",
+///     range_sep: "..",
+/// }
+/// ```
+/// will show each permission line as
+/// ```text
+/// 0.. 1.. 2.. 3.. 4.. 5
+/// [Act|Res|Frz|Dis|___]
+/// ```
+struct DisplayFmtPermission {
+    /// Text that starts the permission block.
+    open: S,
+    /// Text that separates permissions on different ranges.
+    sep: S,
+    /// Text that ends the permission block.
+    close: S,
+    /// Text to show when a permission is not initialized.
+    /// Should have the same width as a `Permission`'s `.short_name()`, i.e.
+    /// 3 if using the `Res/Act/Frz/Dis` notation.
+    uninit: S,
+    /// Text to separate the `start` and `end` values of a range.
+    range_sep: S,
+}
+
+/// Formating of the tree structure.
+///
+/// Example:
+/// ```
+/// DisplayFmtPadding {
+///     join_middle: "|-",
+///     join_last: "'-",
+///     join_haschild: "-+-",
+///     join_default: "---",
+///     indent_middle: "| ",
+///     indent_last: "  ",
+/// }
+/// ```
+/// will show the tree as
+/// ```text
+/// -+- root
+///  |--+- a
+///  |  '--+- b
+///  |     '---- c
+///  |--+- d
+///  |  '---- e
+///  '---- f
+/// ```
+struct DisplayFmtPadding {
+    /// Connector for a child other than the last.
+    join_middle: S,
+    /// Connector for the last child. Should have the same width as `join_middle`.
+    join_last: S,
+    /// Connector for a node that itself has a child.
+    join_haschild: S,
+    /// Connector for a node that does not have a child. Should have the same width
+    /// as `join_haschild`.
+    join_default: S,
+    /// Indentation when there is a next child.
+    indent_middle: S,
+    /// Indentation for the last child.
+    indent_last: S,
+}
+/// How to show whether a location has been accessed
+///
+/// Example:
+/// ```
+/// DisplayFmtAccess {
+///     yes: " ",
+///     no: "?",
+///     meh: "_",
+/// }
+/// ```
+/// will show states as
+/// ```text
+///  Act
+/// ?Res
+/// ____
+/// ```
+struct DisplayFmtAccess {
+    /// Used when `State.initialized = true`.
+    yes: S,
+    /// Used when `State.initialized = false`.
+    /// Should have the same width as `yes`.
+    no: S,
+    /// Used when there is no `State`.
+    /// Should have the same width as `yes`.
+    meh: S,
+}
+
+/// All parameters to determine how the tree is formated.
+struct DisplayFmt {
+    wrapper: DisplayFmtWrapper,
+    perm: DisplayFmtPermission,
+    padding: DisplayFmtPadding,
+    accessed: DisplayFmtAccess,
+}
+impl DisplayFmt {
+    /// Print the permission with the format
+    /// ` Res`/` Re*`/` Act`/` Frz`/` Dis` for accessed locations
+    /// and `?Res`/`?Re*`/`?Act`/`?Frz`/`?Dis` for unaccessed locations.
+    fn print_perm(&self, perm: Option<LocationState>) -> String {
+        if let Some(perm) = perm {
+            format!(
+                "{ac}{st}",
+                ac = if perm.is_initialized() { self.accessed.yes } else { self.accessed.no },
+                st = perm.permission().short_name(),
+            )
+        } else {
+            format!("{}{}", self.accessed.meh, self.perm.uninit)
+        }
+    }
+
+    /// Print the tag with the format `<XYZ>` if the tag is unnamed,
+    /// and `<XYZ=name>` if the tag is named.
+    fn print_tag(&self, tag: BorTag, name: &Option<String>) -> String {
+        let printable_tag = tag.get();
+        if let Some(name) = name {
+            format!("<{printable_tag}={name}>")
+        } else {
+            format!("<{printable_tag}>")
+        }
+    }
+
+    /// Print extra text if the tag has a protector.
+    fn print_protector(&self, protector: Option<&ProtectorKind>) -> &'static str {
+        protector
+            .map(|p| {
+                match *p {
+                    ProtectorKind::WeakProtector => " Weakly protected",
+                    ProtectorKind::StrongProtector => " Strongly protected",
+                }
+            })
+            .unwrap_or("")
+    }
+}
+
+/// Track the indentation of the tree.
+struct DisplayIndent {
+    curr: String,
+}
+impl DisplayIndent {
+    fn new() -> Self {
+        Self { curr: "    ".to_string() }
+    }
+
+    /// Increment the indentation by one. Note: need to know if this
+    /// is the last child or not because the presence of other children
+    /// changes the way the indentation is shown.
+    fn increment(&mut self, formatter: &DisplayFmt, is_last: bool) {
+        self.curr.push_str(if is_last {
+            formatter.padding.indent_last
+        } else {
+            formatter.padding.indent_middle
+        });
+    }
+
+    /// Pop the last level of indentation.
+    fn decrement(&mut self, formatter: &DisplayFmt) {
+        for _ in 0..formatter.padding.indent_last.len() {
+            let _ = self.curr.pop();
+        }
+    }
+
+    /// Print the current indentation.
+    fn write(&self, s: &mut String) {
+        s.push_str(&self.curr);
+    }
+}
+
+/// Repeat a character a number of times.
+fn char_repeat(c: char, n: usize) -> String {
+    std::iter::once(c).cycle().take(n).collect::<String>()
+}
+
+/// Extracted information from the tree, in a form that is readily accessible
+/// for printing. I.e. resolve parent-child pointers into an actual tree,
+/// zip permissions with their tag, remove wrappers, stringify data.
+struct DisplayRepr {
+    tag: BorTag,
+    name: Option<String>,
+    rperm: Vec<Option<LocationState>>,
+    children: Vec<DisplayRepr>,
+}
+
+impl DisplayRepr {
+    fn from(tree: &Tree, show_unnamed: bool) -> Option<Self> {
+        let mut v = Vec::new();
+        extraction_aux(tree, tree.root, show_unnamed, &mut v);
+        let Some(root) = v.pop() else {
+            if show_unnamed {
+                unreachable!("This allocation contains no tags, not even a root. This should not happen.");
+            }
+            eprintln!("This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags.");
+            return None;
+        };
+        assert!(v.is_empty());
+        return Some(root);
+
+        fn extraction_aux(
+            tree: &Tree,
+            idx: UniIndex,
+            show_unnamed: bool,
+            acc: &mut Vec<DisplayRepr>,
+        ) {
+            let node = tree.nodes.get(idx).unwrap();
+            let name = node.debug_info.name.clone();
+            let children_sorted = {
+                let mut children = node.children.iter().cloned().collect::<Vec<_>>();
+                children.sort_by_key(|idx| tree.nodes.get(*idx).unwrap().tag);
+                children
+            };
+            if !show_unnamed && name.is_none() {
+                // We skip this node
+                for child_idx in children_sorted {
+                    extraction_aux(tree, child_idx, show_unnamed, acc);
+                }
+            } else {
+                // We take this node
+                let rperm = tree
+                    .rperms
+                    .iter_all()
+                    .map(move |(_offset, perms)| {
+                        let perm = perms.get(idx);
+                        perm.cloned()
+                    })
+                    .collect::<Vec<_>>();
+                let mut children = Vec::new();
+                for child_idx in children_sorted {
+                    extraction_aux(tree, child_idx, show_unnamed, &mut children);
+                }
+                acc.push(DisplayRepr { tag: node.tag, name, rperm, children });
+            }
+        }
+    }
+    fn print(
+        &self,
+        fmt: &DisplayFmt,
+        indenter: &mut DisplayIndent,
+        protected_tags: &FxHashMap<BorTag, ProtectorKind>,
+        ranges: Vec<Range<u64>>,
+        print_warning: bool,
+    ) {
+        let mut block = Vec::new();
+        // Push the header and compute the required paddings for the body.
+        // Header looks like this: `0.. 1.. 2.. 3.. 4.. 5.. 6.. 7.. 8`,
+        // and is properly aligned with the `|` of the body.
+        let (range_header, range_padding) = {
+            let mut header_top = String::new();
+            header_top.push_str("0..");
+            let mut padding = Vec::new();
+            for (i, range) in ranges.iter().enumerate() {
+                if i > 0 {
+                    header_top.push_str(fmt.perm.range_sep);
+                }
+                let s = range.end.to_string();
+                let l = s.chars().count() + fmt.perm.range_sep.chars().count();
+                {
+                    let target_len =
+                        fmt.perm.uninit.chars().count() + fmt.accessed.yes.chars().count() + 1;
+                    let tot_len = target_len.max(l);
+                    let header_top_pad_len = target_len.saturating_sub(l);
+                    let body_pad_len = tot_len.saturating_sub(target_len);
+                    header_top.push_str(&format!("{}{}", char_repeat(' ', header_top_pad_len), s));
+                    padding.push(body_pad_len);
+                }
+            }
+            ([header_top], padding)
+        };
+        for s in range_header {
+            block.push(s);
+        }
+        // This is the actual work
+        print_aux(
+            self,
+            &range_padding,
+            fmt,
+            indenter,
+            protected_tags,
+            true, /* root _is_ the last child */
+            &mut block,
+        );
+        // Then it's just prettifying it with a border of dashes.
+        {
+            let wr = &fmt.wrapper;
+            let max_width = {
+                let block_width = block.iter().map(|s| s.chars().count()).max().unwrap();
+                if print_warning {
+                    block_width.max(wr.warning_text.chars().count())
+                } else {
+                    block_width
+                }
+            };
+            eprintln!("{}", char_repeat(wr.top, max_width));
+            if print_warning {
+                eprintln!("{}", wr.warning_text,);
+            }
+            for line in block {
+                eprintln!("{line}");
+            }
+            eprintln!("{}", char_repeat(wr.bot, max_width));
+        }
+
+        // Here is the function that does the heavy lifting
+        fn print_aux(
+            tree: &DisplayRepr,
+            padding: &[usize],
+            fmt: &DisplayFmt,
+            indent: &mut DisplayIndent,
+            protected_tags: &FxHashMap<BorTag, ProtectorKind>,
+            is_last_child: bool,
+            acc: &mut Vec<String>,
+        ) {
+            let mut line = String::new();
+            // Format the permissions on each range.
+            // Looks like `| Act| Res| Res| Act|`.
+            line.push_str(fmt.perm.open);
+            for (i, (perm, &pad)) in tree.rperm.iter().zip(padding.iter()).enumerate() {
+                if i > 0 {
+                    line.push_str(fmt.perm.sep);
+                }
+                let show_perm = fmt.print_perm(*perm);
+                line.push_str(&format!("{}{}", char_repeat(' ', pad), show_perm));
+            }
+            line.push_str(fmt.perm.close);
+            // Format the tree structure.
+            // Main difficulty is handling the indentation properly.
+            indent.write(&mut line);
+            {
+                // padding
+                line.push_str(if is_last_child {
+                    fmt.padding.join_last
+                } else {
+                    fmt.padding.join_middle
+                });
+                line.push_str(fmt.padding.join_default);
+                line.push_str(if tree.children.is_empty() {
+                    fmt.padding.join_default
+                } else {
+                    fmt.padding.join_haschild
+                });
+                line.push_str(fmt.padding.join_default);
+                line.push_str(fmt.padding.join_default);
+            }
+            line.push_str(&fmt.print_tag(tree.tag, &tree.name));
+            let protector = protected_tags.get(&tree.tag);
+            line.push_str(fmt.print_protector(protector));
+            // Push the line to the accumulator then recurse.
+            acc.push(line);
+            let nb_children = tree.children.len();
+            for (i, child) in tree.children.iter().enumerate() {
+                indent.increment(fmt, is_last_child);
+                print_aux(child, padding, fmt, indent, protected_tags, i + 1 == nb_children, acc);
+                indent.decrement(fmt);
+            }
+        }
+    }
+}
+
+const DEFAULT_FORMATTER: DisplayFmt = DisplayFmt {
+    wrapper: DisplayFmtWrapper {
+        top: '─',
+        bot: '─',
+        warning_text: "Warning: this tree is indicative only. Some tags may have been hidden.",
+    },
+    perm: DisplayFmtPermission { open: "|", sep: "|", close: "|", uninit: "---", range_sep: ".." },
+    padding: DisplayFmtPadding {
+        join_middle: "├",
+        join_last: "â””",
+        indent_middle: "│ ",
+        indent_last: "  ",
+        join_haschild: "┬",
+        join_default: "─",
+    },
+    accessed: DisplayFmtAccess { yes: " ", no: "?", meh: "-" },
+};
+
+impl<'tcx> Tree {
+    /// Display the contents of the tree.
+    pub fn print_tree(
+        &self,
+        protected_tags: &FxHashMap<BorTag, ProtectorKind>,
+        show_unnamed: bool,
+    ) -> InterpResult<'tcx> {
+        let mut indenter = DisplayIndent::new();
+        let ranges = self.rperms.iter_all().map(|(range, _perms)| range).collect::<Vec<_>>();
+        if let Some(repr) = DisplayRepr::from(self, show_unnamed) {
+            repr.print(
+                &DEFAULT_FORMATTER,
+                &mut indenter,
+                protected_tags,
+                ranges,
+                /* print warning message about tags not shown */ !show_unnamed,
+            );
+        }
+        Ok(())
+    }
+}
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
new file mode 100644
index 00000000000..2297ceb1259
--- /dev/null
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -0,0 +1,539 @@
+use log::trace;
+
+use rustc_target::abi::{Abi, Size};
+
+use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind, RetagFields};
+use rustc_middle::{
+    mir::{Mutability, RetagKind},
+    ty::{
+        self,
+        layout::{HasParamEnv, LayoutOf},
+        Ty,
+    },
+};
+
+use crate::*;
+
+mod diagnostics;
+mod perms;
+mod tree;
+mod unimap;
+use perms::Permission;
+pub use tree::Tree;
+
+pub type AllocState = Tree;
+
+pub fn err_tb_ub<'tcx>(msg: String) -> InterpError<'tcx> {
+    err_machine_stop!(TerminationInfo::TreeBorrowsUb { msg })
+}
+
+impl<'tcx> Tree {
+    /// Create a new allocation, i.e. a new tree
+    pub fn new_allocation(
+        id: AllocId,
+        size: Size,
+        state: &mut GlobalStateInner,
+        _kind: MemoryKind<machine::MiriMemoryKind>,
+        machine: &MiriMachine<'_, 'tcx>,
+    ) -> Self {
+        let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root
+        Tree::new(tag, size)
+    }
+
+    /// Check that an access on the entire range is permitted, and update
+    /// the tree.
+    pub fn before_memory_access(
+        &mut self,
+        access_kind: AccessKind,
+        alloc_id: AllocId,
+        prov: ProvenanceExtra,
+        range: AllocRange,
+        machine: &MiriMachine<'_, 'tcx>,
+    ) -> InterpResult<'tcx> {
+        trace!(
+            "{} with tag {:?}: {:?}, size {}",
+            access_kind,
+            prov,
+            Pointer::new(alloc_id, range.start),
+            range.size.bytes(),
+        );
+        // TODO: for now we bail out on wildcard pointers. Eventually we should
+        // handle them as much as we can.
+        let tag = match prov {
+            ProvenanceExtra::Concrete(tag) => tag,
+            ProvenanceExtra::Wildcard => return Ok(()),
+        };
+        let global = machine.borrow_tracker.as_ref().unwrap();
+        self.perform_access(access_kind, tag, range, global)
+    }
+
+    /// Check that this pointer has permission to deallocate this range.
+    pub fn before_memory_deallocation(
+        &mut self,
+        _alloc_id: AllocId,
+        prov: ProvenanceExtra,
+        range: AllocRange,
+        machine: &MiriMachine<'_, 'tcx>,
+    ) -> InterpResult<'tcx> {
+        // TODO: for now we bail out on wildcard pointers. Eventually we should
+        // handle them as much as we can.
+        let tag = match prov {
+            ProvenanceExtra::Concrete(tag) => tag,
+            ProvenanceExtra::Wildcard => return Ok(()),
+        };
+        let global = machine.borrow_tracker.as_ref().unwrap();
+        self.dealloc(tag, range, global)
+    }
+
+    pub fn expose_tag(&mut self, _tag: BorTag) {
+        // TODO
+    }
+}
+
+/// Policy for a new borrow.
+#[derive(Debug, Clone, Copy)]
+struct NewPermission {
+    /// Whether this borrow requires a read access on its parent.
+    /// `perform_read_access` is `true` for all pointers marked `dereferenceable`.
+    perform_read_access: bool,
+    /// Which permission should the pointer start with.
+    initial_state: Permission,
+    /// Whether this pointer is part of the arguments of a function call.
+    /// `protector` is `Some(_)` for all pointers marked `noalias`.
+    protector: Option<ProtectorKind>,
+}
+
+impl<'tcx> NewPermission {
+    /// Determine NewPermission of the reference from the type of the pointee.
+    fn from_ref_ty(
+        pointee: Ty<'tcx>,
+        mutability: Mutability,
+        kind: RetagKind,
+        cx: &crate::MiriInterpCx<'_, 'tcx>,
+    ) -> Option<Self> {
+        let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env());
+        let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env());
+        let initial_state = match mutability {
+            Mutability::Mut if ty_is_unpin => Permission::new_unique_2phase(ty_is_freeze),
+            Mutability::Not if ty_is_freeze => Permission::new_frozen(),
+            // Raw pointers never enter this function so they are not handled.
+            // However raw pointers are not the only pointers that take the parent
+            // tag, this also happens for `!Unpin` `&mut`s and interior mutable
+            // `&`s, which are excluded above.
+            _ => return None,
+        };
+        // This field happens to be redundant since right now we always do a read,
+        // but it could be useful in the future.
+        let perform_read_access = true;
+
+        let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
+        Some(Self { perform_read_access, initial_state, protector })
+    }
+
+    // Boxes are not handled by `from_ref_ty`, they need special behavior
+    // implemented here.
+    fn from_box_ty(
+        ty: Ty<'tcx>,
+        kind: RetagKind,
+        cx: &crate::MiriInterpCx<'_, 'tcx>,
+    ) -> Option<Self> {
+        let pointee = ty.builtin_deref(true).unwrap().ty;
+        pointee.is_unpin(*cx.tcx, cx.param_env()).then_some(()).map(|()| {
+            // Regular `Unpin` box, give it `noalias` but only a weak protector
+            // because it is valid to deallocate it within the function.
+            let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.param_env());
+            Self {
+                perform_read_access: true,
+                initial_state: Permission::new_unique_2phase(ty_is_freeze),
+                protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
+            }
+        })
+    }
+}
+
+/// Retagging/reborrowing.
+/// Policy on which permission to grant to each pointer should be left to
+/// the implementation of NewPermission.
+impl<'mir: 'ecx, 'tcx: 'mir, 'ecx> EvalContextPrivExt<'mir, 'tcx, 'ecx>
+    for crate::MiriInterpCx<'mir, 'tcx>
+{
+}
+trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// Returns the `AllocId` the reborrow was done in, if there is some actual
+    /// memory associated with this pointer. Returns `None` if there is no actual
+    /// memory allocated. Also checks that the reborrow of size `ptr_size` is
+    /// within bounds of the allocation.
+    ///
+    /// Also returns the tag that the pointer should get, which is essentially
+    /// `if new_perm.is_some() { new_tag } else { parent_tag }` along with
+    /// some logging (always) and fake reads (if `new_perm` is
+    /// `Some(NewPermission { perform_read_access: true }`).
+    fn tb_reborrow(
+        &mut self,
+        place: &MPlaceTy<'tcx, Provenance>, // parent tag extracted from here
+        ptr_size: Size,
+        new_perm: Option<NewPermission>,
+        new_tag: BorTag,
+    ) -> InterpResult<'tcx, Option<(AllocId, BorTag)>> {
+        let this = self.eval_context_mut();
+
+        // It is crucial that this gets called on all code paths, to ensure we track tag creation.
+        let log_creation = |this: &MiriInterpCx<'mir, 'tcx>,
+                            loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag
+         -> InterpResult<'tcx> {
+            let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
+            let ty = place.layout.ty;
+            if global.tracked_pointer_tags.contains(&new_tag) {
+                let kind_str = format!("{new_perm:?} (pointee type {ty})");
+                this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
+                    new_tag.inner(),
+                    Some(kind_str),
+                    loc.map(|(alloc_id, base_offset, orig_tag)| (alloc_id, alloc_range(base_offset, ptr_size), orig_tag)),
+                ));
+            }
+            drop(global); // don't hold that reference any longer than we have to
+            Ok(())
+        };
+
+        let (alloc_id, base_offset, parent_prov) = if ptr_size > Size::ZERO {
+            this.ptr_get_alloc_id(place.ptr)?
+        } else {
+            match this.ptr_try_get_alloc_id(place.ptr) {
+                Ok(data) => data,
+                Err(_) => {
+                    // This pointer doesn't come with an AllocId, so there's no
+                    // memory to do retagging in.
+                    trace!(
+                        "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
+                        new_tag,
+                        place.ptr,
+                        place.layout.ty,
+                    );
+                    log_creation(this, None)?;
+                    return Ok(None);
+                }
+            }
+        };
+        let orig_tag = match parent_prov {
+            ProvenanceExtra::Wildcard => return Ok(None), // TODO: handle wildcard pointers
+            ProvenanceExtra::Concrete(tag) => tag,
+        };
+
+        // Protection against trying to get a reference to a vtable:
+        // vtables do not have an alloc_extra so the call to
+        // `get_alloc_extra` that follows fails.
+        let (alloc_size, _align, alloc_kind) = this.get_alloc_info(alloc_id);
+        if ptr_size == Size::ZERO && !matches!(alloc_kind, AllocKind::LiveData) {
+            return Ok(Some((alloc_id, orig_tag)));
+        }
+
+        log_creation(this, Some((alloc_id, base_offset, parent_prov)))?;
+
+        // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
+        if base_offset + ptr_size > alloc_size {
+            throw_ub!(PointerOutOfBounds {
+                alloc_id,
+                alloc_size,
+                ptr_offset: this.target_usize_to_isize(base_offset.bytes()),
+                ptr_size,
+                msg: CheckInAllocMsg::InboundsTest
+            });
+        }
+
+        trace!(
+            "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
+            new_tag,
+            orig_tag,
+            place.layout.ty,
+            Pointer::new(alloc_id, base_offset),
+            ptr_size.bytes()
+        );
+
+        let Some(new_perm) = new_perm else { return Ok(Some((alloc_id, orig_tag))); };
+
+        if let Some(protect) = new_perm.protector {
+            // We register the protection in two different places.
+            // This makes creating a protector slower, but checking whether a tag
+            // is protected faster.
+            this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
+            this.machine
+                .borrow_tracker
+                .as_mut()
+                .expect("We should have borrow tracking data")
+                .get_mut()
+                .protected_tags
+                .insert(new_tag, protect);
+        }
+
+        let alloc_extra = this.get_alloc_extra(alloc_id)?;
+        let range = alloc_range(base_offset, ptr_size);
+        let mut tree_borrows = alloc_extra.borrow_tracker_tb().borrow_mut();
+
+        if new_perm.perform_read_access {
+            // Count this reborrow as a read access
+            let global = &this.machine.borrow_tracker.as_ref().unwrap();
+            tree_borrows.perform_access(AccessKind::Read, orig_tag, range, global)?;
+            if let Some(data_race) = alloc_extra.data_race.as_ref() {
+                data_race.read(alloc_id, range, &this.machine)?;
+            }
+        }
+
+        // Record the parent-child pair in the tree.
+        tree_borrows.new_child(orig_tag, new_tag, new_perm.initial_state, range)?;
+        Ok(Some((alloc_id, new_tag)))
+    }
+
+    /// Retags an indidual pointer, returning the retagged version.
+    fn tb_retag_reference(
+        &mut self,
+        val: &ImmTy<'tcx, Provenance>,
+        new_perm: Option<NewPermission>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        let this = self.eval_context_mut();
+        // We want a place for where the ptr *points to*, so we get one.
+        let place = this.ref_to_mplace(val)?;
+
+        // Get a lower bound of the size of this place.
+        // (When `extern type` are involved, use the size of the known prefix.)
+        let size = this
+            .size_and_align_of_mplace(&place)?
+            .map(|(size, _)| size)
+            .unwrap_or(place.layout.size);
+
+        // This new tag is not guaranteed to actually be used.
+        //
+        // If you run out of tags, consider the following optimization: adjust `tb_reborrow`
+        // so that rather than taking as input a fresh tag and deciding whether it uses this
+        // one or the parent it instead just returns whether a new tag should be created.
+        // This will avoid creating tags than end up never being used.
+        let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
+
+        // Compute the actual reborrow.
+        let reborrowed = this.tb_reborrow(&place, size, new_perm, new_tag)?;
+
+        // Adjust pointer.
+        let new_place = place.map_provenance(|p| {
+            p.map(|prov| {
+                match reborrowed {
+                    Some((alloc_id, actual_tag)) => {
+                        // If `reborrow` could figure out the AllocId of this ptr, hard-code it into the new one.
+                        // Even if we started out with a wildcard, this newly retagged pointer is tied to that allocation.
+                        Provenance::Concrete { alloc_id, tag: actual_tag }
+                    }
+                    None => {
+                        // Looks like this has to stay a wildcard pointer.
+                        assert!(matches!(prov, Provenance::Wildcard));
+                        Provenance::Wildcard
+                    }
+                }
+            })
+        });
+
+        // Return new pointer.
+        Ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout))
+    }
+}
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// Retag a pointer. References are passed to `from_ref_ty` and
+    /// raw pointers are never reborrowed.
+    fn tb_retag_ptr_value(
+        &mut self,
+        kind: RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        let this = self.eval_context_mut();
+        let new_perm = if let &ty::Ref(_, pointee, mutability) = val.layout.ty.kind() {
+            NewPermission::from_ref_ty(pointee, mutability, kind, this)
+        } else {
+            None
+        };
+        this.tb_retag_reference(val, new_perm)
+    }
+
+    /// Retag all pointers that are stored in this place.
+    fn tb_retag_place_contents(
+        &mut self,
+        kind: RetagKind,
+        place: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
+        let mut visitor = RetagVisitor { ecx: this, kind, retag_fields };
+        return visitor.visit_value(place);
+
+        // The actual visitor.
+        struct RetagVisitor<'ecx, 'mir, 'tcx> {
+            ecx: &'ecx mut MiriInterpCx<'mir, 'tcx>,
+            kind: RetagKind,
+            retag_fields: RetagFields,
+        }
+        impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
+            #[inline(always)] // yes this helps in our benchmarks
+            fn retag_ptr_inplace(
+                &mut self,
+                place: &PlaceTy<'tcx, Provenance>,
+                new_perm: Option<NewPermission>,
+            ) -> InterpResult<'tcx> {
+                let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
+                let val = self.ecx.tb_retag_reference(&val, new_perm)?;
+                self.ecx.write_immediate(*val, place)?;
+                Ok(())
+            }
+        }
+        impl<'ecx, 'mir, 'tcx> MutValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>>
+            for RetagVisitor<'ecx, 'mir, 'tcx>
+        {
+            type V = PlaceTy<'tcx, Provenance>;
+
+            #[inline(always)]
+            fn ecx(&mut self) -> &mut MiriInterpCx<'mir, 'tcx> {
+                self.ecx
+            }
+
+            fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+                let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx);
+                self.retag_ptr_inplace(place, new_perm)
+            }
+
+            fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+                // If this place is smaller than a pointer, we know that it can't contain any
+                // pointers we need to retag, so we can stop recursion early.
+                // This optimization is crucial for ZSTs, because they can contain way more fields
+                // than we can ever visit.
+                if place.layout.is_sized() && place.layout.size < self.ecx.pointer_size() {
+                    return Ok(());
+                }
+
+                // Check the type of this value to see what to do with it (retag, or recurse).
+                match place.layout.ty.kind() {
+                    &ty::Ref(_, pointee, mutability) => {
+                        let new_perm =
+                            NewPermission::from_ref_ty(pointee, mutability, self.kind, self.ecx);
+                        self.retag_ptr_inplace(place, new_perm)?;
+                    }
+                    ty::RawPtr(_) => {
+                        // We definitely do *not* want to recurse into raw pointers -- wide raw
+                        // pointers have fields, and for dyn Trait pointees those can have reference
+                        // type!
+                        // We also do not want to reborrow them.
+                    }
+                    ty::Adt(adt, _) if adt.is_box() => {
+                        // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
+                        // (Yes this means we technically also recursively retag the allocator itself
+                        // even if field retagging is not enabled. *shrug*)
+                        self.walk_value(place)?;
+                    }
+                    _ => {
+                        // Not a reference/pointer/box. Only recurse if configured appropriately.
+                        let recurse = match self.retag_fields {
+                            RetagFields::No => false,
+                            RetagFields::Yes => true,
+                            RetagFields::OnlyScalar => {
+                                // Matching `ArgAbi::new` at the time of writing, only fields of
+                                // `Scalar` and `ScalarPair` ABI are considered.
+                                matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
+                            }
+                        };
+                        if recurse {
+                            self.walk_value(place)?;
+                        }
+                    }
+                }
+
+                Ok(())
+            }
+        }
+    }
+
+    /// After a stack frame got pushed, retag the return place so that we are sure
+    /// it does not alias with anything.
+    ///
+    /// This is a HACK because there is nothing in MIR that would make the retag
+    /// explicit. Also see <https://github.com/rust-lang/rust/issues/71117>.
+    fn tb_retag_return_place(&mut self) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        //this.debug_hint_location();
+        let return_place = &this.frame().return_place;
+        if return_place.layout.is_zst() {
+            // There may not be any memory here, nothing to do.
+            return Ok(());
+        }
+        // We need this to be in-memory to use tagged pointers.
+        let return_place = this.force_allocation(&return_place.clone())?;
+
+        // We have to turn the place into a pointer to use the existing code.
+        // (The pointer type does not matter, so we use a raw pointer.)
+        let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
+        let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
+        // Reborrow it. With protection! That is part of the point.
+        // FIXME: do we truly want a 2phase borrow here?
+        let new_perm = Some(NewPermission {
+            initial_state: Permission::new_unique_2phase(/*freeze*/ false),
+            perform_read_access: true,
+            protector: Some(ProtectorKind::StrongProtector),
+        });
+        let val = this.tb_retag_reference(&val, new_perm)?;
+        // And use reborrowed pointer for return place.
+        let return_place = this.ref_to_mplace(&val)?;
+        this.frame_mut().return_place = return_place.into();
+
+        Ok(())
+    }
+
+    /// Mark the given tag as exposed. It was found on a pointer with the given AllocId.
+    fn tb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        // Function pointers and dead objects don't have an alloc_extra so we ignore them.
+        // This is okay because accessing them is UB anyway, no need for any Tree Borrows checks.
+        // NOT using `get_alloc_extra_mut` since this might be a read-only allocation!
+        let (_size, _align, kind) = this.get_alloc_info(alloc_id);
+        match kind {
+            AllocKind::LiveData => {
+                // This should have alloc_extra data, but `get_alloc_extra` can still fail
+                // if converting this alloc_id from a global to a local one
+                // uncovers a non-supported `extern static`.
+                let alloc_extra = this.get_alloc_extra(alloc_id)?;
+                trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}");
+                alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag);
+            }
+            AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+                // No tree borrows on these allocations.
+            }
+        }
+        Ok(())
+    }
+
+    /// Display the tree.
+    fn print_tree(&mut self, alloc_id: AllocId, show_unnamed: bool) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let alloc_extra = this.get_alloc_extra(alloc_id)?;
+        let tree_borrows = alloc_extra.borrow_tracker_tb().borrow();
+        let borrow_tracker = &this.machine.borrow_tracker.as_ref().unwrap().borrow();
+        tree_borrows.print_tree(&borrow_tracker.protected_tags, show_unnamed)
+    }
+
+    /// Give a name to the pointer, usually the name it has in the source code (for debugging).
+    /// The name given is `name` and the pointer that receives it is the `nth_parent`
+    /// of `ptr` (with 0 representing `ptr` itself)
+    fn tb_give_pointer_debug_name(
+        &mut self,
+        ptr: Pointer<Option<Provenance>>,
+        nth_parent: u8,
+        name: &str,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let (tag, alloc_id) = match ptr.provenance {
+            Some(Provenance::Concrete { tag, alloc_id }) => (tag, alloc_id),
+            _ => {
+                eprintln!("Can't give the name {name} to Wildcard pointer");
+                return Ok(());
+            }
+        };
+        let alloc_extra = this.get_alloc_extra(alloc_id)?;
+        let mut tree_borrows = alloc_extra.borrow_tracker_tb().borrow_mut();
+        tree_borrows.give_pointer_debug_name(tag, nth_parent, name)
+    }
+}
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
new file mode 100644
index 00000000000..04b8e1df576
--- /dev/null
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
@@ -0,0 +1,307 @@
+use std::cmp::{Ordering, PartialOrd};
+use std::fmt;
+
+use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness;
+use crate::borrow_tracker::AccessKind;
+
+/// The activation states of a pointer
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum PermissionPriv {
+    /// represents: a local reference that has not yet been written to;
+    /// allows: child reads, foreign reads, foreign writes if type is freeze;
+    /// rejects: child writes (Active), foreign writes (Disabled, except if type is not freeze).
+    /// special case: behaves differently when protected to adhere more closely to noalias
+    Reserved { ty_is_freeze: bool },
+    /// represents: a unique pointer;
+    /// allows: child reads, child writes;
+    /// rejects: foreign reads (Frozen), foreign writes (Disabled).
+    Active,
+    /// represents: a shared pointer;
+    /// allows: all read accesses;
+    /// rejects child writes (UB), foreign writes (Disabled).
+    Frozen,
+    /// represents: a dead pointer;
+    /// allows: all foreign accesses;
+    /// rejects: all child accesses (UB).
+    Disabled,
+}
+use PermissionPriv::*;
+
+impl PartialOrd for PermissionPriv {
+    /// PermissionPriv is ordered as follows:
+    /// - Reserved(_) < Active < Frozen < Disabled;
+    /// - different kinds of `Reserved` (with or without interior mutability)
+    /// are incomparable to each other.
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        use Ordering::*;
+        Some(match (self, other) {
+            (a, b) if a == b => Equal,
+            (Disabled, _) => Greater,
+            (_, Disabled) => Less,
+            (Frozen, _) => Greater,
+            (_, Frozen) => Less,
+            (Active, _) => Greater,
+            (_, Active) => Less,
+            (Reserved { .. }, Reserved { .. }) => return None,
+        })
+    }
+}
+
+/// This module controls how each permission individually reacts to an access.
+/// Although these functions take `protected` as an argument, this is NOT because
+/// we check protector violations here, but because some permissions behave differently
+/// when protected.
+mod transition {
+    use super::*;
+    /// A child node was read-accessed: UB on Disabled, noop on the rest.
+    fn child_read(state: PermissionPriv, _protected: bool) -> Option<PermissionPriv> {
+        Some(match state {
+            Disabled => return None,
+            // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read
+            // accesses, since the data is not being mutated. Hence the `{ .. }`
+            readable @ (Reserved { .. } | Active | Frozen) => readable,
+        })
+    }
+
+    /// A non-child node was read-accessed: noop on non-protected Reserved, advance to Frozen otherwise.
+    fn foreign_read(state: PermissionPriv, protected: bool) -> Option<PermissionPriv> {
+        use Option::*;
+        Some(match state {
+            // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read
+            // accesses, since the data is not being mutated. Hence the `{ .. }`
+            res @ Reserved { .. } if !protected => res,
+            Reserved { .. } => Frozen, // protected reserved
+            Active => Frozen,
+            non_writeable @ (Frozen | Disabled) => non_writeable,
+        })
+    }
+
+    /// A child node was write-accessed: `Reserved` must become `Active` to obtain
+    /// write permissions, `Frozen` and `Disabled` cannot obtain such permissions and produce UB.
+    fn child_write(state: PermissionPriv, _protected: bool) -> Option<PermissionPriv> {
+        Some(match state {
+            // A write always activates the 2-phase borrow, even with interior
+            // mutability
+            Reserved { .. } | Active => Active,
+            Frozen | Disabled => return None,
+        })
+    }
+
+    /// A non-child node was write-accessed: this makes everything `Disabled` except for
+    /// non-protected interior mutable `Reserved` which stay the same.
+    fn foreign_write(state: PermissionPriv, protected: bool) -> Option<PermissionPriv> {
+        Some(match state {
+            cell @ Reserved { ty_is_freeze: false } if !protected => cell,
+            _ => Disabled,
+        })
+    }
+
+    /// Dispatch handler depending on the kind of access and its position.
+    pub(super) fn perform_access(
+        kind: AccessKind,
+        rel_pos: AccessRelatedness,
+        child: PermissionPriv,
+        protected: bool,
+    ) -> Option<PermissionPriv> {
+        match (kind, rel_pos.is_foreign()) {
+            (AccessKind::Write, true) => foreign_write(child, protected),
+            (AccessKind::Read, true) => foreign_read(child, protected),
+            (AccessKind::Write, false) => child_write(child, protected),
+            (AccessKind::Read, false) => child_read(child, protected),
+        }
+    }
+}
+
+impl PermissionPriv {
+    /// Determines whether a transition that occured is compatible with the presence
+    /// of a Protector. This is not included in the `transition` functions because
+    /// it would distract from the few places where the transition is modified
+    /// because of a protector, but not forbidden.
+    fn protector_allows_transition(self, new: Self) -> bool {
+        match (self, new) {
+            _ if self == new => true,
+            // It is always a protector violation to not be readable anymore
+            (_, Disabled) => false,
+            // In the case of a `Reserved` under a protector, both transitions
+            // `Reserved => Active` and `Reserved => Frozen` can legitimately occur.
+            // The first is standard (Child Write), the second is for Foreign Writes
+            // on protected Reserved where we must ensure that the pointer is not
+            // written to in the future.
+            (Reserved { .. }, Active) | (Reserved { .. }, Frozen) => true,
+            // This pointer should have stayed writeable for the whole function
+            (Active, Frozen) => false,
+            _ => unreachable!("Transition from {self:?} to {new:?} should never be possible"),
+        }
+    }
+}
+
+/// Public interface to the state machine that controls read-write permissions.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Permission(PermissionPriv);
+
+impl fmt::Display for Permission {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self.0 {
+                PermissionPriv::Reserved { .. } => "Reserved",
+                PermissionPriv::Active => "Active",
+                PermissionPriv::Frozen => "Frozen",
+                PermissionPriv::Disabled => "Disabled",
+            }
+        )
+    }
+}
+
+impl Permission {
+    /// Default initial permission of the root of a new tree.
+    pub fn new_root() -> Self {
+        Self(Active)
+    }
+
+    /// Default initial permission of a reborrowed mutable reference.
+    pub fn new_unique_2phase(ty_is_freeze: bool) -> Self {
+        Self(Reserved { ty_is_freeze })
+    }
+
+    /// Default initial permission of a reborrowed shared reference
+    pub fn new_frozen() -> Self {
+        Self(Frozen)
+    }
+
+    /// Pretty-printing. Needs to be here and not in diagnostics.rs
+    /// because `Self` is private.
+    pub fn short_name(self) -> &'static str {
+        // Make sure there are all of the same length as each other
+        // and also as `diagnostics::DisplayFmtPermission.uninit` otherwise
+        // alignment will be incorrect.
+        match self.0 {
+            Reserved { ty_is_freeze: true } => "Res",
+            Reserved { ty_is_freeze: false } => "Re*",
+            Active => "Act",
+            Frozen => "Frz",
+            Disabled => "Dis",
+        }
+    }
+
+    /// Check that there are no complaints from a possible protector.
+    ///
+    /// Note: this is not in charge of checking that there *is* a protector,
+    /// it should be used as
+    /// ```
+    /// let no_protector_error = if is_protected(tag) {
+    ///     old_perm.protector_allows_transition(new_perm)
+    /// };
+    /// ```
+    pub fn protector_allows_transition(self, new: Self) -> bool {
+        self.0.protector_allows_transition(new.0)
+    }
+
+    /// Apply the transition to the inner PermissionPriv.
+    pub fn perform_access(
+        kind: AccessKind,
+        rel_pos: AccessRelatedness,
+        old_perm: Self,
+        protected: bool,
+    ) -> Option<Self> {
+        let old_state = old_perm.0;
+        transition::perform_access(kind, rel_pos, old_state, protected).map(Self)
+    }
+}
+
+#[cfg(test)]
+mod propagation_optimization_checks {
+    pub use super::*;
+
+    mod util {
+        pub use super::*;
+        impl PermissionPriv {
+            /// Enumerate all states
+            pub fn all() -> impl Iterator<Item = PermissionPriv> {
+                vec![
+                    Active,
+                    Reserved { ty_is_freeze: true },
+                    Reserved { ty_is_freeze: false },
+                    Frozen,
+                    Disabled,
+                ]
+                .into_iter()
+            }
+        }
+
+        impl AccessKind {
+            /// Enumerate all AccessKind.
+            pub fn all() -> impl Iterator<Item = AccessKind> {
+                use AccessKind::*;
+                [Read, Write].into_iter()
+            }
+        }
+
+        impl AccessRelatedness {
+            /// Enumerate all relative positions
+            pub fn all() -> impl Iterator<Item = AccessRelatedness> {
+                use AccessRelatedness::*;
+                [This, StrictChildAccess, AncestorAccess, DistantAccess].into_iter()
+            }
+        }
+    }
+
+    #[test]
+    // For any kind of access, if we do it twice the second should be a no-op.
+    // Even if the protector has disappeared.
+    fn all_transitions_idempotent() {
+        use transition::*;
+        for old in PermissionPriv::all() {
+            for (old_protected, new_protected) in [(true, true), (true, false), (false, false)] {
+                for access in AccessKind::all() {
+                    for rel_pos in AccessRelatedness::all() {
+                        if let Some(new) = perform_access(access, rel_pos, old, old_protected) {
+                            assert_eq!(
+                                new,
+                                perform_access(access, rel_pos, new, new_protected).unwrap()
+                            );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn foreign_read_is_noop_after_write() {
+        use transition::*;
+        let old_access = AccessKind::Write;
+        let new_access = AccessKind::Read;
+        for old in PermissionPriv::all() {
+            for (old_protected, new_protected) in [(true, true), (true, false), (false, false)] {
+                for rel_pos in AccessRelatedness::all().filter(|rel| rel.is_foreign()) {
+                    if let Some(new) = perform_access(old_access, rel_pos, old, old_protected) {
+                        assert_eq!(
+                            new,
+                            perform_access(new_access, rel_pos, new, new_protected).unwrap()
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    #[test]
+    // Check that all transitions are consistent with the order on PermissionPriv,
+    // i.e. Reserved -> Active -> Frozen -> Disabled
+    fn access_transitions_progress_increasing() {
+        use transition::*;
+        for old in PermissionPriv::all() {
+            for protected in [true, false] {
+                for access in AccessKind::all() {
+                    for rel_pos in AccessRelatedness::all() {
+                        if let Some(new) = perform_access(access, rel_pos, old, protected) {
+                            assert!(old <= new);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
new file mode 100644
index 00000000000..86416a0eb1b
--- /dev/null
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -0,0 +1,554 @@
+//! In this file we handle the "Tree" part of Tree Borrows, i.e. all tree
+//! traversal functions, optimizations to trim branches, and keeping track of
+//! the relative position of the access to each node being updated. This of course
+//! also includes the definition of the tree structure.
+//!
+//! Functions here manipulate permissions but are oblivious to them: as
+//! the internals of `Permission` are private, the update process is a black
+//! box. All we need to know here are
+//! - the fact that updates depend only on the old state, the status of protectors,
+//!   and the relative position of the access;
+//! - idempotency properties asserted in `perms.rs` (for optimizations)
+
+use smallvec::SmallVec;
+
+use rustc_const_eval::interpret::InterpResult;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_target::abi::Size;
+
+use crate::borrow_tracker::tree_borrows::{
+    diagnostics::{NodeDebugInfo, TbError, TransitionError},
+    unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap},
+    Permission,
+};
+use crate::borrow_tracker::{AccessKind, GlobalState, ProtectorKind};
+use crate::*;
+
+/// Data for a single *location*.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(super) struct LocationState {
+    /// This pointer's current permission
+    permission: Permission,
+    /// A location is initialized when it is child accessed for the first time,
+    /// and it then stays initialized forever.
+    /// Before initialization we still apply some preemptive transitions on
+    /// `permission` to know what to do in case it ever gets initialized,
+    /// but these can never cause any immediate UB. There can however be UB
+    /// the moment we attempt to initalize (i.e. child-access) because some
+    /// foreign access done between the creation and the initialization is
+    /// incompatible with child accesses.
+    initialized: bool,
+    /// Strongest foreign access whose effects have already been applied to
+    /// this node and all its children since the last child access.
+    /// This is `None` if the most recent access is a child access,
+    /// `Some(Write)` if at least one foreign write access has been applied
+    /// since the previous child access, and `Some(Read)` if at least one
+    /// foreign read and no foreign write have occurred since the last child access.
+    latest_foreign_access: Option<AccessKind>,
+}
+
+impl LocationState {
+    /// Default initial state has never been accessed and has been subjected to no
+    /// foreign access.
+    fn new(permission: Permission) -> Self {
+        Self { permission, initialized: false, latest_foreign_access: None }
+    }
+
+    /// Record that this location was accessed through a child pointer by
+    /// marking it as initialized
+    fn with_access(mut self) -> Self {
+        self.initialized = true;
+        self
+    }
+
+    pub fn is_initialized(&self) -> bool {
+        self.initialized
+    }
+
+    pub fn permission(&self) -> Permission {
+        self.permission
+    }
+}
+
+/// Tree structure with both parents and children since we want to be
+/// able to traverse the tree efficiently in both directions.
+#[derive(Clone, Debug)]
+pub struct Tree {
+    /// Mapping from tags to keys. The key obtained can then be used in
+    /// any of the `UniValMap` relative to this allocation, i.e. both the
+    /// `nodes` and `rperms` of the same `Tree`.
+    /// The parent-child relationship in `Node` is encoded in terms of these same
+    /// keys, so traversing the entire tree needs exactly one access to
+    /// `tag_mapping`.
+    pub(super) tag_mapping: UniKeyMap<BorTag>,
+    /// All nodes of this tree.
+    pub(super) nodes: UniValMap<Node>,
+    /// Maps a tag and a location to a perm, with possible lazy
+    /// initialization.
+    ///
+    /// NOTE: not all tags registered in `nodes` are necessarily in all
+    /// ranges of `rperms`, because `rperms` is in part lazily initialized.
+    /// Just because `nodes.get(key)` is `Some(_)` does not mean you can safely
+    /// `unwrap` any `perm.get(key)`.
+    ///
+    /// We do uphold the fact that `keys(perms)` is a subset of `keys(nodes)`
+    pub(super) rperms: RangeMap<UniValMap<LocationState>>,
+    /// The index of the root node.
+    pub(super) root: UniIndex,
+}
+
+/// A node in the borrow tree. Each node is uniquely identified by a tag via
+/// the `nodes` map of `Tree`.
+#[derive(Clone, Debug)]
+pub(super) struct Node {
+    /// The tag of this node.
+    pub tag: BorTag,
+    /// All tags except the root have a parent tag.
+    pub parent: Option<UniIndex>,
+    /// If the pointer was reborrowed, it has children.
+    // FIXME: bench to compare this to FxHashSet and to other SmallVec sizes
+    pub children: SmallVec<[UniIndex; 4]>,
+    /// Either `Reserved` or `Frozen`, the permission this tag will be lazily initialized
+    /// to on the first access.
+    default_initial_perm: Permission,
+    /// Some extra information useful only for debugging purposes
+    pub debug_info: NodeDebugInfo,
+}
+
+/// Data given to the transition function
+struct NodeAppArgs<'node> {
+    /// Node on which the transition is currently being applied
+    node: &'node Node,
+    /// Mutable access to its permissions
+    perm: UniEntry<'node, LocationState>,
+    /// Relative position of the access
+    rel_pos: AccessRelatedness,
+}
+/// Data given to the error handler
+struct ErrHandlerArgs<'node, InErr> {
+    /// Kind of error that occurred
+    error_kind: InErr,
+    /// Tag that triggered the error (not the tag that was accessed,
+    /// rather the parent tag that had insufficient permissions or the
+    /// non-parent tag that had a protector).
+    faulty_tag: &'node NodeDebugInfo,
+}
+/// Internal contents of `Tree` with the minimum of mutable access for
+/// the purposes of the tree traversal functions: the permissions (`perms`) can be
+/// updated but not the tree structure (`tag_mapping` and `nodes`)
+struct TreeVisitor<'tree> {
+    tag_mapping: &'tree UniKeyMap<BorTag>,
+    nodes: &'tree UniValMap<Node>,
+    perms: &'tree mut UniValMap<LocationState>,
+}
+
+/// Whether to continue exploring the children recursively or not.
+enum ContinueTraversal {
+    Recurse,
+    SkipChildren,
+}
+
+impl<'tree> TreeVisitor<'tree> {
+    // Applies `f_propagate` to every vertex of the tree top-down in the following order: first
+    // all ancestors of `start`, then `start` itself, then children of `start`, then the rest.
+    // This ensures that errors are triggered in the following order
+    // - first invalid accesses with insufficient permissions, closest to the root first,
+    // - then protector violations, closest to `start` first.
+    //
+    // `f_propagate` should follow the following format: for a given `Node` it updates its
+    // `Permission` depending on the position relative to `start` (given by an
+    // `AccessRelatedness`).
+    // It outputs whether the tree traversal for this subree should continue or not.
+    fn traverse_parents_this_children_others<InnErr, OutErr>(
+        mut self,
+        start: BorTag,
+        f_propagate: impl Fn(NodeAppArgs<'_>) -> Result<ContinueTraversal, InnErr>,
+        err_builder: impl Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr,
+    ) -> Result<(), OutErr>
+where {
+        struct TreeVisitAux<NodeApp, ErrHandler> {
+            f_propagate: NodeApp,
+            err_builder: ErrHandler,
+            stack: Vec<(UniIndex, AccessRelatedness)>,
+        }
+        impl<NodeApp, InnErr, OutErr, ErrHandler> TreeVisitAux<NodeApp, ErrHandler>
+        where
+            NodeApp: Fn(NodeAppArgs<'_>) -> Result<ContinueTraversal, InnErr>,
+            ErrHandler: Fn(ErrHandlerArgs<'_, InnErr>) -> OutErr,
+        {
+            fn pop(&mut self) -> Option<(UniIndex, AccessRelatedness)> {
+                self.stack.pop()
+            }
+
+            /// Apply the function to the current `tag`, and push its children
+            /// to the stack of future tags to visit.
+            fn exec_and_visit(
+                &mut self,
+                this: &mut TreeVisitor<'_>,
+                tag: UniIndex,
+                exclude: Option<UniIndex>,
+                rel_pos: AccessRelatedness,
+            ) -> Result<(), OutErr> {
+                // 1. apply the propagation function
+                let node = this.nodes.get(tag).unwrap();
+                let recurse =
+                    (self.f_propagate)(NodeAppArgs { node, perm: this.perms.entry(tag), rel_pos })
+                        .map_err(|error_kind| {
+                            (self.err_builder)(ErrHandlerArgs {
+                                error_kind,
+                                faulty_tag: &node.debug_info,
+                            })
+                        })?;
+                // 2. add the children to the stack for future traversal
+                if matches!(recurse, ContinueTraversal::Recurse) {
+                    let child_rel = rel_pos.for_child();
+                    for &child in node.children.iter() {
+                        // some child might be excluded from here and handled separately
+                        if Some(child) != exclude {
+                            self.stack.push((child, child_rel));
+                        }
+                    }
+                }
+                Ok(())
+            }
+        }
+
+        let start_idx = self.tag_mapping.get(&start).unwrap();
+        let mut stack = TreeVisitAux { f_propagate, err_builder, stack: Vec::new() };
+        {
+            let mut path_ascend = Vec::new();
+            // First climb to the root while recording the path
+            let mut curr = start_idx;
+            while let Some(ancestor) = self.nodes.get(curr).unwrap().parent {
+                path_ascend.push((ancestor, curr));
+                curr = ancestor;
+            }
+            // Then descend:
+            // - execute f_propagate on each node
+            // - record children in visit
+            while let Some((ancestor, next_in_path)) = path_ascend.pop() {
+                // Explore ancestors in descending order.
+                // `next_in_path` is excluded from the recursion because it
+                // will be the `ancestor` of the next iteration.
+                // It also needs a different `AccessRelatedness` than the other
+                // children of `ancestor`.
+                stack.exec_and_visit(
+                    &mut self,
+                    ancestor,
+                    Some(next_in_path),
+                    AccessRelatedness::StrictChildAccess,
+                )?;
+            }
+        };
+        // All (potentially zero) ancestors have been explored, call f_propagate on start
+        stack.exec_and_visit(&mut self, start_idx, None, AccessRelatedness::This)?;
+        // up to this point we have never popped from `stack`, hence if the
+        // path to the root is `root = p(n) <- p(n-1)... <- p(1) <- p(0) = start`
+        // then now `stack` contains
+        // `[<children(p(n)) except p(n-1)> ... <children(p(1)) except p(0)> <children(p(0))>]`,
+        // all of which are for now unexplored.
+        // This is the starting point of a standard DFS which will thus
+        // explore all non-ancestors of `start` in the following order:
+        // - all descendants of `start`;
+        // - then the unexplored descendants of `parent(start)`;
+        // ...
+        // - until finally the unexplored descendants of `root`.
+        while let Some((tag, rel_pos)) = stack.pop() {
+            stack.exec_and_visit(&mut self, tag, None, rel_pos)?;
+        }
+        Ok(())
+    }
+}
+
+impl Tree {
+    /// Create a new tree, with only a root pointer.
+    pub fn new(root_tag: BorTag, size: Size) -> Self {
+        let root_perm = Permission::new_root();
+        let mut tag_mapping = UniKeyMap::default();
+        let root_idx = tag_mapping.insert(root_tag);
+        let nodes = {
+            let mut nodes = UniValMap::<Node>::default();
+            nodes.insert(
+                root_idx,
+                Node {
+                    tag: root_tag,
+                    parent: None,
+                    children: SmallVec::default(),
+                    default_initial_perm: root_perm,
+                    debug_info: NodeDebugInfo::new(root_tag),
+                },
+            );
+            nodes
+        };
+        let rperms = {
+            let mut perms = UniValMap::default();
+            perms.insert(root_idx, LocationState::new(root_perm).with_access());
+            RangeMap::new(size, perms)
+        };
+        Self { root: root_idx, nodes, rperms, tag_mapping }
+    }
+}
+
+impl<'tcx> Tree {
+    /// Insert a new tag in the tree
+    pub fn new_child(
+        &mut self,
+        parent_tag: BorTag,
+        new_tag: BorTag,
+        default_initial_perm: Permission,
+        range: AllocRange,
+    ) -> InterpResult<'tcx> {
+        assert!(!self.tag_mapping.contains_key(&new_tag));
+        let idx = self.tag_mapping.insert(new_tag);
+        let parent_idx = self.tag_mapping.get(&parent_tag).unwrap();
+        // Create the node
+        self.nodes.insert(
+            idx,
+            Node {
+                tag: new_tag,
+                parent: Some(parent_idx),
+                children: SmallVec::default(),
+                default_initial_perm,
+                debug_info: NodeDebugInfo::new(new_tag),
+            },
+        );
+        // Register new_tag as a child of parent_tag
+        self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
+        // Initialize perms
+        let perm = LocationState::new(default_initial_perm).with_access();
+        for (_range, perms) in self.rperms.iter_mut(range.start, range.size) {
+            perms.insert(idx, perm);
+        }
+        Ok(())
+    }
+
+    /// Deallocation requires
+    /// - a pointer that permits write accesses
+    /// - the absence of Strong Protectors anywhere in the allocation
+    pub fn dealloc(
+        &mut self,
+        tag: BorTag,
+        range: AllocRange,
+        global: &GlobalState,
+    ) -> InterpResult<'tcx> {
+        self.perform_access(AccessKind::Write, tag, range, global)?;
+        let access_info = &self.nodes.get(self.tag_mapping.get(&tag).unwrap()).unwrap().debug_info;
+        for (_range, perms) in self.rperms.iter_mut(range.start, range.size) {
+            TreeVisitor { nodes: &self.nodes, tag_mapping: &self.tag_mapping, perms }
+                .traverse_parents_this_children_others(
+                    tag,
+                    |args: NodeAppArgs<'_>| -> Result<ContinueTraversal, TransitionError> {
+                        let NodeAppArgs { node, .. } = args;
+                        if global.borrow().protected_tags.get(&node.tag)
+                            == Some(&ProtectorKind::StrongProtector)
+                        {
+                            Err(TransitionError::ProtectedDealloc)
+                        } else {
+                            Ok(ContinueTraversal::Recurse)
+                        }
+                    },
+                    |args: ErrHandlerArgs<'_, TransitionError>| -> InterpErrorInfo<'tcx> {
+                        let ErrHandlerArgs { error_kind, faulty_tag } = args;
+                        TbError {
+                            faulty_tag,
+                            access_kind: AccessKind::Write,
+                            error_kind,
+                            tag_of_access: access_info,
+                        }
+                        .build()
+                    },
+                )?;
+        }
+        Ok(())
+    }
+
+    /// Maps the following propagation procedure to each range:
+    /// - initialize if needed;
+    /// - compute new state after transition;
+    /// - check that there is no protector that would forbid this;
+    /// - record this specific location as accessed.
+    pub fn perform_access(
+        &mut self,
+        access_kind: AccessKind,
+        tag: BorTag,
+        range: AllocRange,
+        global: &GlobalState,
+    ) -> InterpResult<'tcx> {
+        let access_info = &self.nodes.get(self.tag_mapping.get(&tag).unwrap()).unwrap().debug_info;
+        for (_range, perms) in self.rperms.iter_mut(range.start, range.size) {
+            TreeVisitor { nodes: &self.nodes, tag_mapping: &self.tag_mapping, perms }
+                .traverse_parents_this_children_others(
+                    tag,
+                    |args: NodeAppArgs<'_>| -> Result<ContinueTraversal, TransitionError> {
+                        let NodeAppArgs { node, mut perm, rel_pos } = args;
+
+                        let old_state =
+                            perm.or_insert_with(|| LocationState::new(node.default_initial_perm));
+
+                        // Optimize the tree traversal.
+                        // The optimization here consists of observing thanks to the tests
+                        // `foreign_read_is_noop_after_write` and `all_transitions_idempotent`
+                        // that if we apply twice in a row the effects of a foreign access
+                        // we can skip some branches.
+                        // "two foreign accesses in a row" occurs when `perm.latest_foreign_access` is `Some(_)`
+                        // AND the `rel_pos` of the current access corresponds to a foreign access.
+                        if rel_pos.is_foreign() {
+                            let new_access_noop =
+                                match (old_state.latest_foreign_access, access_kind) {
+                                    // Previously applied transition makes the new one a guaranteed
+                                    // noop in the two following cases:
+                                    // (1) justified by `foreign_read_is_noop_after_write`
+                                    (Some(AccessKind::Write), AccessKind::Read) => true,
+                                    // (2) justified by `all_transitions_idempotent`
+                                    (Some(old), new) if old == new => true,
+                                    // In all other cases there has been a recent enough
+                                    // child access that the effects of the new foreign access
+                                    // need to be applied to this subtree.
+                                    _ => false,
+                                };
+                            if new_access_noop {
+                                // Abort traversal if the new transition is indeed guaranteed
+                                // to be noop.
+                                return Ok(ContinueTraversal::SkipChildren);
+                            } else {
+                                // Otherwise propagate this time, and also record the
+                                // access that just occurred so that we can skip the propagation
+                                // next time.
+                                old_state.latest_foreign_access = Some(access_kind);
+                            }
+                        } else {
+                            // A child access occurred, this breaks the streak of "two foreign
+                            // accesses in a row" and we reset this field.
+                            old_state.latest_foreign_access = None;
+                        }
+
+                        let old_perm = old_state.permission;
+                        let protected = global.borrow().protected_tags.contains_key(&node.tag);
+                        let new_perm =
+                            Permission::perform_access(access_kind, rel_pos, old_perm, protected)
+                                .ok_or(TransitionError::ChildAccessForbidden(old_perm))?;
+                        if protected
+                            // Can't trigger Protector on uninitialized locations
+                            && old_state.initialized
+                            && !old_perm.protector_allows_transition(new_perm)
+                        {
+                            return Err(TransitionError::ProtectedTransition(old_perm, new_perm));
+                        }
+                        old_state.permission = new_perm;
+                        old_state.initialized |= !rel_pos.is_foreign();
+                        Ok(ContinueTraversal::Recurse)
+                    },
+                    |args: ErrHandlerArgs<'_, TransitionError>| -> InterpErrorInfo<'tcx> {
+                        let ErrHandlerArgs { error_kind, faulty_tag } = args;
+                        TbError { faulty_tag, access_kind, error_kind, tag_of_access: access_info }
+                            .build()
+                    },
+                )?;
+        }
+        Ok(())
+    }
+}
+
+/// Integration with the BorTag garbage collector
+impl Tree {
+    pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet<BorTag>) {
+        assert!(self.keep_only_needed(self.root, live_tags)); // root can't be removed
+    }
+
+    /// Traverses the entire tree looking for useless tags.
+    /// Returns true iff the tag it was called on is still live or has live children,
+    /// and removes from the tree all tags that have no live children.
+    ///
+    /// NOTE: This leaves in the middle of the tree tags that are unreachable but have
+    /// reachable children. There is a potential for compacting the tree by reassigning
+    /// children of dead tags to the nearest live parent, but it must be done with care
+    /// not to remove UB.
+    ///
+    /// Example: Consider the tree `root - parent - child`, with `parent: Frozen` and
+    /// `child: Reserved`. This tree can exist. If we blindly delete `parent` and reassign
+    /// `child` to be a direct child of `root` then Writes to `child` are now permitted
+    /// whereas they were not when `parent` was still there.
+    fn keep_only_needed(&mut self, idx: UniIndex, live: &FxHashSet<BorTag>) -> bool {
+        let node = self.nodes.get(idx).unwrap();
+        // FIXME: this function does a lot of cloning, a 2-pass approach is possibly
+        // more efficient. It could consist of
+        // 1. traverse the Tree, collect all useless tags in a Vec
+        // 2. traverse the Vec, remove all tags previously selected
+        // Bench it.
+        let children: SmallVec<_> = node
+            .children
+            .clone()
+            .into_iter()
+            .filter(|child| self.keep_only_needed(*child, live))
+            .collect();
+        let no_children = children.is_empty();
+        let node = self.nodes.get_mut(idx).unwrap();
+        node.children = children;
+        if !live.contains(&node.tag) && no_children {
+            // All of the children and this node are unreachable, delete this tag
+            // from the tree (the children have already been deleted by recursive
+            // calls).
+            // Due to the API of UniMap we must absolutely call
+            // `UniValMap::remove` for the key of this tag on *all* maps that used it
+            // (which are `self.nodes` and every range of `self.rperms`)
+            // before we can safely apply `UniValMap::forget` to truly remove
+            // the tag from the mapping.
+            let tag = node.tag;
+            self.nodes.remove(idx);
+            for perms in self.rperms.iter_mut_all() {
+                perms.remove(idx);
+            }
+            self.tag_mapping.remove(&tag);
+            // The tag has been deleted, inform the caller
+            false
+        } else {
+            // The tag is still live or has live children, it must be kept
+            true
+        }
+    }
+}
+
+impl VisitTags for Tree {
+    fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
+        // To ensure that the root never gets removed, we visit it
+        // (the `root` node of `Tree` is not an `Option<_>`)
+        visit(self.nodes.get(self.root).unwrap().tag)
+    }
+}
+
+/// Relative position of the access
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum AccessRelatedness {
+    /// The accessed pointer is the current one
+    This,
+    /// The accessed pointer is a (transitive) child of the current one.
+    // Current pointer is excluded (unlike in some other places of this module
+    // where "child" is inclusive).
+    StrictChildAccess,
+    /// The accessed pointer is a (transitive) parent of the current one.
+    // Current pointer is excluded.
+    AncestorAccess,
+    /// The accessed pointer is neither of the above.
+    // It's a cousin/uncle/etc., something in a side branch.
+    // FIXME: find a better name ?
+    DistantAccess,
+}
+
+impl AccessRelatedness {
+    /// Check that access is either Ancestor or Distant, i.e. not
+    /// a transitive child (initial pointer included).
+    pub fn is_foreign(self) -> bool {
+        matches!(self, AccessRelatedness::AncestorAccess | AccessRelatedness::DistantAccess)
+    }
+
+    /// Given the AccessRelatedness for the parent node, compute the AccessRelatedness
+    /// for the child node. This function assumes that we propagate away from the initial
+    /// access.
+    pub fn for_child(self) -> Self {
+        use AccessRelatedness::*;
+        match self {
+            AncestorAccess | This => AncestorAccess,
+            StrictChildAccess | DistantAccess => DistantAccess,
+        }
+    }
+}
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs
new file mode 100644
index 00000000000..c1d452ca89e
--- /dev/null
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs
@@ -0,0 +1,304 @@
+//! This module implements the `UniMap`, which is a way to get efficient mappings
+//! optimized for the setting of `tree_borrows/tree.rs`.
+//!
+//! A `UniKeyMap<K>` is a (slow) mapping from `K` to `UniIndex`,
+//! and `UniValMap<V>` is a (fast) mapping from `UniIndex` to `V`.
+//! Thus a pair `(UniKeyMap<K>, UniValMap<V>)` acts as a virtual `HashMap<K, V>`.
+//!
+//! Because of the asymmetry in access time, the use-case for `UniMap` is the following:
+//! a tuple `(UniKeyMap<K>, Vec<UniValMap<V>>)` is much more efficient than
+//! the equivalent `Vec<HashMap<K, V>>` it represents if all maps have similar
+//! sets of keys.
+
+#![allow(dead_code)]
+
+use std::hash::Hash;
+
+use rustc_data_structures::fx::FxHashMap;
+
+/// Intermediate key between a UniKeyMap and a UniValMap.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct UniIndex {
+    idx: u32,
+}
+
+/// From K to UniIndex
+#[derive(Debug, Clone, Default)]
+pub struct UniKeyMap<K> {
+    /// Underlying map that does all the hard work.
+    /// Key invariant: the contents of `deassigned` are disjoint from the
+    /// keys of `mapping`, and together they form the set of contiguous integers
+    /// `0 .. (mapping.len() + deassigned.len())`.
+    mapping: FxHashMap<K, u32>,
+    /// Indexes that can be reused: memory gain when the map gets sparse
+    /// due to many deletions.
+    deassigned: Vec<u32>,
+}
+
+/// From UniIndex to V
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct UniValMap<V> {
+    /// The mapping data. Thanks to Vec we get both fast accesses, and
+    /// a memory-optimal representation if there are few deletions.
+    data: Vec<Option<V>>,
+}
+
+impl<V> Default for UniValMap<V> {
+    fn default() -> Self {
+        Self { data: Vec::default() }
+    }
+}
+
+impl<K> UniKeyMap<K>
+where
+    K: Hash + Eq,
+{
+    /// How many keys/index pairs are currently active.
+    pub fn len(&self) -> usize {
+        self.mapping.len()
+    }
+
+    /// Whether this key has an associated index or not.
+    pub fn contains_key(&self, key: &K) -> bool {
+        self.mapping.contains_key(key)
+    }
+
+    /// Assign this key to a new index. Panics if the key is already assigned,
+    /// use `get_or_insert` for a version that instead returns the existing
+    /// assignment.
+    #[track_caller]
+    pub fn insert(&mut self, key: K) -> UniIndex {
+        // We want an unused index. First we attempt to find one from `deassigned`,
+        // and if `deassigned` is empty we generate a fresh index.
+        let idx = self.deassigned.pop().unwrap_or_else(|| {
+            // `deassigned` is empty, so all keys in use are already in `mapping`.
+            // The next available key is `mapping.len()`.
+            self.mapping.len().try_into().expect("UniMap ran out of useable keys")
+        });
+        if self.mapping.insert(key, idx).is_some() {
+            panic!(
+                "This key is already assigned to a different index; either use `get_or_insert` instead if you care about this data, or first call `remove` to undo the preexisting assignment."
+            );
+        };
+        UniIndex { idx }
+    }
+
+    /// If it exists, the index this key maps to.
+    pub fn get(&self, key: &K) -> Option<UniIndex> {
+        self.mapping.get(key).map(|&idx| UniIndex { idx })
+    }
+
+    /// Either get a previously existing entry, or create a new one if it
+    /// is not yet present.
+    pub fn get_or_insert(&mut self, key: K) -> UniIndex {
+        self.get(&key).unwrap_or_else(|| self.insert(key))
+    }
+
+    /// Return whatever index this key was using to the deassigned pool.
+    ///
+    /// Note: calling this function can be dangerous. If the index still exists
+    /// somewhere in a `UniValMap` and is reassigned by the `UniKeyMap` then
+    /// it will inherit the old value of a completely unrelated key.
+    /// If you `UniKeyMap::remove` a key you should make sure to also `UniValMap::remove`
+    /// the associated `UniIndex` from ALL `UniValMap`s.
+    ///
+    /// Example of such behavior:
+    /// ```
+    /// let mut keymap = UniKeyMap::<char>::default();
+    /// let mut valmap = UniValMap::<char>::default();
+    /// // Insert 'a' -> _ -> 'A'
+    /// let idx_a = keymap.insert('a');
+    /// valmap.insert(idx_a, 'A');
+    /// // Remove 'a' -> _, but forget to remove _ -> 'A'
+    /// keymap.remove(&'a');
+    /// // valmap.remove(idx_a); // If we uncomment this line the issue is fixed
+    /// // Insert 'b' -> _
+    /// let idx_b = keymap.insert('b');
+    /// let val_b = valmap.get(idx_b);
+    /// assert_eq!(val_b, Some('A')); // Oh no
+    /// // assert_eq!(val_b, None); // This is what we would have expected
+    /// ```
+    pub fn remove(&mut self, key: &K) {
+        if let Some(idx) = self.mapping.remove(key) {
+            self.deassigned.push(idx);
+        }
+    }
+}
+
+impl<V> UniValMap<V> {
+    /// Whether this index has an associated value.
+    pub fn contains_idx(&self, idx: UniIndex) -> bool {
+        self.data.get(idx.idx as usize).and_then(Option::as_ref).is_some()
+    }
+
+    /// Reserve enough space to insert the value at the right index.
+    fn extend_to_length(&mut self, len: usize) {
+        if len > self.data.len() {
+            let nb = len - self.data.len();
+            self.data.reserve(nb);
+            for _ in 0..nb {
+                self.data.push(None);
+            }
+        }
+    }
+
+    /// Assign a value to the index. Permanently overwrites any previous value.
+    pub fn insert(&mut self, idx: UniIndex, val: V) {
+        self.extend_to_length(idx.idx as usize + 1);
+        self.data[idx.idx as usize] = Some(val)
+    }
+
+    /// Get the value at this index, if it exists.
+    pub fn get(&self, idx: UniIndex) -> Option<&V> {
+        self.data.get(idx.idx as usize).and_then(Option::as_ref)
+    }
+
+    /// Get the value at this index mutably, if it exists.
+    pub fn get_mut(&mut self, idx: UniIndex) -> Option<&mut V> {
+        self.data.get_mut(idx.idx as usize).and_then(Option::as_mut)
+    }
+
+    /// Delete any value associated with this index. Ok even if the index
+    /// has no associated value.
+    pub fn remove(&mut self, idx: UniIndex) {
+        if idx.idx as usize >= self.data.len() {
+            return;
+        }
+        self.data[idx.idx as usize] = None;
+    }
+}
+
+/// An access to a single value of the map.
+pub struct UniEntry<'a, V> {
+    inner: &'a mut Option<V>,
+}
+
+impl<'a, V> UniValMap<V> {
+    /// Get a wrapper around a mutable access to the value corresponding to `idx`.
+    pub fn entry(&'a mut self, idx: UniIndex) -> UniEntry<'a, V> {
+        self.extend_to_length(idx.idx as usize + 1);
+        UniEntry { inner: &mut self.data[idx.idx as usize] }
+    }
+}
+
+impl<'a, V> UniEntry<'a, V> {
+    /// Insert in the map and get the value.
+    pub fn or_insert_with<F>(&mut self, default: F) -> &mut V
+    where
+        F: FnOnce() -> V,
+    {
+        if self.inner.is_none() {
+            *self.inner = Some(default());
+        }
+        self.inner.as_mut().unwrap()
+    }
+}
+
+mod tests {
+    use super::*;
+
+    #[test]
+    fn extend_to_length() {
+        let mut km = UniValMap::<char>::default();
+        km.extend_to_length(10);
+        assert!(km.data.len() == 10);
+        km.extend_to_length(0);
+        assert!(km.data.len() == 10);
+        km.extend_to_length(10);
+        assert!(km.data.len() == 10);
+        km.extend_to_length(11);
+        assert!(km.data.len() == 11);
+    }
+
+    #[derive(Default)]
+    struct MapWitness<K, V> {
+        key: UniKeyMap<K>,
+        val: UniValMap<V>,
+        map: FxHashMap<K, V>,
+    }
+
+    impl<K, V> MapWitness<K, V>
+    where
+        K: Copy + Hash + Eq,
+        V: Copy + Eq + std::fmt::Debug,
+    {
+        fn insert(&mut self, k: K, v: V) {
+            // UniMap
+            let i = self.key.get_or_insert(k);
+            self.val.insert(i, v);
+            // HashMap
+            self.map.insert(k, v);
+            // Consistency: nothing to check
+        }
+
+        fn get(&self, k: &K) {
+            // UniMap
+            let v1 = self.key.get(k).and_then(|i| self.val.get(i));
+            // HashMap
+            let v2 = self.map.get(k);
+            // Consistency
+            assert_eq!(v1, v2);
+        }
+
+        fn get_mut(&mut self, k: &K) {
+            // UniMap
+            let v1 = self.key.get(k).and_then(|i| self.val.get_mut(i));
+            // HashMap
+            let v2 = self.map.get_mut(k);
+            // Consistency
+            assert_eq!(v1, v2);
+        }
+        fn remove(&mut self, k: &K) {
+            // UniMap
+            if let Some(i) = self.key.get(k) {
+                self.val.remove(i);
+            }
+            self.key.remove(k);
+            // HashMap
+            self.map.remove(k);
+            // Consistency: nothing to check
+        }
+    }
+
+    #[test]
+    fn consistency_small() {
+        let mut m = MapWitness::<u64, char>::default();
+        m.insert(1, 'a');
+        m.insert(2, 'b');
+        m.get(&1);
+        m.get_mut(&2);
+        m.remove(&2);
+        m.insert(1, 'c');
+        m.get(&1);
+        m.insert(3, 'd');
+        m.insert(4, 'e');
+        m.insert(4, 'f');
+        m.get(&2);
+        m.get(&3);
+        m.get(&4);
+        m.get(&5);
+        m.remove(&100);
+        m.get_mut(&100);
+        m.get(&100);
+    }
+
+    #[test]
+    fn consistency_large() {
+        use std::collections::hash_map::DefaultHasher;
+        use std::hash::{Hash, Hasher};
+        let mut hasher = DefaultHasher::new();
+        let mut map = MapWitness::<u64, u64>::default();
+        for i in 0..1000 {
+            i.hash(&mut hasher);
+            let rng = hasher.finish();
+            let op = rng % 3 == 0;
+            let key = (rng / 2) % 50;
+            let val = (rng / 100) % 1000;
+            if op {
+                map.insert(key, val);
+            } else {
+                map.get(&key);
+            }
+        }
+    }
+}
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 035c0e64233..3c13118122c 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -22,6 +22,10 @@ pub enum TerminationInfo {
         help: Option<String>,
         history: Option<TagHistory>,
     },
+    TreeBorrowsUb {
+        msg: String,
+        // FIXME: incomplete
+    },
     Int2PtrWithStrictProvenance,
     Deadlock,
     MultipleSymbolDefinitions {
@@ -61,6 +65,7 @@ impl fmt::Display for TerminationInfo {
                     "integer-to-pointer casts and `ptr::from_exposed_addr` are not supported with `-Zmiri-strict-provenance`"
                 ),
             StackedBorrowsUb { msg, .. } => write!(f, "{msg}"),
+            TreeBorrowsUb { msg } => write!(f, "{msg}"),
             Deadlock => write!(f, "the evaluated program deadlocked"),
             MultipleSymbolDefinitions { link_name, .. } =>
                 write!(f, "multiple definitions of symbol `{link_name}`"),
@@ -184,7 +189,8 @@ pub fn report_error<'tcx, 'mir>(
             Abort(_) => Some("abnormal termination"),
             UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
                 Some("unsupported operation"),
-            StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
+            StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>
+                Some("Undefined Behavior"),
             Deadlock => Some("deadlock"),
             MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
         };
@@ -212,6 +218,12 @@ pub fn report_error<'tcx, 'mir>(
                     }
                 }
                 helps
+            },
+            TreeBorrowsUb { .. } => {
+                let helps = vec![
+                    (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental")),
+                ];
+                helps
             }
             MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
                 vec![
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 8443e907938..a32b18595b5 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -87,7 +87,7 @@ pub struct MiriConfig {
     pub env: Vec<(OsString, OsString)>,
     /// Determine if validity checking is enabled.
     pub validate: bool,
-    /// Determines if Stacked Borrows is enabled.
+    /// Determines if Stacked Borrows or Tree Borrows is enabled.
     pub borrow_tracker: Option<BorrowTrackerMethod>,
     /// Controls alignment checking.
     pub check_alignment: AlignmentCheck,
@@ -134,7 +134,7 @@ pub struct MiriConfig {
     pub preemption_rate: f64,
     /// Report the current instruction being executed every N basic blocks.
     pub report_progress: Option<u32>,
-    /// Whether Stacked Borrows retagging should recurse into fields of datatypes.
+    /// Whether Stacked Borrows and Tree Borrows retagging should recurse into fields of datatypes.
     pub retag_fields: RetagFields,
     /// The location of a shared object file to load when calling external functions
     /// FIXME! consider allowing users to specify paths to multiple SO files, or to a directory
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index ed3dd741a8b..21a413002d0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -1,5 +1,6 @@
 pub mod convert;
 
+use std::any::Any;
 use std::cmp;
 use std::iter;
 use std::num::NonZeroUsize;
@@ -23,7 +24,23 @@ use rand::RngCore;
 
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+/// A trait to work around not having trait object upcasting:
+/// Add `AsAny` as supertrait and your trait objects can be turned into `&dyn Any` on which you can
+/// then call `downcast`.
+pub trait AsAny: Any {
+    fn as_any(&self) -> &dyn Any;
+    fn as_any_mut(&mut self) -> &mut dyn Any;
+}
+impl<T: Any> AsAny for T {
+    #[inline(always)]
+    fn as_any(&self) -> &dyn Any {
+        self
+    }
+    #[inline(always)]
+    fn as_any_mut(&mut self) -> &mut dyn Any {
+        self
+    }
+}
 
 // This mapping should match `decode_error_kind` in
 // <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/unix/mod.rs>.
@@ -119,6 +136,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
     }
 }
 
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Checks if the given crate/module exists.
     fn have_module(&self, path: &[&str]) -> bool {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index f64f216520f..01d0f01d319 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(nonzero_ops)]
 #![feature(local_key_cell_methods)]
 #![feature(is_terminal)]
+#![feature(round_ties_even)]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
@@ -94,6 +95,7 @@ pub use crate::shims::EvalContextExt as _;
 pub use crate::borrow_tracker::stacked_borrows::{
     EvalContextExt as _, Item, Permission, Stack, Stacks,
 };
+pub use crate::borrow_tracker::tree_borrows::{EvalContextExt as _, Tree};
 pub use crate::borrow_tracker::{
     BorTag, BorrowTrackerMethod, CallId, EvalContextExt as _, RetagFields,
 };
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 969c81f7e32..c4baeb2a73b 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -38,7 +38,7 @@ pub const SIGRTMAX: i32 = 42;
 
 /// Extra data stored with each stack frame
 pub struct FrameExtra<'tcx> {
-    /// Extra data for Stacked Borrows.
+    /// Extra data for the Borrow Tracker.
     pub borrow_tracker: Option<borrow_tracker::FrameState>,
 
     /// If this is Some(), then this is a special "catch unwind" frame (the frame of `try_fn`
@@ -146,7 +146,7 @@ impl fmt::Display for MiriMemoryKind {
 pub enum Provenance {
     Concrete {
         alloc_id: AllocId,
-        /// Stacked Borrows tag.
+        /// Borrow Tracker tag.
         tag: BorTag,
     },
     Wildcard,
@@ -195,7 +195,7 @@ impl fmt::Debug for Provenance {
                 } else {
                     write!(f, "[{alloc_id:?}]")?;
                 }
-                // Print Stacked Borrows tag.
+                // Print Borrow Tracker tag.
                 write!(f, "{tag:?}")?;
             }
             Provenance::Wildcard => {
@@ -822,7 +822,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     #[inline(always)]
-    fn ignore_checkable_overflow_assertions(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
+    fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
         !ecx.tcx.sess.overflow_checks()
     }
 
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 03275ed4ed1..73439133af2 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -232,6 +232,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
     }
 
+    /// Read bytes from a `(ptr, len)` argument
+    fn read_byte_slice<'i>(&'i self, bytes: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, &'i [u8]>
+    where
+        'mir: 'i,
+    {
+        let this = self.eval_context_ref();
+        let (ptr, len) = this.read_immediate(bytes)?.to_scalar_pair();
+        let ptr = ptr.to_pointer(this)?;
+        let len = len.to_target_usize(this)?;
+        let bytes = this.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
+        Ok(bytes)
+    }
+
     /// Emulates calling a foreign item, failing if the item is not supported.
     /// This function will handle `goto_block` if needed.
     /// Returns Ok(None) if the foreign item was completely handled
@@ -427,13 +440,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 })?;
                 this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
             }
-            "miri_print_borrow_stacks" => {
-                let [id] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+            "miri_print_borrow_state" => {
+                let [id, show_unnamed] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let id = this.read_scalar(id)?.to_u64()?;
+                let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?;
                 if let Some(id) = std::num::NonZeroU64::new(id) {
-                    this.print_stacks(AllocId(id))?;
+                    this.print_borrow_state(AllocId(id), show_unnamed)?;
                 }
             }
+            "miri_pointer_name" => {
+                // This associates a name to a tag. Very useful for debugging, and also makes
+                // tests more strict.
+                let [ptr, nth_parent, name] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                let ptr = this.read_pointer(ptr)?;
+                let nth_parent = this.read_scalar(nth_parent)?.to_u8()?;
+                let name = this.read_byte_slice(name)?;
+                // We must make `name` owned because we need to
+                // end the shared borrow from `read_byte_slice` before we can
+                // start the mutable borrow for `give_pointer_debug_name`.
+                let name = String::from_utf8_lossy(name).into_owned();
+                this.give_pointer_debug_name(ptr, nth_parent, &name)?;
+            }
             "miri_static_root" => {
                 let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
@@ -487,12 +514,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // Writes some bytes to the interpreter's stdout/stderr. See the
             // README for details.
             "miri_write_to_stdout" | "miri_write_to_stderr" => {
-                let [bytes] = this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let (ptr, len) = this.read_immediate(bytes)?.to_scalar_pair();
-                let ptr = ptr.to_pointer(this)?;
-                let len = len.to_target_usize(this)?;
-                let msg = this.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
-
+                let [msg] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                let msg = this.read_byte_slice(msg)?;
                 // Note: we're ignoring errors writing to host stdout/stderr.
                 let _ignore = match link_name.as_str() {
                     "miri_write_to_stdout" => std::io::stdout().write_all(msg),
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index d21a1560699..9ecbb18ef5a 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -157,6 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "ceilf32"
             | "truncf32"
             | "roundf32"
+            | "rintf32"
             => {
                 let [f] = check_arg_count(args)?;
                 // FIXME: Using host floats.
@@ -174,6 +175,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "ceilf32" => f.ceil(),
                     "truncf32" => f.trunc(),
                     "roundf32" => f.round(),
+                    "rintf32" => f.round_ties_even(),
                     _ => bug!(),
                 };
                 this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?;
@@ -192,6 +194,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "ceilf64"
             | "truncf64"
             | "roundf64"
+            | "rintf64"
             => {
                 let [f] = check_arg_count(args)?;
                 // FIXME: Using host floats.
@@ -209,6 +212,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "ceilf64" => f.ceil(),
                     "truncf64" => f.trunc(),
                     "roundf64" => f.round(),
+                    "rintf64" => f.round_ties_even(),
                     _ => bug!(),
                 };
                 this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?;
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index d05c4d98fad..1eca389e984 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -17,7 +17,6 @@ use crate::shims::os_str::bytes_to_os_str;
 use crate::*;
 use shims::os_str::os_str_to_bytes;
 use shims::time::system_time_to_duration;
-use shims::unix::linux::fd::epoll::Epoll;
 
 #[derive(Debug)]
 pub struct FileHandle {
@@ -25,17 +24,9 @@ pub struct FileHandle {
     writable: bool,
 }
 
-pub trait FileDescriptor: std::fmt::Debug {
+pub trait FileDescriptor: std::fmt::Debug + helpers::AsAny {
     fn name(&self) -> &'static str;
 
-    fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
-        throw_unsup_format!("{} cannot be used as FileHandle", self.name());
-    }
-
-    fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
-        throw_unsup_format!("not an epoll file descriptor");
-    }
-
     fn read<'tcx>(
         &mut self,
         _communicate_allowed: bool,
@@ -69,7 +60,9 @@ pub trait FileDescriptor: std::fmt::Debug {
 
     fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;
 
-    fn is_tty(&self) -> bool;
+    fn is_tty(&self) -> bool {
+        false
+    }
 
     #[cfg(unix)]
     fn as_unix_host_fd(&self) -> Option<i32> {
@@ -82,10 +75,6 @@ impl FileDescriptor for FileHandle {
         "FILE"
     }
 
-    fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
-        Ok(self)
-    }
-
     fn read<'tcx>(
         &mut self,
         communicate_allowed: bool,
@@ -271,10 +260,6 @@ impl FileDescriptor for NullOutput {
     fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
         Ok(Box::new(NullOutput))
     }
-
-    fn is_tty(&self) -> bool {
-        false
-    }
 }
 
 #[derive(Debug)]
@@ -694,7 +679,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
             if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
                 // FIXME: Support fullfsync for all FDs
-                let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
+                let FileHandle { file, writable } =
+                    file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
+                        err_unsup_format!(
+                            "`F_FULLFSYNC` is only supported on file-backed file descriptors"
+                        )
+                    })?;
                 let io_result = maybe_sync_file(file, *writable, File::sync_all);
                 this.try_unwrap_io_result(io_result)
             } else {
@@ -1530,7 +1520,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         Ok(Scalar::from_i32(
             if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
                 // FIXME: Support ftruncate64 for all FDs
-                let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
+                let FileHandle { file, writable } =
+                    file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
+                        err_unsup_format!(
+                            "`ftruncate64` is only supported on file-backed file descriptors"
+                        )
+                    })?;
                 if *writable {
                     if let Ok(length) = length.try_into() {
                         let result = file.set_len(length);
@@ -1571,7 +1566,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
             // FIXME: Support fsync for all FDs
-            let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
+            let FileHandle { file, writable } =
+                file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
+                    err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
+                })?;
             let io_result = maybe_sync_file(file, *writable, File::sync_all);
             this.try_unwrap_io_result(io_result)
         } else {
@@ -1593,7 +1591,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
             // FIXME: Support fdatasync for all FDs
-            let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
+            let FileHandle { file, writable } =
+                file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
+                    err_unsup_format!(
+                        "`fdatasync` is only supported on file-backed file descriptors"
+                    )
+                })?;
             let io_result = maybe_sync_file(file, *writable, File::sync_data);
             this.try_unwrap_io_result(io_result)
         } else {
@@ -1638,7 +1641,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
             // FIXME: Support sync_data_range for all FDs
-            let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
+            let FileHandle { file, writable } =
+                file_descriptor.as_any().downcast_ref::<FileHandle>().ok_or_else(|| {
+                    err_unsup_format!(
+                        "`sync_data_range` is only supported on file-backed file descriptors"
+                    )
+                })?;
             let io_result = maybe_sync_file(file, *writable, File::sync_data);
             Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
         } else {
@@ -1942,7 +1950,16 @@ impl FileMetadata {
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
         let option = ecx.machine.file_handler.handles.get(&fd);
         let file = match option {
-            Some(file_descriptor) => &file_descriptor.as_file_handle()?.file,
+            Some(file_descriptor) =>
+                &file_descriptor
+                    .as_any()
+                    .downcast_ref::<FileHandle>()
+                    .ok_or_else(|| {
+                        err_unsup_format!(
+                            "obtaining metadata is only supported on file-backed file descriptors"
+                        )
+                    })?
+                    .file,
             None => return ecx.handle_not_found().map(|_: i32| None),
         };
         let metadata = file.metadata();
diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs
index fd4927fa10c..3c4a678e598 100644
--- a/src/tools/miri/src/shims/unix/linux/fd.rs
+++ b/src/tools/miri/src/shims/unix/linux/fd.rs
@@ -80,7 +80,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let event = EpollEvent { events, data };
 
             if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
-                let epfd = epfd.as_epoll_handle()?;
+                let epfd = epfd
+                    .as_any_mut()
+                    .downcast_mut::<Epoll>()
+                    .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
 
                 epfd.file_descriptors.insert(fd, event);
                 Ok(Scalar::from_i32(0))
@@ -89,7 +92,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         } else if op == epoll_ctl_del {
             if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
-                let epfd = epfd.as_epoll_handle()?;
+                let epfd = epfd
+                    .as_any_mut()
+                    .downcast_mut::<Epoll>()
+                    .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
 
                 epfd.file_descriptors.remove(&fd);
                 Ok(Scalar::from_i32(0))
@@ -148,7 +154,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let numevents = 0;
         if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
-            let _epfd = epfd.as_epoll_handle()?;
+            let _epfd = epfd
+                .as_any_mut()
+                .downcast_mut::<Epoll>()
+                .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;
 
             // FIXME return number of events ready when scheme for marking events ready exists
             Ok(Scalar::from_i32(numevents))
diff --git a/src/tools/miri/src/shims/unix/linux/fd/epoll.rs b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
index e33673fecf6..a429caaf8f4 100644
--- a/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
@@ -32,18 +32,10 @@ impl FileDescriptor for Epoll {
         "epoll"
     }
 
-    fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
-        Ok(self)
-    }
-
     fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
         Ok(Box::new(self.clone()))
     }
 
-    fn is_tty(&self) -> bool {
-        false
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
diff --git a/src/tools/miri/src/shims/unix/linux/fd/event.rs b/src/tools/miri/src/shims/unix/linux/fd/event.rs
index b28a6e0c56e..1db020bb7b6 100644
--- a/src/tools/miri/src/shims/unix/linux/fd/event.rs
+++ b/src/tools/miri/src/shims/unix/linux/fd/event.rs
@@ -28,10 +28,6 @@ impl FileDescriptor for Event {
         Ok(Box::new(Event { val: self.val.clone() }))
     }
 
-    fn is_tty(&self) -> bool {
-        false
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
diff --git a/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs b/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
index f9e56b4a2b4..6adae88235f 100644
--- a/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
+++ b/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
@@ -19,10 +19,6 @@ impl FileDescriptor for SocketPair {
         Ok(Box::new(SocketPair))
     }
 
-    fn is_tty(&self) -> bool {
-        false
-    }
-
     fn close<'tcx>(
         self: Box<Self>,
         _communicate_allowed: bool,
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index 1d7ed34c59a..21eaeabe6ad 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -139,8 +139,9 @@ regexes! {
     STDOUT:
     // Windows file paths
     r"\\"                           => "/",
-    // erase Stacked Borrows tags
+    // erase borrow tags
     "<[0-9]+>"                      => "<TAG>",
+    "<[0-9]+="                      => "<TAG=",
 }
 
 regexes! {
@@ -149,8 +150,9 @@ regexes! {
     r"\.rs:[0-9]+:[0-9]+(: [0-9]+:[0-9]+)?" => ".rs:LL:CC",
     // erase alloc ids
     "alloc[0-9]+"                    => "ALLOC",
-    // erase Stacked Borrows tags
+    // erase borrow tags
     "<[0-9]+>"                       => "<TAG>",
+    "<[0-9]+="                       => "<TAG=",
     // erase whitespace that differs between platforms
     r" +at (.*\.rs)"                 => " at $1",
     // erase generics in backtraces
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
index a63cd03366f..0637e08af9b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
@@ -1,4 +1,4 @@
-//! Make sure that a retag acts like a write for the data race model.
+//! Make sure that a retag acts like a read for the data race model.
 //@compile-flags: -Zmiri-preemption-rate=0
 #[derive(Copy, Clone)]
 struct SendPtr(*mut u8);
diff --git a/src/tools/miri/tests/fail/tree-borrows/alternate-read-write.rs b/src/tools/miri/tests/fail/tree-borrows/alternate-read-write.rs
new file mode 100644
index 00000000000..122a8ff8752
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/alternate-read-write.rs
@@ -0,0 +1,19 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// Check that TB properly rejects alternating Reads and Writes, but tolerates
+// alternating only Reads to Reserved mutable references.
+pub fn main() {
+    let x = &mut 0u8;
+    let y = unsafe { &mut *(x as *mut u8) };
+    // Foreign Read, but this is a no-op from the point of view of y (still Reserved)
+    let _val = *x;
+    // Now we activate y, for this to succeed y needs to not have been Frozen
+    // by the previous operation
+    *y += 1; // Success
+    // This time y gets Frozen...
+    let _val = *x;
+    // ... and the next Write attempt fails.
+    *y += 1; // Failure //~ ERROR: /write access through .* is forbidden/
+    let _val = *x;
+    *y += 1; // Unreachable
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/alternate-read-write.stderr b/src/tools/miri/tests/fail/tree-borrows/alternate-read-write.stderr
new file mode 100644
index 00000000000..7c5bcd4e7b0
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/alternate-read-write.stderr
@@ -0,0 +1,14 @@
+error: Undefined Behavior: write access through <TAG> is forbidden because it is a child of <TAG> which is Frozen.
+  --> $DIR/alternate-read-write.rs:LL:CC
+   |
+LL |     *y += 1; // Failure
+   |     ^^^^^^^ write access through <TAG> is forbidden because it is a child of <TAG> which is Frozen.
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/alternate-read-write.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/fragile-data-race.rs b/src/tools/miri/tests/fail/tree-borrows/fragile-data-race.rs
new file mode 100644
index 00000000000..215100de0a1
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/fragile-data-race.rs
@@ -0,0 +1,42 @@
+//! Race-condition-like interaction between a read and a reborrow.
+//! Even though no write or fake write occurs, reads have an effect on protected
+//! Reserved. This is a protected-retag/read data race, but is not *detected* as
+//! a data race violation because reborrows are not writes.
+//!
+//! This test is sensitive to the exact schedule so we disable preemption.
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0
+use std::ptr::addr_of_mut;
+use std::thread;
+
+#[derive(Copy, Clone)]
+struct SendPtr(*mut u8);
+
+unsafe impl Send for SendPtr {}
+
+// First thread is just a reborrow, but for an instant `x` is
+// protected and thus vulnerable to foreign reads.
+fn thread_1(x: &mut u8) -> SendPtr {
+    thread::yield_now(); // make the other thread go first
+    SendPtr(x as *mut u8)
+}
+
+// Second thread simply performs a read.
+fn thread_2(x: &u8) {
+    let _val = *x;
+}
+
+fn main() {
+    let mut x = 0u8;
+    let x_1 = unsafe { &mut *addr_of_mut!(x) };
+    let xg = unsafe { &*addr_of_mut!(x) };
+
+    // The two threads are executed in parallel on aliasing pointers.
+    // UB occurs if the read of thread_2 occurs while the protector of thread_1
+    // is in place.
+    let hf = thread::spawn(move || thread_1(x_1));
+    let hg = thread::spawn(move || thread_2(xg));
+    let SendPtr(p) = hf.join().unwrap();
+    let () = hg.join().unwrap();
+
+    unsafe { *p = 1 }; //~ ERROR: /write access through .* is forbidden/
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/fragile-data-race.stderr b/src/tools/miri/tests/fail/tree-borrows/fragile-data-race.stderr
new file mode 100644
index 00000000000..a078d18d3b0
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/fragile-data-race.stderr
@@ -0,0 +1,14 @@
+error: Undefined Behavior: write access through <TAG> is forbidden because it is a child of <TAG> which is Frozen.
+  --> $DIR/fragile-data-race.rs:LL:CC
+   |
+LL |     unsafe { *p = 1 };
+   |              ^^^^^^ write access through <TAG> is forbidden because it is a child of <TAG> which is Frozen.
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/fragile-data-race.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/outside-range.rs b/src/tools/miri/tests/fail/tree-borrows/outside-range.rs
new file mode 100644
index 00000000000..8450e1c168d
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/outside-range.rs
@@ -0,0 +1,22 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// Check that in the case of locations outside the range of a pointer,
+// protectors trigger if and only if the location has already been accessed
+fn main() {
+    unsafe {
+        let data = &mut [0u8, 1, 2, 3];
+        let raw = data.as_mut_ptr();
+        stuff(&mut *raw, raw);
+    }
+}
+
+unsafe fn stuff(x: &mut u8, y: *mut u8) {
+    let xraw = x as *mut u8;
+    // No issue here: location 1 is not accessed
+    *y.add(1) = 42;
+    // Still no issue: location 2 is not invalidated
+    let _val = *xraw.add(2);
+    // However protector triggers if location is both accessed and invalidated
+    let _val = *xraw.add(3);
+    *y.add(3) = 42; //~ ERROR: /write access through .* is forbidden/
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/outside-range.stderr b/src/tools/miri/tests/fail/tree-borrows/outside-range.stderr
new file mode 100644
index 00000000000..4396c63679e
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/outside-range.stderr
@@ -0,0 +1,19 @@
+error: Undefined Behavior: write access through <TAG> is forbidden because it is a foreign tag for <TAG>, which would hence change from Reserved to Disabled, but <TAG> is protected
+  --> $DIR/outside-range.rs:LL:CC
+   |
+LL |     *y.add(3) = 42;
+   |     ^^^^^^^^^^^^^^ write access through <TAG> is forbidden because it is a foreign tag for <TAG>, which would hence change from Reserved to Disabled, but <TAG> is protected
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `stuff` at $DIR/outside-range.rs:LL:CC
+note: inside `main`
+  --> $DIR/outside-range.rs:LL:CC
+   |
+LL |         stuff(&mut *raw, raw);
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/read-to-local.rs b/src/tools/miri/tests/fail/tree-borrows/read-to-local.rs
new file mode 100644
index 00000000000..025b7ad22dc
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/read-to-local.rs
@@ -0,0 +1,14 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// Read to local variable kills reborrows *and* raw pointers derived from them.
+// This test would succeed under Stacked Borrows.
+fn main() {
+    unsafe {
+        let mut root = 6u8;
+        let mref = &mut root;
+        let ptr = mref as *mut u8;
+        *ptr = 0; // Write
+        assert_eq!(root, 0); // Parent Read
+        *ptr = 0; //~ ERROR: /write access through .* is forbidden/
+    }
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/read-to-local.stderr b/src/tools/miri/tests/fail/tree-borrows/read-to-local.stderr
new file mode 100644
index 00000000000..7d9367c87d0
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/read-to-local.stderr
@@ -0,0 +1,14 @@
+error: Undefined Behavior: write access through <TAG> is forbidden because it is a child of <TAG> which is Frozen.
+  --> $DIR/read-to-local.rs:LL:CC
+   |
+LL |         *ptr = 0;
+   |         ^^^^^^^^ write access through <TAG> is forbidden because it is a child of <TAG> which is Frozen.
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/read-to-local.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.rs b/src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.rs
new file mode 100644
index 00000000000..872efe3ad59
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.rs
@@ -0,0 +1,34 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+
+// Check how a Reserved with interior mutability
+// responds to a Foreign Write under a Protector
+#[path = "../../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+
+use std::cell::UnsafeCell;
+
+fn main() {
+    unsafe {
+        let n = &mut UnsafeCell::new(0u8);
+        name!(n.get(), "base");
+        let x = &mut *(n as *mut UnsafeCell<_>);
+        name!(x.get(), "x");
+        let y = (&mut *n).get();
+        name!(y);
+        write_second(x, y);
+        unsafe fn write_second(x: &mut UnsafeCell<u8>, y: *mut u8) {
+            let alloc_id = alloc_id!(x.get());
+            name!(x.get(), "callee:x");
+            name!(x.get()=>1, "caller:x");
+            name!(y, "callee:y");
+            name!(y, "caller:y");
+            print_state!(alloc_id);
+            // Right before the faulty Write, x is
+            // - Reserved
+            // - with interior mut
+            // - Protected
+            *y = 1; //~ ERROR: /write access through .* is forbidden/
+        }
+    }
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.stderr
new file mode 100644
index 00000000000..8ae1c09470a
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/reserved/cell-protected-write.stderr
@@ -0,0 +1,28 @@
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Re*|    └─┬──<TAG=base>
+| Re*|      ├─┬──<TAG=x>
+| Re*|      │ └─┬──<TAG=caller:x>
+| Re*|      │   └────<TAG=callee:x> Strongly protected
+| Re*|      └────<TAG=y,callee:y,caller:y>
+──────────────────────────────────────────────────────────────────────
+error: Undefined Behavior: write access through <TAG> (also named 'y,callee:y,caller:y') is forbidden because it is a foreign tag for <TAG> (also named 'callee:x'), which would hence change from Reserved to Disabled, but <TAG> (also named 'callee:x') is protected
+  --> $DIR/cell-protected-write.rs:LL:CC
+   |
+LL |             *y = 1;
+   |             ^^^^^^ write access through <TAG> (also named 'y,callee:y,caller:y') is forbidden because it is a foreign tag for <TAG> (also named 'callee:x'), which would hence change from Reserved to Disabled, but <TAG> (also named 'callee:x') is protected
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `main::write_second` at $DIR/cell-protected-write.rs:LL:CC
+note: inside `main`
+  --> $DIR/cell-protected-write.rs:LL:CC
+   |
+LL |         write_second(x, y);
+   |         ^^^^^^^^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.rs b/src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.rs
new file mode 100644
index 00000000000..3a1205a84f7
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.rs
@@ -0,0 +1,32 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+
+#[path = "../../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+
+// Check how a Reserved without interior mutability responds to a Foreign
+// Write when under a protector
+fn main() {
+    unsafe {
+        let n = &mut 0u8;
+        name!(n);
+        let x = &mut *(n as *mut _);
+        name!(x);
+        let y = (&mut *n) as *mut _;
+        name!(y);
+        write_second(x, y);
+        unsafe fn write_second(x: &mut u8, y: *mut u8) {
+            let alloc_id = alloc_id!(x);
+            name!(x, "callee:x");
+            name!(x=>1, "caller:x");
+            name!(y, "callee:y");
+            name!(y, "caller:y");
+            print_state!(alloc_id);
+            // Right before the faulty Write, x is
+            // - Reserved
+            // - Protected
+            // The Write turns it Disabled
+            *y = 0; //~ ERROR: /write access through .* is forbidden/
+        }
+    }
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.stderr b/src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.stderr
new file mode 100644
index 00000000000..a199fc0f0da
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/reserved/int-protected-write.stderr
@@ -0,0 +1,28 @@
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Res|    └─┬──<TAG=n>
+| Res|      ├─┬──<TAG=x>
+| Res|      │ └─┬──<TAG=caller:x>
+| Res|      │   └────<TAG=callee:x> Strongly protected
+| Res|      └────<TAG=y,callee:y,caller:y>
+──────────────────────────────────────────────────────────────────────
+error: Undefined Behavior: write access through <TAG> (also named 'y,callee:y,caller:y') is forbidden because it is a foreign tag for <TAG> (also named 'callee:x'), which would hence change from Reserved to Disabled, but <TAG> (also named 'callee:x') is protected
+  --> $DIR/int-protected-write.rs:LL:CC
+   |
+LL |             *y = 0;
+   |             ^^^^^^ write access through <TAG> (also named 'y,callee:y,caller:y') is forbidden because it is a foreign tag for <TAG> (also named 'callee:x'), which would hence change from Reserved to Disabled, but <TAG> (also named 'callee:x') is protected
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `main::write_second` at $DIR/int-protected-write.rs:LL:CC
+note: inside `main`
+  --> $DIR/int-protected-write.rs:LL:CC
+   |
+LL |         write_second(x, y);
+   |         ^^^^^^^^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/retag-data-race.rs b/src/tools/miri/tests/fail/tree-borrows/retag-data-race.rs
new file mode 100644
index 00000000000..8ef3d23e804
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/retag-data-race.rs
@@ -0,0 +1,28 @@
+//! Make sure that a retag acts like a read for the data race model.
+//! This is a retag/write race condition.
+//!
+//! This test is sensitive to the exact schedule so we disable preemption.
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0
+#[derive(Copy, Clone)]
+struct SendPtr(*mut u8);
+
+unsafe impl Send for SendPtr {}
+
+unsafe fn thread_1(SendPtr(p): SendPtr) {
+    let _r = &*p;
+}
+
+unsafe fn thread_2(SendPtr(p): SendPtr) {
+    *p = 5; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
+}
+
+fn main() {
+    let mut x = 0;
+    let p = std::ptr::addr_of_mut!(x);
+    let p = SendPtr(p);
+
+    let t1 = std::thread::spawn(move || unsafe { thread_1(p) });
+    let t2 = std::thread::spawn(move || unsafe { thread_2(p) });
+    let _ = t1.join();
+    let _ = t2.join();
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/retag-data-race.stderr b/src/tools/miri/tests/fail/tree-borrows/retag-data-race.stderr
new file mode 100644
index 00000000000..f2cdfe7c314
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/retag-data-race.stderr
@@ -0,0 +1,25 @@
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+  --> $DIR/retag-data-race.rs:LL:CC
+   |
+LL |     *p = 5;
+   |     ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
+   |
+help: and (1) occurred earlier here
+  --> $DIR/retag-data-race.rs:LL:CC
+   |
+LL |     let _r = &*p;
+   |              ^^^
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE (of the first span):
+   = note: inside `thread_2` at $DIR/retag-data-race.rs:LL:CC
+note: inside closure
+  --> $DIR/retag-data-race.rs:LL:CC
+   |
+LL |     let t2 = std::thread::spawn(move || unsafe { thread_2(p) });
+   |                                                  ^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/tree-borrows/write-during-2phase.rs b/src/tools/miri/tests/fail/tree-borrows/write-during-2phase.rs
new file mode 100644
index 00000000000..6695d36306b
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/write-during-2phase.rs
@@ -0,0 +1,27 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// We invalidate a reference during a 2-phase borrow by doing a Foreign
+// Write in between the initial reborrow and function entry. UB occurs
+// on function entry when reborrow from a Disabled fails.
+// This test would pass under Stacked Borrows, but Tree Borrows
+// is more strict on 2-phase borrows.
+
+struct Foo(u64);
+impl Foo {
+    #[rustfmt::skip] // rustfmt is wrong about which line contains an error
+    fn add(&mut self, n: u64) -> u64 { //~ ERROR: /read access through .* is forbidden/
+        self.0 + n
+    }
+}
+
+pub fn main() {
+    let mut f = Foo(0);
+    let inner = &mut f.0 as *mut u64;
+    let _res = f.add(unsafe {
+        let n = f.0;
+        // This is the access at fault, but it's not immediately apparent because
+        // the reference that got invalidated is not under a Protector.
+        *inner = 42;
+        n
+    });
+}
diff --git a/src/tools/miri/tests/fail/tree-borrows/write-during-2phase.stderr b/src/tools/miri/tests/fail/tree-borrows/write-during-2phase.stderr
new file mode 100644
index 00000000000..e511eb9cf8f
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree-borrows/write-during-2phase.stderr
@@ -0,0 +1,26 @@
+error: Undefined Behavior: read access through <TAG> is forbidden because it is a child of <TAG> which is Disabled.
+  --> $DIR/write-during-2phase.rs:LL:CC
+   |
+LL |     fn add(&mut self, n: u64) -> u64 {
+   |            ^^^^^^^^^ read access through <TAG> is forbidden because it is a child of <TAG> which is Disabled.
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = note: BACKTRACE:
+   = note: inside `Foo::add` at $DIR/write-during-2phase.rs:LL:CC
+note: inside `main`
+  --> $DIR/write-during-2phase.rs:LL:CC
+   |
+LL |       let _res = f.add(unsafe {
+   |  ________________^
+LL | |         let n = f.0;
+LL | |         // This is the access at fault, but it's not immediately apparent because
+LL | |         // the reference that got invalidated is not under a Protector.
+LL | |         *inner = 42;
+LL | |         n
+LL | |     });
+   | |______^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/pass/adjacent-allocs.rs b/src/tools/miri/tests/pass/adjacent-allocs.rs
index 0051c62121c..cbf41d68b57 100644
--- a/src/tools/miri/tests/pass/adjacent-allocs.rs
+++ b/src/tools/miri/tests/pass/adjacent-allocs.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 
 fn ensure_allocs_can_be_adjacent() {
diff --git a/src/tools/miri/tests/pass/associated-const.rs b/src/tools/miri/tests/pass/associated-const.rs
index 2ff08ffc4bf..331fbfcefde 100644
--- a/src/tools/miri/tests/pass/associated-const.rs
+++ b/src/tools/miri/tests/pass/associated-const.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 trait Foo {
     const ID: i32;
 }
diff --git a/src/tools/miri/tests/pass/assume_bug.rs b/src/tools/miri/tests/pass/assume_bug.rs
index e14f875c022..662b9015088 100644
--- a/src/tools/miri/tests/pass/assume_bug.rs
+++ b/src/tools/miri/tests/pass/assume_bug.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 fn main() {
     vec![()].into_iter();
 }
diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs
index e3d80a78916..60b8ff87b59 100644
--- a/src/tools/miri/tests/pass/atomic.rs
+++ b/src/tools/miri/tests/pass/atomic.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(strict_provenance, strict_provenance_atomic_ptr)]
 use std::sync::atomic::{
diff --git a/src/tools/miri/tests/pass/available-parallelism.rs b/src/tools/miri/tests/pass/available-parallelism.rs
index eb4d09b1f54..77fb78424ba 100644
--- a/src/tools/miri/tests/pass/available-parallelism.rs
+++ b/src/tools/miri/tests/pass/available-parallelism.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 fn main() {
     assert_eq!(std::thread::available_parallelism().unwrap().get(), 1);
 }
diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs
index ef432a86d46..155e3d74ab9 100644
--- a/src/tools/miri/tests/pass/box-custom-alloc.rs
+++ b/src/tools/miri/tests/pass/box-custom-alloc.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![allow(incomplete_features)] // for trait upcasting
 #![feature(allocator_api, trait_upcasting)]
 
diff --git a/src/tools/miri/tests/pass/box.rs b/src/tools/miri/tests/pass/box.rs
index 7bbe7be516b..3bb481aab88 100644
--- a/src/tools/miri/tests/pass/box.rs
+++ b/src/tools/miri/tests/pass/box.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance
 #![feature(ptr_internals)]
 
 fn main() {
diff --git a/src/tools/miri/tests/pass/box.stderr b/src/tools/miri/tests/pass/box.stack.stderr
index 4c2fb40e110..4c2fb40e110 100644
--- a/src/tools/miri/tests/pass/box.stderr
+++ b/src/tools/miri/tests/pass/box.stack.stderr
diff --git a/src/tools/miri/tests/pass/box.stdout b/src/tools/miri/tests/pass/box.stack.stdout
index 230ef368da6..230ef368da6 100644
--- a/src/tools/miri/tests/pass/box.stdout
+++ b/src/tools/miri/tests/pass/box.stack.stdout
diff --git a/src/tools/miri/tests/pass/box.tree.stdout b/src/tools/miri/tests/pass/box.tree.stdout
new file mode 100644
index 00000000000..230ef368da6
--- /dev/null
+++ b/src/tools/miri/tests/pass/box.tree.stdout
@@ -0,0 +1,3 @@
+pair_foo = PairFoo { fst: Foo(42), snd: Foo(1337) }
+foo #0 = Foo(42)
+foo #1 = Foo(1337)
diff --git a/src/tools/miri/tests/pass/btreemap.rs b/src/tools/miri/tests/pass/btreemap.rs
index 040c648d474..b7c0406becc 100644
--- a/src/tools/miri/tests/pass/btreemap.rs
+++ b/src/tools/miri/tests/pass/btreemap.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(btree_drain_filter)]
 use std::collections::{BTreeMap, BTreeSet};
diff --git a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs
index d76c23633da..ccf96b99672 100644
--- a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs
+++ b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 // Check that you can cast between different pointers to trait objects
 // whose vtable have the same kind (both lengths, or both trait pointers).
 
diff --git a/src/tools/miri/tests/pass/concurrency/channels.rs b/src/tools/miri/tests/pass/concurrency/channels.rs
index 53b57942d76..43086756b03 100644
--- a/src/tools/miri/tests/pass/concurrency/channels.rs
+++ b/src/tools/miri/tests/pass/concurrency/channels.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 
 use std::sync::mpsc::{channel, sync_channel};
diff --git a/src/tools/miri/tests/pass/concurrency/sync.rs b/src/tools/miri/tests/pass/concurrency/sync.rs
index 19ea6c130bd..3bd1e542407 100644
--- a/src/tools/miri/tests/pass/concurrency/sync.rs
+++ b/src/tools/miri/tests/pass/concurrency/sync.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-disable-isolation -Zmiri-strict-provenance
 
 use std::sync::{Arc, Barrier, Condvar, Mutex, Once, RwLock};
diff --git a/src/tools/miri/tests/pass/concurrency/sync.stdout b/src/tools/miri/tests/pass/concurrency/sync.stack.stdout
index f2c036a1735..f2c036a1735 100644
--- a/src/tools/miri/tests/pass/concurrency/sync.stdout
+++ b/src/tools/miri/tests/pass/concurrency/sync.stack.stdout
diff --git a/src/tools/miri/tests/pass/concurrency/sync.tree.stdout b/src/tools/miri/tests/pass/concurrency/sync.tree.stdout
new file mode 100644
index 00000000000..f2c036a1735
--- /dev/null
+++ b/src/tools/miri/tests/pass/concurrency/sync.tree.stdout
@@ -0,0 +1,20 @@
+before wait
+before wait
+before wait
+before wait
+before wait
+before wait
+before wait
+before wait
+before wait
+before wait
+after wait
+after wait
+after wait
+after wait
+after wait
+after wait
+after wait
+after wait
+after wait
+after wait
diff --git a/src/tools/miri/tests/pass/concurrency/thread_locals.rs b/src/tools/miri/tests/pass/concurrency/thread_locals.rs
index b19e56312f3..13c11b55775 100644
--- a/src/tools/miri/tests/pass/concurrency/thread_locals.rs
+++ b/src/tools/miri/tests/pass/concurrency/thread_locals.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 
 //! The main purpose of this test is to check that if we take a pointer to
diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs
index 7ccafec6037..bd06eec9cd5 100644
--- a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs
+++ b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs
@@ -1,3 +1,6 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+
 use std::cell::RefCell;
 use std::thread;
 
diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.stdout b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.stack.stdout
index b7877820a0c..b7877820a0c 100644
--- a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.stdout
+++ b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.stack.stdout
diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.tree.stdout b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.tree.stdout
new file mode 100644
index 00000000000..b7877820a0c
--- /dev/null
+++ b/src/tools/miri/tests/pass/concurrency/tls_lib_drop.tree.stdout
@@ -0,0 +1,5 @@
+Dropping: 8 (should be before 'Continue main 1').
+Dropping: 8 (should be before 'Continue main 1').
+Continue main 1.
+Joining: 7 (should be before 'Continue main 2').
+Continue main 2.
diff --git a/src/tools/miri/tests/pass/disable-alignment-check.rs b/src/tools/miri/tests/pass/disable-alignment-check.rs
index 366aff4a9f8..fdcacc6cea4 100644
--- a/src/tools/miri/tests/pass/disable-alignment-check.rs
+++ b/src/tools/miri/tests/pass/disable-alignment-check.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-disable-alignment-check
 
 fn main() {
diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
index 256c72add92..94cf465e884 100644
--- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
+++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
 #![feature(rustc_attrs)]
 
diff --git a/src/tools/miri/tests/pass/extern_types.rs b/src/tools/miri/tests/pass/extern_types.rs
index aa4c65ea892..7ac93577f0c 100644
--- a/src/tools/miri/tests/pass/extern_types.rs
+++ b/src/tools/miri/tests/pass/extern_types.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance
 #![feature(extern_types)]
 
 extern "C" {
diff --git a/src/tools/miri/tests/pass/extern_types.stderr b/src/tools/miri/tests/pass/extern_types.stack.stderr
index 2e18f693058..2e18f693058 100644
--- a/src/tools/miri/tests/pass/extern_types.stderr
+++ b/src/tools/miri/tests/pass/extern_types.stack.stderr
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index ce62fb0de04..fee5ca44ffb 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -1,4 +1,5 @@
 #![feature(stmt_expr_attributes)]
+#![feature(round_ties_even)]
 #![allow(arithmetic_overflow)]
 use std::fmt::Debug;
 use std::hint::black_box;
@@ -9,6 +10,7 @@ fn main() {
     more_casts();
     ops();
     nan_casts();
+    rounding();
 }
 
 // Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
@@ -553,3 +555,31 @@ fn nan_casts() {
     assert!(nan1_32.is_nan());
     assert!(nan2_32.is_nan());
 }
+
+fn rounding() {
+    // Test cases taken from the library's tests for this feature
+    // f32
+    assert_eq(2.5f32.round_ties_even(), 2.0f32);
+    assert_eq(1.0f32.round_ties_even(), 1.0f32);
+    assert_eq(1.3f32.round_ties_even(), 1.0f32);
+    assert_eq(1.5f32.round_ties_even(), 2.0f32);
+    assert_eq(1.7f32.round_ties_even(), 2.0f32);
+    assert_eq(0.0f32.round_ties_even(), 0.0f32);
+    assert_eq((-0.0f32).round_ties_even(), -0.0f32);
+    assert_eq((-1.0f32).round_ties_even(), -1.0f32);
+    assert_eq((-1.3f32).round_ties_even(), -1.0f32);
+    assert_eq((-1.5f32).round_ties_even(), -2.0f32);
+    assert_eq((-1.7f32).round_ties_even(), -2.0f32);
+    // f64
+    assert_eq(2.5f64.round_ties_even(), 2.0f64);
+    assert_eq(1.0f64.round_ties_even(), 1.0f64);
+    assert_eq(1.3f64.round_ties_even(), 1.0f64);
+    assert_eq(1.5f64.round_ties_even(), 2.0f64);
+    assert_eq(1.7f64.round_ties_even(), 2.0f64);
+    assert_eq(0.0f64.round_ties_even(), 0.0f64);
+    assert_eq((-0.0f64).round_ties_even(), -0.0f64);
+    assert_eq((-1.0f64).round_ties_even(), -1.0f64);
+    assert_eq((-1.3f64).round_ties_even(), -1.0f64);
+    assert_eq((-1.5f64).round_ties_even(), -2.0f64);
+    assert_eq((-1.7f64).round_ties_even(), -2.0f64);
+}
diff --git a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs b/src/tools/miri/tests/pass/future-self-referential.rs
index 6994def16a1..763eceeb6f0 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
+++ b/src/tools/miri/tests/pass/future-self-referential.rs
@@ -1,3 +1,6 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+
 use std::future::*;
 use std::marker::PhantomPinned;
 use std::pin::*;
diff --git a/src/tools/miri/tests/pass/generator.rs b/src/tools/miri/tests/pass/generator.rs
index 06f48666c55..e059c7114e3 100644
--- a/src/tools/miri/tests/pass/generator.rs
+++ b/src/tools/miri/tests/pass/generator.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(generators, generator_trait, never_type)]
 
 use std::fmt::Debug;
diff --git a/src/tools/miri/tests/pass/hashmap.rs b/src/tools/miri/tests/pass/hashmap.rs
index 29ddd6c59a1..7224e357c6f 100644
--- a/src/tools/miri/tests/pass/hashmap.rs
+++ b/src/tools/miri/tests/pass/hashmap.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 use std::collections::HashMap;
 use std::hash::BuildHasher;
 
diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs
index e7ff90cb6bf..42b6f433420 100644
--- a/src/tools/miri/tests/pass/intptrcast.rs
+++ b/src/tools/miri/tests/pass/intptrcast.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 
 use std::mem;
diff --git a/src/tools/miri/tests/pass/linked-list.rs b/src/tools/miri/tests/pass/linked-list.rs
index 7377f9f60b0..36df30070cb 100644
--- a/src/tools/miri/tests/pass/linked-list.rs
+++ b/src/tools/miri/tests/pass/linked-list.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(linked_list_cursors)]
 use std::collections::LinkedList;
 
diff --git a/src/tools/miri/tests/pass/many_shr_bor.rs b/src/tools/miri/tests/pass/many_shr_bor.rs
index 376b41dd6e2..aa960aa147a 100644
--- a/src/tools/miri/tests/pass/many_shr_bor.rs
+++ b/src/tools/miri/tests/pass/many_shr_bor.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 // Make sure validation can handle many overlapping shared borrows for different parts of a data structure
 use std::cell::RefCell;
 
diff --git a/src/tools/miri/tests/pass/memleak_ignored.rs b/src/tools/miri/tests/pass/memleak_ignored.rs
index 60e06094e17..bba3207ee4c 100644
--- a/src/tools/miri/tests/pass/memleak_ignored.rs
+++ b/src/tools/miri/tests/pass/memleak_ignored.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-ignore-leaks
 
 fn main() {
diff --git a/src/tools/miri/tests/pass/option_box_transmute_ptr.rs b/src/tools/miri/tests/pass/option_box_transmute_ptr.rs
index 0786db1ef89..0ba6607a5d4 100644
--- a/src/tools/miri/tests/pass/option_box_transmute_ptr.rs
+++ b/src/tools/miri/tests/pass/option_box_transmute_ptr.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 // This tests that the size of Option<Box<i32>> is the same as *const i32.
 fn option_box_deref() -> i32 {
     let val = Some(Box::new(42));
diff --git a/src/tools/miri/tests/pass/pointers.rs b/src/tools/miri/tests/pass/pointers.rs
index d1340a04e04..1525ded6151 100644
--- a/src/tools/miri/tests/pass/pointers.rs
+++ b/src/tools/miri/tests/pass/pointers.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 #![feature(ptr_metadata, const_raw_ptr_comparison)]
 
diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs
index c411f748a06..835daa36cfc 100644
--- a/src/tools/miri/tests/pass/provenance.rs
+++ b/src/tools/miri/tests/pass/provenance.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(strict_provenance)]
 #![feature(pointer_byte_offsets)]
 use std::{mem, ptr};
diff --git a/src/tools/miri/tests/pass/ptr_int_casts.rs b/src/tools/miri/tests/pass/ptr_int_casts.rs
index 3044ac092b7..a2fcd098107 100644
--- a/src/tools/miri/tests/pass/ptr_int_casts.rs
+++ b/src/tools/miri/tests/pass/ptr_int_casts.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 use std::mem;
 use std::ptr;
diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
index ef7ff34d26b..35a52d0220b 100644
--- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
+++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 #![feature(strict_provenance)]
 
diff --git a/src/tools/miri/tests/pass/ptr_int_transmute.rs b/src/tools/miri/tests/pass/ptr_int_transmute.rs
index ba50480c539..d99c25413e6 100644
--- a/src/tools/miri/tests/pass/ptr_int_transmute.rs
+++ b/src/tools/miri/tests/pass/ptr_int_transmute.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 // Test what happens when we read parts of a pointer.
 // Related to <https://github.com/rust-lang/rust/issues/69488>.
 fn ptr_partial_read() {
diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs
index 569dbc459a5..6375abcd232 100644
--- a/src/tools/miri/tests/pass/rc.rs
+++ b/src/tools/miri/tests/pass/rc.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(new_uninit)]
 #![feature(get_mut_unchecked)]
diff --git a/src/tools/miri/tests/pass/send-is-not-static-par-for.rs b/src/tools/miri/tests/pass/send-is-not-static-par-for.rs
index 642f75ecc09..458312508d2 100644
--- a/src/tools/miri/tests/pass/send-is-not-static-par-for.rs
+++ b/src/tools/miri/tests/pass/send-is-not-static-par-for.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 use std::sync::Mutex;
 
 fn par_for<I, F>(iter: I, f: F)
diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs
index a56b97a5088..a99e921150b 100644
--- a/src/tools/miri/tests/pass/slices.rs
+++ b/src/tools/miri/tests/pass/slices.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(new_uninit)]
 #![feature(slice_as_chunks)]
diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs
index 3ca937ae13d..74761a89cb9 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs
@@ -7,7 +7,7 @@ use std::{
 
 extern "Rust" {
     fn miri_get_alloc_id(ptr: *const u8) -> u64;
-    fn miri_print_borrow_stacks(alloc_id: u64);
+    fn miri_print_borrow_state(alloc_id: u64, show_unnamed: bool);
 }
 
 fn get_alloc_id(ptr: *const u8) -> u64 {
@@ -15,7 +15,9 @@ fn get_alloc_id(ptr: *const u8) -> u64 {
 }
 
 fn print_borrow_stacks(alloc_id: u64) {
-    unsafe { miri_print_borrow_stacks(alloc_id) }
+    unsafe {
+        miri_print_borrow_state(alloc_id, /* ignored: show_unnamed */ false)
+    }
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/pass/threadleak_ignored.rs b/src/tools/miri/tests/pass/threadleak_ignored.rs
index a5f81573e96..d4899856194 100644
--- a/src/tools/miri/tests/pass/threadleak_ignored.rs
+++ b/src/tools/miri/tests/pass/threadleak_ignored.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-ignore-leaks
 
 //! Test that leaking threads works, and that their destructors are not executed.
diff --git a/src/tools/miri/tests/pass/threadleak_ignored.stderr b/src/tools/miri/tests/pass/threadleak_ignored.stack.stderr
index 7557f49c758..7557f49c758 100644
--- a/src/tools/miri/tests/pass/threadleak_ignored.stderr
+++ b/src/tools/miri/tests/pass/threadleak_ignored.stack.stderr
diff --git a/src/tools/miri/tests/pass/threadleak_ignored.tree.stderr b/src/tools/miri/tests/pass/threadleak_ignored.tree.stderr
new file mode 100644
index 00000000000..7557f49c758
--- /dev/null
+++ b/src/tools/miri/tests/pass/threadleak_ignored.tree.stderr
@@ -0,0 +1 @@
+Dropping 0
diff --git a/src/tools/miri/tests/pass/transmute_ptr.rs b/src/tools/miri/tests/pass/transmute_ptr.rs
index fd9d457e440..ce6d86b7068 100644
--- a/src/tools/miri/tests/pass/transmute_ptr.rs
+++ b/src/tools/miri/tests/pass/transmute_ptr.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(strict_provenance)]
 use std::{mem, ptr};
 
diff --git a/src/tools/miri/tests/pass/tree-borrows/2phase-interiormut.rs b/src/tools/miri/tests/pass/tree-borrows/2phase-interiormut.rs
new file mode 100644
index 00000000000..af52f53791a
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/2phase-interiormut.rs
@@ -0,0 +1,27 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// Counterpart to tests/fail/tree-borrows/write-during-2phase.rs,
+// this is the opposite situation: the Write is not problematic because
+// the Protector has not yet been added and the Reserved has interior
+// mutability.
+use core::cell::Cell;
+
+trait Thing: Sized {
+    fn do_the_thing(&mut self, _s: i32) {}
+}
+impl<T> Thing for Cell<T> {}
+
+fn main() {
+    let mut x = Cell::new(1);
+    let l = &x;
+
+    x.do_the_thing({
+        // Several Foreign accesses (both Reads and Writes) to the location
+        // being reborrowed. Reserved + unprotected + interior mut
+        // makes the pointer immune to everything as long as all accesses
+        // are child accesses to its parent pointer x.
+        x.set(3);
+        l.set(4);
+        x.get() + l.get()
+    });
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.rs b/src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.rs
new file mode 100644
index 00000000000..1bd94c6df67
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.rs
@@ -0,0 +1,27 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+#[path = "../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+
+use std::cell::UnsafeCell;
+
+// UnsafeCells use the parent tag, so it is possible to use them with
+// few restrictions when only among themselves.
+fn main() {
+    unsafe {
+        let data = &mut UnsafeCell::new(0u8);
+        name!(data.get(), "data");
+        let x = &*data;
+        name!(x.get(), "x");
+        let y = &*data;
+        name!(y.get(), "y");
+        let alloc_id = alloc_id!(data.get());
+        print_state!(alloc_id);
+        // y and x tolerate alternating Writes
+        *y.get() = 1;
+        *x.get() = 2;
+        *y.get() = 3;
+        *x.get() = 4;
+        print_state!(alloc_id);
+    }
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.stderr b/src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.stderr
new file mode 100644
index 00000000000..d4bc822b4bb
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/cell-alternate-writes.stderr
@@ -0,0 +1,10 @@
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Re*|    └────<TAG=data,x,y>
+──────────────────────────────────────────────────────────────────────
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Act|    └────<TAG=data,x,y>
+──────────────────────────────────────────────────────────────────────
diff --git a/src/tools/miri/tests/pass/tree-borrows/copy-nonoverlapping.rs b/src/tools/miri/tests/pass/tree-borrows/copy-nonoverlapping.rs
new file mode 100644
index 00000000000..23250d6e6df
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/copy-nonoverlapping.rs
@@ -0,0 +1,29 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// copy_nonoverlapping works regardless of the order in which we construct
+// the arguments.
+pub fn main() {
+    test_to_from();
+    test_from_to();
+}
+
+fn test_to_from() {
+    unsafe {
+        let data = &mut [0u64, 1];
+        let to = data.as_mut_ptr().add(1);
+        let from = data.as_ptr();
+        std::ptr::copy_nonoverlapping(from, to, 1);
+    }
+}
+
+// Stacked Borrows would not have liked this one because the `as_mut_ptr` reborrow
+// invalidates the earlier pointer obtained from `as_ptr`, but Tree Borrows is fine
+// with it.
+fn test_from_to() {
+    unsafe {
+        let data = &mut [0u64, 1];
+        let from = data.as_ptr();
+        let to = data.as_mut_ptr().add(1);
+        std::ptr::copy_nonoverlapping(from, to, 1);
+    }
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/end-of-protector.rs b/src/tools/miri/tests/pass/tree-borrows/end-of-protector.rs
new file mode 100644
index 00000000000..76bbc73e662
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/end-of-protector.rs
@@ -0,0 +1,32 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+
+// Check that a protector goes back to normal behavior when the function
+// returns.
+#[path = "../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+
+fn main() {
+    unsafe {
+        let data = &mut 0u8;
+        name!(data);
+        let alloc_id = alloc_id!(data);
+        let x = &mut *data;
+        name!(x);
+        print_state!(alloc_id);
+        do_nothing(x); // creates then removes a Protector for a child of x
+        let y = &mut *data;
+        name!(y);
+        print_state!(alloc_id);
+        // Invalidates the previous reborrow, but its Protector has been removed.
+        *y = 1;
+        print_state!(alloc_id);
+    }
+}
+
+unsafe fn do_nothing(x: &mut u8) {
+    name!(x, "callee:x");
+    name!(x=>1, "caller:x");
+    let alloc_id = alloc_id!(x);
+    print_state!(alloc_id);
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/end-of-protector.stderr b/src/tools/miri/tests/pass/tree-borrows/end-of-protector.stderr
new file mode 100644
index 00000000000..d08d6948320
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/end-of-protector.stderr
@@ -0,0 +1,32 @@
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Res|    └─┬──<TAG=data>
+| Res|      └────<TAG=x>
+──────────────────────────────────────────────────────────────────────
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Res|    └─┬──<TAG=data>
+| Res|      └─┬──<TAG=x>
+| Res|        └─┬──<TAG=caller:x>
+| Res|          └────<TAG=callee:x> Strongly protected
+──────────────────────────────────────────────────────────────────────
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Res|    └─┬──<TAG=data>
+| Res|      ├─┬──<TAG=x>
+| Res|      │ └─┬──<TAG=caller:x>
+| Res|      │   └────<TAG=callee:x>
+| Res|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Act|    └─┬──<TAG=data>
+| Dis|      ├─┬──<TAG=x>
+| Dis|      │ └─┬──<TAG=caller:x>
+| Dis|      │   └────<TAG=callee:x>
+| Act|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
diff --git a/src/tools/miri/tests/pass/tree-borrows/formatting.rs b/src/tools/miri/tests/pass/tree-borrows/formatting.rs
new file mode 100644
index 00000000000..9021c417638
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/formatting.rs
@@ -0,0 +1,73 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+
+#[path = "../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+
+// Check the formatting of the trees.
+fn main() {
+    unsafe {
+        alignment_check();
+        structure_check();
+    }
+}
+
+// Alignment check: we split the array at indexes with different amounts of
+// decimal digits to verify proper padding.
+unsafe fn alignment_check() {
+    let data: &mut [u8] = &mut [0; 1024];
+    name!(data.as_ptr()=>2, "data");
+    let alloc_id = alloc_id!(data.as_ptr());
+    let x = &mut data[1];
+    name!(x as *mut _, "data[1]");
+    *x = 1;
+    let x = &mut data[10];
+    name!(x as *mut _, "data[10]");
+    *x = 1;
+    let x = &mut data[100];
+    name!(x as *mut _, "data[100]");
+    *x = 1;
+    let _val = data[100]; // So that the above is Frz
+    let x = &mut data[1000];
+    name!(x as *mut _, "data[1000]");
+    *x = 1;
+    print_state!(alloc_id);
+}
+
+// Tree structure check: somewhat complex organization of reborrows.
+unsafe fn structure_check() {
+    let x = &0u8;
+    name!(x);
+    let xa = &*x;
+    name!(xa);
+    let xb = &*x;
+    name!(xb);
+    let xc = &*x;
+    name!(xc);
+    let xaa = &*xa;
+    name!(xaa);
+    let xab = &*xa;
+    name!(xab);
+    let xba = &*xb;
+    name!(xba);
+    let xbaa = &*xba;
+    name!(xbaa);
+    let xbaaa = &*xbaa;
+    name!(xbaaa);
+    let xbaaaa = &*xbaaa;
+    name!(xbaaaa);
+    let xca = &*xc;
+    name!(xca);
+    let xcb = &*xc;
+    name!(xcb);
+    let xcaa = &*xca;
+    name!(xcaa);
+    let xcab = &*xca;
+    name!(xcab);
+    let xcba = &*xcb;
+    name!(xcba);
+    let xcbb = &*xcb;
+    name!(xcbb);
+    let alloc_id = alloc_id!(x);
+    print_state!(alloc_id);
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/formatting.stderr b/src/tools/miri/tests/pass/tree-borrows/formatting.stderr
new file mode 100644
index 00000000000..a59775cf21f
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/formatting.stderr
@@ -0,0 +1,29 @@
+─────────────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1..  2.. 10.. 11..100..101..1000..1001..1024
+| Res| Act| Res| Act| Res| Act|  Res|  Act|  Res|    └─┬──<TAG=data>
+|----| Act|----|?Dis|----|?Dis| ----| ?Dis| ----|      ├────<TAG=data[1]>
+|----|----|----| Act|----|?Dis| ----| ?Dis| ----|      ├────<TAG=data[10]>
+|----|----|----|----|----| Frz| ----| ?Dis| ----|      ├────<TAG=data[100]>
+|----|----|----|----|----|----| ----|  Act| ----|      └────<TAG=data[1000]>
+─────────────────────────────────────────────────────────────────────────────
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Frz|    └─┬──<TAG=x>
+| Frz|      ├─┬──<TAG=xa>
+| Frz|      │ ├────<TAG=xaa>
+| Frz|      │ └────<TAG=xab>
+| Frz|      ├─┬──<TAG=xb>
+| Frz|      │ └─┬──<TAG=xba>
+| Frz|      │   └─┬──<TAG=xbaa>
+| Frz|      │     └─┬──<TAG=xbaaa>
+| Frz|      │       └────<TAG=xbaaaa>
+| Frz|      └─┬──<TAG=xc>
+| Frz|        ├─┬──<TAG=xca>
+| Frz|        │ ├────<TAG=xcaa>
+| Frz|        │ └────<TAG=xcab>
+| Frz|        └─┬──<TAG=xcb>
+| Frz|          ├────<TAG=xcba>
+| Frz|          └────<TAG=xcbb>
+──────────────────────────────────────────────────────────────────────
diff --git a/src/tools/miri/tests/pass/tree-borrows/read-only-from-mut.rs b/src/tools/miri/tests/pass/tree-borrows/read-only-from-mut.rs
new file mode 100644
index 00000000000..4daf06c777e
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/read-only-from-mut.rs
@@ -0,0 +1,14 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+// Tree Borrows has no issue with several mutable references existing
+// at the same time, as long as they are used only immutably.
+// I.e. multiple Reserved can coexist.
+pub fn main() {
+    unsafe {
+        let base = &mut 42u64;
+        let r1 = &mut *(base as *mut u64);
+        let r2 = &mut *(base as *mut u64);
+        let _l = *r1;
+        let _l = *r2;
+    }
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.rs b/src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.rs
new file mode 100644
index 00000000000..e3f3f2d4032
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.rs
@@ -0,0 +1,24 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+
+#[path = "../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+
+// To check that a reborrow is counted as a Read access, we use a reborrow
+// with no additional Read to Freeze an Active pointer.
+
+fn main() {
+    unsafe {
+        let parent = &mut 0u8;
+        name!(parent);
+        let alloc_id = alloc_id!(parent);
+        let x = &mut *parent;
+        name!(x);
+        *x = 0; // x is now Active
+        print_state!(alloc_id);
+        let y = &mut *parent;
+        name!(y);
+        // Check in the debug output that x has been Frozen by the reborrow
+        print_state!(alloc_id);
+    }
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.stderr b/src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.stderr
new file mode 100644
index 00000000000..b9c52c20640
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/reborrow-is-read.stderr
@@ -0,0 +1,13 @@
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Act|    └─┬──<TAG=parent>
+| Act|      └────<TAG=x>
+──────────────────────────────────────────────────────────────────────
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Act|    └─┬──<TAG=parent>
+| Frz|      ├────<TAG=x>
+| Res|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
diff --git a/src/tools/miri/tests/pass/tree-borrows/reserved.rs b/src/tools/miri/tests/pass/tree-borrows/reserved.rs
new file mode 100644
index 00000000000..d8a8c27568d
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/reserved.rs
@@ -0,0 +1,127 @@
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0
+
+#[path = "../../utils/mod.rs"]
+mod utils;
+use utils::macros::*;
+use utils::miri_extern::miri_write_to_stderr;
+
+use std::cell::UnsafeCell;
+
+// We exhaustively check that Reserved behaves as we want under all of the
+// following conditions:
+// - with or without interior mutability
+// - with or without a protector
+// - for a foreign read or write
+// Of these cases, those in this file are the ones that must not cause
+// immediate UB, and those that do are in tests/fail/tree-borrows/reserved/
+// and are the combinations [_ + protected + write]
+
+fn main() {
+    unsafe {
+        cell_protected_read();
+        cell_unprotected_read();
+        cell_unprotected_write();
+        int_protected_read();
+        int_unprotected_read();
+        int_unprotected_write();
+    }
+}
+
+unsafe fn print(msg: &str) {
+    miri_write_to_stderr(msg.as_bytes());
+    miri_write_to_stderr("\n".as_bytes());
+}
+
+unsafe fn read_second<T>(x: &mut T, y: *mut u8) {
+    name!(x as *mut T as *mut u8=>1, "caller:x");
+    name!(x as *mut T as *mut u8, "callee:x");
+    name!(y, "caller:y");
+    name!(y, "callee:y");
+    let _val = *y;
+}
+
+// Foreign Read on a interior mutable Protected Reserved turns it Frozen.
+unsafe fn cell_protected_read() {
+    print("[interior mut + protected] Foreign Read: Re* -> Frz");
+    let base = &mut UnsafeCell::new(0u8);
+    name!(base.get(), "base");
+    let alloc_id = alloc_id!(base.get());
+    let x = &mut *(base as *mut UnsafeCell<u8>);
+    name!(x.get(), "x");
+    let y = (&mut *base).get();
+    name!(y);
+    read_second(x, y); // Foreign Read for callee:x
+    print_state!(alloc_id);
+}
+
+// Foreign Read on an interior mutable pointer is a noop.
+unsafe fn cell_unprotected_read() {
+    print("[interior mut] Foreign Read: Re* -> Re*");
+    let base = &mut UnsafeCell::new(0u64);
+    name!(base.get(), "base");
+    let alloc_id = alloc_id!(base.get());
+    let x = &mut *(base as *mut UnsafeCell<_>);
+    name!(x.get(), "x");
+    let y = (&mut *base).get();
+    name!(y);
+    let _val = *y; // Foreign Read for x
+    print_state!(alloc_id);
+}
+
+// Foreign Write on an interior mutable pointer is a noop.
+// Also y must become Active.
+unsafe fn cell_unprotected_write() {
+    print("[interior mut] Foreign Write: Re* -> Re*");
+    let base = &mut UnsafeCell::new(0u64);
+    name!(base.get(), "base");
+    let alloc_id = alloc_id!(base.get());
+    let x = &mut *(base as *mut UnsafeCell<u64>);
+    name!(x.get(), "x");
+    let y = (&mut *base).get();
+    name!(y);
+    *y = 1; // Foreign Write for x
+    print_state!(alloc_id);
+}
+
+// Foreign Read on a Protected Reserved turns it Frozen.
+unsafe fn int_protected_read() {
+    print("[protected] Foreign Read: Res -> Frz");
+    let base = &mut 0u8;
+    let alloc_id = alloc_id!(base);
+    name!(base);
+    let x = &mut *(base as *mut u8);
+    name!(x);
+    let y = (&mut *base) as *mut u8;
+    name!(y);
+    read_second(x, y); // Foreign Read for callee:x
+    print_state!(alloc_id);
+}
+
+// Foreign Read on a Reserved is a noop.
+// Also y must become Active.
+unsafe fn int_unprotected_read() {
+    print("[] Foreign Read: Res -> Res");
+    let base = &mut 0u8;
+    name!(base);
+    let alloc_id = alloc_id!(base);
+    let x = &mut *(base as *mut u8);
+    name!(x);
+    let y = (&mut *base) as *mut u8;
+    name!(y);
+    let _val = *y; // Foreign Read for x
+    print_state!(alloc_id);
+}
+
+// Foreign Write on a Reserved turns it Disabled.
+unsafe fn int_unprotected_write() {
+    print("[] Foreign Write: Res -> Dis");
+    let base = &mut 0u8;
+    name!(base);
+    let alloc_id = alloc_id!(base);
+    let x = &mut *(base as *mut u8);
+    name!(x);
+    let y = (&mut *base) as *mut u8;
+    name!(y);
+    *y = 1; // Foreign Write for x
+    print_state!(alloc_id);
+}
diff --git a/src/tools/miri/tests/pass/tree-borrows/reserved.stderr b/src/tools/miri/tests/pass/tree-borrows/reserved.stderr
new file mode 100644
index 00000000000..d76ee0f8266
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/reserved.stderr
@@ -0,0 +1,52 @@
+[interior mut + protected] Foreign Read: Re* -> Frz
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Re*|    └─┬──<TAG=base>
+| Re*|      ├─┬──<TAG=x>
+| Re*|      │ └─┬──<TAG=caller:x>
+| Frz|      │   └────<TAG=callee:x>
+| Re*|      └────<TAG=y,caller:y,callee:y>
+──────────────────────────────────────────────────────────────────────
+[interior mut] Foreign Read: Re* -> Re*
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  8
+| Re*|    └─┬──<TAG=base>
+| Re*|      ├────<TAG=x>
+| Re*|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
+[interior mut] Foreign Write: Re* -> Re*
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  8
+| Act|    └─┬──<TAG=base>
+| Re*|      ├────<TAG=x>
+| Act|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
+[protected] Foreign Read: Res -> Frz
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Res|    └─┬──<TAG=base>
+| Res|      ├─┬──<TAG=x>
+| Res|      │ └─┬──<TAG=caller:x>
+| Frz|      │   └────<TAG=callee:x>
+| Res|      └────<TAG=y,caller:y,callee:y>
+──────────────────────────────────────────────────────────────────────
+[] Foreign Read: Res -> Res
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Res|    └─┬──<TAG=base>
+| Res|      ├────<TAG=x>
+| Res|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
+[] Foreign Write: Res -> Dis
+──────────────────────────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..  1
+| Act|    └─┬──<TAG=base>
+| Dis|      ├────<TAG=x>
+| Act|      └────<TAG=y>
+──────────────────────────────────────────────────────────────────────
diff --git a/src/tools/miri/tests/pass/tree-borrows/transmute-unsafecell.rs b/src/tools/miri/tests/pass/tree-borrows/transmute-unsafecell.rs
new file mode 100644
index 00000000000..e1a9334ab54
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree-borrows/transmute-unsafecell.rs
@@ -0,0 +1,13 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+use core::cell::UnsafeCell;
+use core::mem;
+
+fn main() {
+    unsafe {
+        let x = &0i32;
+        // As long as we only read, transmuting this to UnsafeCell should be fine.
+        let cell_x: &UnsafeCell<i32> = mem::transmute(&x);
+        let _val = *cell_x.get();
+    }
+}
diff --git a/src/tools/miri/tests/pass/unsized.rs b/src/tools/miri/tests/pass/unsized.rs
index d9beac4327d..c9046dc3c76 100644
--- a/src/tools/miri/tests/pass/unsized.rs
+++ b/src/tools/miri/tests/pass/unsized.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(unsized_tuple_coercion)]
 #![feature(unsized_fn_params)]
 
diff --git a/src/tools/miri/tests/pass/vec.rs b/src/tools/miri/tests/pass/vec.rs
index 30a28bc5803..06ec2f99172 100644
--- a/src/tools/miri/tests/pass/vec.rs
+++ b/src/tools/miri/tests/pass/vec.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(iter_advance_by, iter_next_chunk)]
 
diff --git a/src/tools/miri/tests/pass/vecdeque.rs b/src/tools/miri/tests/pass/vecdeque.rs
index 6f56f9d103e..dfbf9bb83c1 100644
--- a/src/tools/miri/tests/pass/vecdeque.rs
+++ b/src/tools/miri/tests/pass/vecdeque.rs
@@ -1,3 +1,5 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
 use std::collections::VecDeque;
 
diff --git a/src/tools/miri/tests/pass/vecdeque.stdout b/src/tools/miri/tests/pass/vecdeque.stack.stdout
index 63de960ee2b..63de960ee2b 100644
--- a/src/tools/miri/tests/pass/vecdeque.stdout
+++ b/src/tools/miri/tests/pass/vecdeque.stack.stdout
diff --git a/src/tools/miri/tests/pass/vecdeque.tree.stdout b/src/tools/miri/tests/pass/vecdeque.tree.stdout
new file mode 100644
index 00000000000..63de960ee2b
--- /dev/null
+++ b/src/tools/miri/tests/pass/vecdeque.tree.stdout
@@ -0,0 +1,2 @@
+[2, 2] Iter([2, 2], [])
+Iter([], [])
diff --git a/src/tools/miri/tests/utils/macros.rs b/src/tools/miri/tests/utils/macros.rs
new file mode 100644
index 00000000000..de223410fba
--- /dev/null
+++ b/src/tools/miri/tests/utils/macros.rs
@@ -0,0 +1,61 @@
+#![allow(unused_macros)]
+#![allow(unused_macro_rules)]
+#![allow(unused_imports)]
+
+/// `alloc_id!(ptr)`: obtain the allocation id from a pointer.
+///
+/// `ptr` should be any pointer or reference that can be converted with `_ as *const u8`.
+///
+/// The id obtained can be passed directly to `print_state!`.
+macro_rules! alloc_id {
+    ($ptr:expr) => {
+        crate::utils::miri_extern::miri_get_alloc_id($ptr as *const u8 as *const ())
+    };
+}
+
+/// `print_state!(alloc_id, show_unnamed)`: print the internal state of the borrow
+/// tracker (stack or tree).
+///
+/// `alloc_id` should be obtained from `alloc_id!`.
+///
+/// `show_unnamed` is an optional boolean that determines if Tree Borrows displays
+/// tags that have not been given a name. Defaults to `false`.
+macro_rules! print_state {
+    ($alloc_id:expr) => {
+        crate::utils::macros::print_state!($alloc_id, false);
+    };
+    ($alloc_id:expr, $show:expr) => {
+        crate::utils::miri_extern::miri_print_borrow_state($alloc_id, $show);
+    };
+}
+
+/// `name!(ptr => nth_parent, name)`: associate `name` to the `nth_parent` of `ptr`.
+///
+/// `ptr` should be any pointer or reference that can be converted with `_ as *const u8`.
+///
+/// `nth_parent` is an optional `u8` that defaults to 0. The corresponding ancestor
+/// of the tag of `ptr` will be searched: 0 for `ptr` itself, 1 for the direct parent
+/// of `ptr`, 2 for the grandparent, etc. If `nth_parent` is not specified,
+/// then `=>` should also not be included.
+///
+/// `name` is an optional string that will be used as the name. Defaults to
+/// `stringify!($ptr)` the name of `ptr` in the source code.
+macro_rules! name {
+    ($ptr:expr, $name:expr) => {
+        crate::utils::macros::name!($ptr => 0, $name);
+    };
+    ($ptr:expr) => {
+        crate::utils::macros::name!($ptr => 0, stringify!($ptr));
+    };
+    ($ptr:expr => $nb:expr) => {
+        crate::utils::macros::name!($ptr => $nb, stringify!($ptr));
+    };
+    ($ptr:expr => $nb:expr, $name:expr) => {
+        let name = $name.as_bytes();
+        crate::utils::miri_extern::miri_pointer_name($ptr as *const u8 as *const (), $nb, name);
+    };
+}
+
+pub(crate) use alloc_id;
+pub(crate) use name;
+pub(crate) use print_state;
diff --git a/src/tools/miri/tests/utils/miri_extern.rs b/src/tools/miri/tests/utils/miri_extern.rs
new file mode 100644
index 00000000000..6c4298c613b
--- /dev/null
+++ b/src/tools/miri/tests/utils/miri_extern.rs
@@ -0,0 +1,142 @@
+#![allow(dead_code)]
+
+#[repr(C)]
+/// Layout of the return value of `miri_resolve_frame`,
+/// with fields in the exact same order.
+pub struct MiriFrame {
+    // The size of the name of the function being executed, encoded in UTF-8
+    pub name_len: usize,
+    // The size of filename of the function being executed, encoded in UTF-8
+    pub filename_len: usize,
+    // The line number currently being executed in `filename`, starting from '1'.
+    pub lineno: u32,
+    // The column number currently being executed in `filename`, starting from '1'.
+    pub colno: u32,
+    // The function pointer to the function currently being executed.
+    // This can be compared against function pointers obtained by
+    // casting a function (e.g. `my_fn as *mut ()`)
+    pub fn_ptr: *mut (),
+}
+
+#[cfg(miri)]
+extern "Rust" {
+    /// Miri-provided extern function to mark the block `ptr` points to as a "root"
+    /// for some static memory. This memory and everything reachable by it is not
+    /// considered leaking even if it still exists when the program terminates.
+    ///
+    /// `ptr` has to point to the beginning of an allocated block.
+    pub fn miri_static_root(ptr: *const u8);
+
+    // Miri-provided extern function to get the amount of frames in the current backtrace.
+    // The `flags` argument must be `0`.
+    pub fn miri_backtrace_size(flags: u64) -> usize;
+
+    /// Miri-provided extern function to obtain a backtrace of the current call stack.
+    /// This writes a slice of pointers into `buf` - each pointer is an opaque value
+    /// that is only useful when passed to `miri_resolve_frame`.
+    /// `buf` must have `miri_backtrace_size(0) * pointer_size` bytes of space.
+    /// The `flags` argument must be `1`.
+    pub fn miri_get_backtrace(flags: u64, buf: *mut *mut ());
+
+    /// Miri-provided extern function to resolve a frame pointer obtained
+    /// from `miri_get_backtrace`. The `flags` argument must be `1`.
+    ///
+    /// This function can be called on any thread (not just the one which obtained `frame`).
+    pub fn miri_resolve_frame(frame: *mut (), flags: u64) -> MiriFrame;
+
+    /// Miri-provided extern function to get the name and filename of the frame provided by `miri_resolve_frame`.
+    /// `name_buf` and `filename_buf` should be allocated with the `name_len` and `filename_len` fields of `MiriFrame`.
+    /// The flags argument must be `0`.
+    pub fn miri_resolve_frame_names(
+        ptr: *mut (),
+        flags: u64,
+        name_buf: *mut u8,
+        filename_buf: *mut u8,
+    );
+
+    /// Miri-provided extern function to begin unwinding with the given payload.
+    ///
+    /// This is internal and unstable and should not be used; we give it here
+    /// just to be complete.
+    pub fn miri_start_panic(payload: *mut u8) -> !;
+
+    /// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer
+    /// points to. If this pointer is invalid (not pointing to an allocation), interpretation will abort.
+    ///
+    /// This is only useful as an input to `miri_print_borrow_stacks`, and it is a separate call because
+    /// getting a pointer to an allocation at runtime can change the borrow stacks in the allocation.
+    /// This function should be considered unstable. It exists only to support `miri_print_borrow_stacks` and so
+    /// inherits all of its instability.
+    pub fn miri_get_alloc_id(ptr: *const ()) -> u64;
+
+    /// Miri-provided extern function to print (from the interpreter, not the program) the contents of all
+    /// borrows in an allocation.
+    ///
+    /// If Stacked Borrows is running, this prints all the stacks. The leftmost tag is the bottom of the stack.
+    ///
+    /// If Tree borrows is running, this prints on the left the permissions of each tag on each range,
+    /// an on the right the tree structure of the tags. If some tags were named via `miri_pointer_name`,
+    /// their names appear here.
+    ///
+    /// If additionally `show_unnamed` is `false` then tags that did *not* receive a name will be hidden.
+    /// Ensure that either the important tags have been named, or `show_unnamed = true`.
+    /// Note: as Stacked Borrows does not have tag names at all, `show_unnamed` is ignored and all tags are shown.
+    /// In general, unless you strongly want some tags to be hidden (as is the case in `tree-borrows` tests),
+    /// `show_unnamed = true` should be the default.
+    ///
+    /// The format of what this emits is unstable and may change at any time. In particular, users should be
+    /// aware that Miri will periodically attempt to garbage collect the contents of all stacks. Callers of
+    /// this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC.
+    ///
+    /// This function is extremely unstable. At any time the format of its output may change, its signature may
+    /// change, or it may be removed entirely.
+    pub fn miri_print_borrow_state(alloc_id: u64, show_unnamed: bool);
+
+    /// Miri-provided extern function to associate a name to the nth parent of a tag.
+    /// Typically the name given would be the name of the program variable that holds the pointer.
+    /// Unreachable tags can still be named by using nonzero `nth_parent` and a child tag.
+    ///
+    /// This function does nothing under Stacked Borrows, since Stacked Borrows's implementation
+    /// of `miri_print_borrow_state` does not show the names.
+    ///
+    /// Under Tree Borrows, the names also appear in error messages.
+    pub fn miri_pointer_name(ptr: *const (), nth_parent: u8, name: &[u8]);
+
+    /// Miri-provided extern function to print (from the interpreter, not the
+    /// program) the contents of a section of program memory, as bytes. Bytes
+    /// written using this function will emerge from the interpreter's stdout.
+    pub fn miri_write_to_stdout(bytes: &[u8]);
+
+    /// Miri-provided extern function to print (from the interpreter, not the
+    /// program) the contents of a section of program memory, as bytes. Bytes
+    /// written using this function will emerge from the interpreter's stderr.
+    pub fn miri_write_to_stderr(bytes: &[u8]);
+
+    /// Miri-provided extern function to allocate memory from the interpreter.
+    ///
+    /// This is useful when no fundamental way of allocating memory is
+    /// available, e.g. when using `no_std` + `alloc`.
+    pub fn miri_alloc(size: usize, align: usize) -> *mut u8;
+
+    /// Miri-provided extern function to deallocate memory.
+    pub fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
+
+    /// Convert a path from the host Miri runs on to the target Miri interprets.
+    /// Performs conversion of path separators as needed.
+    ///
+    /// Usually Miri performs this kind of conversion automatically. However, manual conversion
+    /// might be necessary when reading an environment variable that was set on the host
+    /// (such as TMPDIR) and using it as a target path.
+    ///
+    /// Only works with isolation disabled.
+    ///
+    /// `in` must point to a null-terminated string, and will be read as the input host path.
+    /// `out` must point to at least `out_size` many bytes, and the result will be stored there
+    /// with a null terminator.
+    /// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
+    pub fn miri_host_to_target_path(
+        path: *const std::ffi::c_char,
+        out: *mut std::ffi::c_char,
+        out_size: usize,
+    ) -> usize;
+}
diff --git a/src/tools/miri/tests/utils/mod.rs b/src/tools/miri/tests/utils/mod.rs
new file mode 100644
index 00000000000..e1ea77e4df8
--- /dev/null
+++ b/src/tools/miri/tests/utils/mod.rs
@@ -0,0 +1,2 @@
+pub mod macros;
+pub mod miri_extern;
diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs
index 2d6abe59343..070ce93f97c 100644
--- a/src/tools/tidy/src/bins.rs
+++ b/src/tools/tidy/src/bins.rs
@@ -103,7 +103,7 @@ mod os_impl {
 
         // FIXME: we don't need to look at all binaries, only files that have been modified in this branch
         // (e.g. using `git ls-files`).
-        walk_no_read(path, |path| filter_dirs(path) || path.ends_with("src/etc"), &mut |entry| {
+        walk_no_read(&[path], |path| filter_dirs(path) || path.ends_with("src/etc"), &mut |entry| {
             let file = entry.path();
             let extension = file.extension();
             let scripts = ["py", "sh", "ps1"];
diff --git a/src/tools/tidy/src/debug_artifacts.rs b/src/tools/tidy/src/debug_artifacts.rs
index 2241375eaae..84b13306805 100644
--- a/src/tools/tidy/src/debug_artifacts.rs
+++ b/src/tools/tidy/src/debug_artifacts.rs
@@ -1,21 +1,15 @@
 //! Tidy check to prevent creation of unnecessary debug artifacts while running tests.
 
-use crate::walk::{filter_dirs, walk};
+use crate::walk::{filter_dirs, filter_not_rust, walk};
 use std::path::Path;
 
 const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test";
 
 pub fn check(test_dir: &Path, bad: &mut bool) {
-    walk(test_dir, filter_dirs, &mut |entry, contents| {
-        let filename = entry.path();
-        let is_rust = filename.extension().map_or(false, |ext| ext == "rs");
-        if !is_rust {
-            return;
-        }
-
+    walk(test_dir, |path| filter_dirs(path) || filter_not_rust(path), &mut |entry, contents| {
         for (i, line) in contents.lines().enumerate() {
             if line.contains("borrowck_graphviz_postflow") {
-                tidy_error!(bad, "{}:{}: {}", filename.display(), i + 1, GRAPHVIZ_POSTFLOW_MSG);
+                tidy_error!(bad, "{}:{}: {}", entry.path().display(), i + 1, GRAPHVIZ_POSTFLOW_MSG);
             }
         }
     });
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 6d94417a10f..f18feda533c 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -9,8 +9,9 @@
 //! * All unstable lang features have tests to ensure they are actually unstable.
 //! * Language features in a group are sorted by feature name.
 
-use crate::walk::{filter_dirs, walk, walk_many};
+use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many};
 use std::collections::hash_map::{Entry, HashMap};
+use std::ffi::OsStr;
 use std::fmt;
 use std::fs;
 use std::num::NonZeroU32;
@@ -101,17 +102,15 @@ pub fn check(
             &tests_path.join("rustdoc-ui"),
             &tests_path.join("rustdoc"),
         ],
-        filter_dirs,
+        |path| {
+            filter_dirs(path)
+                || filter_not_rust(path)
+                || path.file_name() == Some(OsStr::new("features.rs"))
+                || path.file_name() == Some(OsStr::new("diagnostic_list.rs"))
+        },
         &mut |entry, contents| {
             let file = entry.path();
             let filename = file.file_name().unwrap().to_string_lossy();
-            if !filename.ends_with(".rs")
-                || filename == "features.rs"
-                || filename == "diagnostic_list.rs"
-            {
-                return;
-            }
-
             let filen_underscore = filename.replace('-', "_").replace(".rs", "");
             let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features);
 
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index d98758ace4f..f59406c404b 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -13,7 +13,7 @@ use std::path::PathBuf;
 use std::process;
 use std::str::FromStr;
 use std::sync::atomic::{AtomicBool, Ordering};
-use std::thread::{scope, ScopedJoinHandle};
+use std::thread::{self, scope, ScopedJoinHandle};
 
 fn main() {
     let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into();
@@ -55,16 +55,28 @@ fn main() {
             VecDeque::with_capacity(concurrency.get());
 
         macro_rules! check {
-            ($p:ident $(, $args:expr)* ) => {
+            ($p:ident) => {
+                check!(@ $p, name=format!("{}", stringify!($p)));
+            };
+            ($p:ident, $path:expr $(, $args:expr)* ) => {
+                let shortened = $path.strip_prefix(&root_path).unwrap();
+                let name = if shortened == std::path::Path::new("") {
+                    format!("{} (.)", stringify!($p))
+                } else {
+                    format!("{} ({})", stringify!($p), shortened.display())
+                };
+                check!(@ $p, name=name, $path $(,$args)*);
+            };
+            (@ $p:ident, name=$name:expr $(, $args:expr)* ) => {
                 drain_handles(&mut handles);
 
-                let handle = s.spawn(|| {
+                let handle = thread::Builder::new().name($name).spawn_scoped(s, || {
                     let mut flag = false;
                     $p::check($($args, )* &mut flag);
                     if (flag) {
                         bad.store(true, Ordering::Relaxed);
                     }
-                });
+                }).unwrap();
                 handles.push_back(handle);
             }
         }
@@ -108,7 +120,6 @@ fn main() {
         check!(edition, &library_path);
 
         check!(alphabetical, &src_path);
-        check!(alphabetical, &tests_path);
         check!(alphabetical, &compiler_path);
         check!(alphabetical, &library_path);
 
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 868579b4b1a..6b7b27fd526 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -59,7 +59,6 @@ const EXCEPTION_PATHS: &[&str] = &[
     "library/std/src/path.rs",
     "library/std/src/sys_common", // Should only contain abstractions over platforms
     "library/std/src/net/test.rs", // Utility helpers for tests
-    "library/std/src/panic.rs",   // fuchsia-specific panic backtrace handling
     "library/std/src/personality.rs",
     "library/std/src/personality/",
 ];
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 75a4586cb7f..a965c98f484 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -19,7 +19,7 @@
 
 use crate::walk::{filter_dirs, walk};
 use regex::{Regex, RegexSet};
-use std::path::Path;
+use std::{ffi::OsStr, path::Path};
 
 /// Error code markdown is restricted to 80 columns because they can be
 /// displayed on the console with --example.
@@ -228,21 +228,33 @@ fn is_unexplained_ignore(extension: &str, line: &str) -> bool {
 
 pub fn check(path: &Path, bad: &mut bool) {
     fn skip(path: &Path) -> bool {
-        filter_dirs(path) || skip_markdown_path(path)
+        if path.file_name().map_or(false, |name| name.to_string_lossy().starts_with(".#")) {
+            // vim or emacs temporary file
+            return true;
+        }
+
+        if filter_dirs(path) || skip_markdown_path(path) {
+            return true;
+        }
+
+        let extensions = ["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "goml"];
+        if extensions.iter().all(|e| path.extension() != Some(OsStr::new(e))) {
+            return true;
+        }
+
+        // We only check CSS files in rustdoc.
+        path.extension().map_or(false, |e| e == "css") && !is_in(path, "src", "librustdoc")
     }
+
     let problematic_consts_strings: Vec<String> = (PROBLEMATIC_CONSTS.iter().map(u32::to_string))
         .chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:x}", v)))
         .chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v)))
         .collect();
     let problematic_regex = RegexSet::new(problematic_consts_strings.as_slice()).unwrap();
+
     walk(path, skip, &mut |entry, contents| {
         let file = entry.path();
         let filename = file.file_name().unwrap().to_string_lossy();
-        let extensions =
-            [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl", ".goml"];
-        if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") {
-            return;
-        }
 
         let is_style_file = filename.ends_with(".css");
         let under_rustfmt = filename.ends_with(".rs") &&
@@ -253,11 +265,6 @@ pub fn check(path: &Path, bad: &mut bool) {
                     a.ends_with("src/doc/book")
             });
 
-        if is_style_file && !is_in(file, "src", "librustdoc") {
-            // We only check CSS files in rustdoc.
-            return;
-        }
-
         if contents.is_empty() {
             tidy_error!(bad, "{}: empty file", file.display());
         }
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index f41fa4fcce1..e0fa6aceb85 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -4,6 +4,8 @@
 use std::collections::BTreeMap;
 use std::path::Path;
 
+use crate::walk::filter_not_rust;
+
 const COMMENT: &str = "//";
 const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
 const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
@@ -35,61 +37,57 @@ struct RevisionInfo<'a> {
 }
 
 pub fn check(path: &Path, bad: &mut bool) {
-    crate::walk::walk(
-        path,
-        |path| path.extension().map(|p| p == "rs") == Some(false),
-        &mut |entry, content| {
-            let file = entry.path().display();
-            let mut header_map = BTreeMap::new();
-            iter_header(content, &mut |cfg, directive| {
-                if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
-                    let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
-                    let comp_vec = info.llvm_components.get_or_insert(Vec::new());
-                    for component in value.split(' ') {
-                        let component = component.trim();
-                        if !component.is_empty() {
-                            comp_vec.push(component);
-                        }
-                    }
-                } else if directive.starts_with(COMPILE_FLAGS_HEADER) {
-                    let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..];
-                    if let Some((_, v)) = compile_flags.split_once("--target") {
-                        if let Some((arch, _)) =
-                            v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-")
-                        {
-                            let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
-                            info.target_arch.replace(arch);
-                        } else {
-                            eprintln!("{file}: seems to have a malformed --target value");
-                            *bad = true;
-                        }
+    crate::walk::walk(path, filter_not_rust, &mut |entry, content| {
+        let file = entry.path().display();
+        let mut header_map = BTreeMap::new();
+        iter_header(content, &mut |cfg, directive| {
+            if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
+                let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
+                let comp_vec = info.llvm_components.get_or_insert(Vec::new());
+                for component in value.split(' ') {
+                    let component = component.trim();
+                    if !component.is_empty() {
+                        comp_vec.push(component);
                     }
                 }
-            });
-            for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map {
-                let rev = rev.unwrap_or("[unspecified]");
-                match (target_arch, llvm_components) {
-                    (None, None) => {}
-                    (Some(_), None) => {
-                        eprintln!(
-                            "{}: revision {} should specify `{}` as it has `--target` set",
-                            file, rev, LLVM_COMPONENTS_HEADER
-                        );
+            } else if directive.starts_with(COMPILE_FLAGS_HEADER) {
+                let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..];
+                if let Some((_, v)) = compile_flags.split_once("--target") {
+                    if let Some((arch, _)) =
+                        v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-")
+                    {
+                        let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
+                        info.target_arch.replace(arch);
+                    } else {
+                        eprintln!("{file}: seems to have a malformed --target value");
                         *bad = true;
                     }
-                    (None, Some(_)) => {
-                        eprintln!(
-                            "{}: revision {} should not specify `{}` as it doesn't need `--target`",
-                            file, rev, LLVM_COMPONENTS_HEADER
-                        );
-                        *bad = true;
-                    }
-                    (Some(_), Some(_)) => {
-                        // FIXME: check specified components against the target architectures we
-                        // gathered.
-                    }
                 }
             }
-        },
-    );
+        });
+        for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map {
+            let rev = rev.unwrap_or("[unspecified]");
+            match (target_arch, llvm_components) {
+                (None, None) => {}
+                (Some(_), None) => {
+                    eprintln!(
+                        "{}: revision {} should specify `{}` as it has `--target` set",
+                        file, rev, LLVM_COMPONENTS_HEADER
+                    );
+                    *bad = true;
+                }
+                (None, Some(_)) => {
+                    eprintln!(
+                        "{}: revision {} should not specify `{}` as it doesn't need `--target`",
+                        file, rev, LLVM_COMPONENTS_HEADER
+                    );
+                    *bad = true;
+                }
+                (Some(_), Some(_)) => {
+                    // FIXME: check specified components against the target architectures we
+                    // gathered.
+                }
+            }
+        }
+    });
 }
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 15c36923e88..66f5c932be2 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -3,87 +3,83 @@
 //! - there are no stray `.stderr` files
 
 use ignore::Walk;
-use ignore::WalkBuilder;
+use std::collections::HashMap;
 use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 940;
 const ISSUES_ENTRY_LIMIT: usize = 1978;
 
-fn check_entries(path: &Path, bad: &mut bool) {
-    for dir in Walk::new(&path.join("ui")) {
+fn check_entries(tests_path: &Path, bad: &mut bool) {
+    let mut directories: HashMap<PathBuf, usize> = HashMap::new();
+
+    for dir in Walk::new(&tests_path.join("ui")) {
         if let Ok(entry) = dir {
-            if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
-                let dir_path = entry.path();
-                // Use special values for these dirs.
-                let is_root = path.join("ui") == dir_path;
-                let is_issues_dir = path.join("ui/issues") == dir_path;
-                let limit = if is_root {
-                    ROOT_ENTRY_LIMIT
-                } else if is_issues_dir {
-                    ISSUES_ENTRY_LIMIT
-                } else {
-                    ENTRY_LIMIT
-                };
+            let parent = entry.path().parent().unwrap().to_path_buf();
+            *directories.entry(parent).or_default() += 1;
+        }
+    }
 
-                let count = WalkBuilder::new(&dir_path)
-                    .max_depth(Some(1))
-                    .build()
-                    .into_iter()
-                    .collect::<Vec<_>>()
-                    .len()
-                    - 1; // remove the dir itself
+    for (dir_path, count) in directories {
+        // Use special values for these dirs.
+        let is_root = tests_path.join("ui") == dir_path;
+        let is_issues_dir = tests_path.join("ui/issues") == dir_path;
+        let limit = if is_root {
+            ROOT_ENTRY_LIMIT
+        } else if is_issues_dir {
+            ISSUES_ENTRY_LIMIT
+        } else {
+            ENTRY_LIMIT
+        };
 
-                if count > limit {
-                    tidy_error!(
-                        bad,
-                        "following path contains more than {} entries, \
-                            you should move the test to some relevant subdirectory (current: {}): {}",
-                        limit,
-                        count,
-                        dir_path.display()
-                    );
-                }
-            }
+        if count > limit {
+            tidy_error!(
+                bad,
+                "following path contains more than {} entries, \
+                    you should move the test to some relevant subdirectory (current: {}): {}",
+                limit,
+                count,
+                dir_path.display()
+            );
         }
     }
 }
 
 pub fn check(path: &Path, bad: &mut bool) {
     check_entries(&path, bad);
-    for path in &[&path.join("ui"), &path.join("ui-fulldeps")] {
-        crate::walk::walk_no_read(path, |_| false, &mut |entry| {
-            let file_path = entry.path();
-            if let Some(ext) = file_path.extension() {
-                if ext == "stderr" || ext == "stdout" {
-                    // Test output filenames have one of the formats:
-                    // ```
-                    // $testname.stderr
-                    // $testname.$mode.stderr
-                    // $testname.$revision.stderr
-                    // $testname.$revision.$mode.stderr
-                    // ```
-                    //
-                    // For now, just make sure that there is a corresponding
-                    // `$testname.rs` file.
-                    //
-                    // NB: We do not use file_stem() as some file names have multiple `.`s and we
-                    // must strip all of them.
-                    let testname =
-                        file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
-                    if !file_path.with_file_name(testname).with_extension("rs").exists() {
-                        tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
-                    }
+    let (ui, ui_fulldeps) = (path.join("ui"), path.join("ui-fulldeps"));
+    let paths = [ui.as_path(), ui_fulldeps.as_path()];
+    crate::walk::walk_no_read(&paths, |_| false, &mut |entry| {
+        let file_path = entry.path();
+        if let Some(ext) = file_path.extension() {
+            if ext == "stderr" || ext == "stdout" {
+                // Test output filenames have one of the formats:
+                // ```
+                // $testname.stderr
+                // $testname.$mode.stderr
+                // $testname.$revision.stderr
+                // $testname.$revision.$mode.stderr
+                // ```
+                //
+                // For now, just make sure that there is a corresponding
+                // `$testname.rs` file.
+                //
+                // NB: We do not use file_stem() as some file names have multiple `.`s and we
+                // must strip all of them.
+                let testname =
+                    file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
+                if !file_path.with_file_name(testname).with_extension("rs").exists() {
+                    tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
+                }
 
-                    if let Ok(metadata) = fs::metadata(file_path) {
-                        if metadata.len() == 0 {
-                            tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
-                        }
+                if let Ok(metadata) = fs::metadata(file_path) {
+                    if metadata.len() == 0 {
+                        tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
                     }
                 }
             }
-        });
-    }
+        }
+    });
 }
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index 94152e75168..2ade22c209f 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -1,6 +1,6 @@
 use ignore::DirEntry;
 
-use std::{fs::File, io::Read, path::Path};
+use std::{ffi::OsStr, fs::File, io::Read, path::Path};
 
 /// The default directory filter.
 pub fn filter_dirs(path: &Path) -> bool {
@@ -33,23 +33,26 @@ pub fn filter_dirs(path: &Path) -> bool {
     skip.iter().any(|p| path.ends_with(p))
 }
 
-pub fn walk_many(
-    paths: &[&Path],
+/// Filter for only files that end in `.rs`.
+pub fn filter_not_rust(path: &Path) -> bool {
+    path.extension() != Some(OsStr::new("rs")) && !path.is_dir()
+}
+
+pub fn walk(
+    path: &Path,
     skip: impl Clone + Send + Sync + 'static + Fn(&Path) -> bool,
     f: &mut dyn FnMut(&DirEntry, &str),
 ) {
-    for path in paths {
-        walk(path, skip.clone(), f);
-    }
+    walk_many(&[path], skip, f);
 }
 
-pub fn walk(
-    path: &Path,
-    skip: impl Send + Sync + 'static + Fn(&Path) -> bool,
+pub fn walk_many(
+    paths: &[&Path],
+    skip: impl Clone + Send + Sync + 'static + Fn(&Path) -> bool,
     f: &mut dyn FnMut(&DirEntry, &str),
 ) {
     let mut contents = Vec::new();
-    walk_no_read(path, skip, &mut |entry| {
+    walk_no_read(paths, skip, &mut |entry| {
         contents.clear();
         let mut file = t!(File::open(entry.path()), entry.path());
         t!(file.read_to_end(&mut contents), entry.path());
@@ -62,11 +65,14 @@ pub fn walk(
 }
 
 pub(crate) fn walk_no_read(
-    path: &Path,
+    paths: &[&Path],
     skip: impl Send + Sync + 'static + Fn(&Path) -> bool,
     f: &mut dyn FnMut(&DirEntry),
 ) {
-    let mut walker = ignore::WalkBuilder::new(path);
+    let mut walker = ignore::WalkBuilder::new(paths[0]);
+    for path in &paths[1..] {
+        walker.add(path);
+    }
     let walker = walker.filter_entry(move |e| !skip(e.path()));
     for entry in walker.build() {
         if let Ok(entry) = entry {
diff --git a/tests/codegen/inherit_overflow.rs b/tests/codegen/inherit_overflow.rs
index 0b0b890b2c9..39909d7abfd 100644
--- a/tests/codegen/inherit_overflow.rs
+++ b/tests/codegen/inherit_overflow.rs
@@ -4,7 +4,7 @@
 //[NOASSERT] compile-flags: -Coverflow-checks=off
 
 // CHECK-LABEL: define{{.*}} @assertion
-// ASSERT: call void @_ZN4core9panicking5panic17h
+// ASSERT: call void @{{.*4core9panicking5panic}}
 // NOASSERT: ret i8 0
 #[no_mangle]
 pub fn assertion() -> u8 {
diff --git a/tests/incremental/auxiliary/circular-dependencies-aux.rs b/tests/incremental/auxiliary/circular-dependencies-aux.rs
new file mode 100644
index 00000000000..0e74eb1b2f2
--- /dev/null
+++ b/tests/incremental/auxiliary/circular-dependencies-aux.rs
@@ -0,0 +1,10 @@
+// edition: 2021
+// compile-flags: --crate-type lib --extern circular_dependencies={{build-base}}/circular-dependencies/libcircular_dependencies.rmeta --emit dep-info,metadata
+
+use circular_dependencies::Foo;
+
+pub fn consume_foo(_: Foo) {}
+
+pub fn produce_foo() -> Foo {
+    Foo
+}
diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs
new file mode 100644
index 00000000000..10673066a9d
--- /dev/null
+++ b/tests/incremental/circular-dependencies.rs
@@ -0,0 +1,37 @@
+// ignore-tidy-linelength
+// revisions: cpass1 cfail2
+// edition: 2021
+// [cpass1] compile-flags: --crate-type lib --emit dep-info,metadata
+// [cfail2] aux-build: circular-dependencies-aux.rs
+// [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies
+
+pub struct Foo;
+//[cfail2]~^ NOTE `Foo` is defined in the current crate
+//[cfail2]~| NOTE `Foo` is defined in the current crate
+//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
+//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
+
+pub fn consume_foo(_: Foo) {}
+//[cfail2]~^ NOTE function defined here
+
+pub fn produce_foo() -> Foo {
+    Foo
+}
+
+#[test]
+fn test() {
+    aux::consume_foo(produce_foo());
+    //[cfail2]~^ ERROR mismatched types [E0308]
+    //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo`
+    //[cfail2]~| NOTE arguments to this function are incorrect
+    //[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types
+    //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
+    //[cfail2]~| NOTE function defined here
+
+    consume_foo(aux::produce_foo());
+    //[cfail2]~^ ERROR mismatched types [E0308]
+    //[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo`
+    //[cfail2]~| NOTE arguments to this function are incorrect
+    //[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types
+    //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
+}
diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
index 391b00effac..3884d29db41 100644
--- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
@@ -4,21 +4,13 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
     let mut _0: ();                      // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     let mut _2: usize;                   // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     let mut _3: usize;                   // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _4: usize;                   // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _5: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _7: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _8: bool;                    // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _9: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _10: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _11: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _12: bool;                   // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _13: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _14: bool;                   // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _15: *mut [std::string::String]; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+    let mut _4: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+    let mut _5: bool;                    // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+    let mut _6: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+    let mut _7: bool;                    // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
 
     bb0: {
-        goto -> bb15;                    // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        goto -> bb8;                     // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb1: {
@@ -30,72 +22,34 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
     }
 
     bb3 (cleanup): {
-        _5 = &raw mut (*_1)[_4];         // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        drop((*_5)) -> bb4;              // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _4 = &raw mut (*_1)[_3];         // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        drop((*_4)) -> bb4;              // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb4 (cleanup): {
-        _6 = Eq(_4, _3);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _6) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _5 = Eq(_3, _2);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _5) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb5: {
-        _7 = &raw mut (*_1)[_4];         // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        drop((*_7)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _6 = &raw mut (*_1)[_3];         // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        drop((*_6)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb6: {
-        _8 = Eq(_4, _3);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _8) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _7 = Eq(_3, _2);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _7) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb7: {
-        _4 = const 0_usize;              // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _2 = Len((*_1));                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _3 = const 0_usize;              // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         goto -> bb6;                     // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb8: {
         goto -> bb7;                     // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
-
-    bb9 (cleanup): {
-        _11 = _9;                        // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        drop((*_11)) -> bb10;            // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
-
-    bb10 (cleanup): {
-        _12 = Eq(_9, _10);               // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _12) -> [0: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
-
-    bb11: {
-        _13 = _9;                        // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        drop((*_13)) -> [return: bb12, unwind: bb10]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
-
-    bb12: {
-        _14 = Eq(_9, _10);               // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _14) -> [0: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
-
-    bb13: {
-        _15 = &raw mut (*_1);            // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _9 = move _15 as *mut std::string::String (PtrToPtr); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _10 = Offset(_9, move _3);       // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        goto -> bb12;                    // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
-
-    bb14: {
-        goto -> bb13;                    // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
-
-    bb15: {
-        _2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _3 = Len((*_1));                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _2) -> [0: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    }
 }
diff --git a/tests/ui/async-await/async-trait-fn.current.stderr b/tests/ui/async-await/async-trait-fn.current.stderr
new file mode 100644
index 00000000000..7ccf2f2301d
--- /dev/null
+++ b/tests/ui/async-await/async-trait-fn.current.stderr
@@ -0,0 +1,42 @@
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/async-trait-fn.rs:6:5
+   |
+LL |     async fn foo() {}
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/async-trait-fn.rs:7:5
+   |
+LL |     async fn bar(&self) {}
+   |     -----^^^^^^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/async-trait-fn.rs:8:5
+   |
+LL |     async fn baz() {
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0706`.
diff --git a/tests/ui/async-await/async-trait-fn.next.stderr b/tests/ui/async-await/async-trait-fn.next.stderr
new file mode 100644
index 00000000000..7ccf2f2301d
--- /dev/null
+++ b/tests/ui/async-await/async-trait-fn.next.stderr
@@ -0,0 +1,42 @@
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/async-trait-fn.rs:6:5
+   |
+LL |     async fn foo() {}
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/async-trait-fn.rs:7:5
+   |
+LL |     async fn bar(&self) {}
+   |     -----^^^^^^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/async-trait-fn.rs:8:5
+   |
+LL |     async fn baz() {
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0706`.
diff --git a/tests/ui/async-await/async-trait-fn.rs b/tests/ui/async-await/async-trait-fn.rs
index e2062e82725..04123badb53 100644
--- a/tests/ui/async-await/async-trait-fn.rs
+++ b/tests/ui/async-await/async-trait-fn.rs
@@ -1,4 +1,5 @@
 // edition:2018
+
 trait T {
     async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
     async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async`
diff --git a/tests/ui/async-await/async-trait-fn.stderr b/tests/ui/async-await/async-trait-fn.stderr
index afbe25cf7ab..68ebe3507ac 100644
--- a/tests/ui/async-await/async-trait-fn.stderr
+++ b/tests/ui/async-await/async-trait-fn.stderr
@@ -1,5 +1,5 @@
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:3:5
+  --> $DIR/async-trait-fn.rs:4:5
    |
 LL |     async fn foo() {}
    |     -----^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     async fn foo() {}
    = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:4:5
+  --> $DIR/async-trait-fn.rs:5:5
    |
 LL |     async fn bar(&self) {}
    |     -----^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     async fn bar(&self) {}
    = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:5:5
+  --> $DIR/async-trait-fn.rs:6:5
    |
 LL |     async fn baz() {
    |     -----^^^^^^^^^
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.current.stderr
index ba918eb28de..c47b99e657e 100644
--- a/tests/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.current.stderr
@@ -1,5 +1,5 @@
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:3:1
+  --> $DIR/edition-deny-async-fns-2015.rs:5:1
    |
 LL | async fn foo() {}
    | ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -8,7 +8,7 @@ LL | async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:5:12
+  --> $DIR/edition-deny-async-fns-2015.rs:7:12
    |
 LL | fn baz() { async fn foo() {} }
    |            ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -17,7 +17,7 @@ LL | fn baz() { async fn foo() {} }
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:7:1
+  --> $DIR/edition-deny-async-fns-2015.rs:9:1
    |
 LL | async fn async_baz() {
    | ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -26,7 +26,7 @@ LL | async fn async_baz() {
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:8:5
+  --> $DIR/edition-deny-async-fns-2015.rs:10:5
    |
 LL |     async fn bar() {}
    |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -35,7 +35,7 @@ LL |     async fn bar() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:14:5
+  --> $DIR/edition-deny-async-fns-2015.rs:16:5
    |
 LL |     async fn foo() {}
    |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -44,7 +44,7 @@ LL |     async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:18:5
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
    |
 LL |     async fn foo() {}
    |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -53,7 +53,7 @@ LL |     async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:36:9
+  --> $DIR/edition-deny-async-fns-2015.rs:38:9
    |
 LL |         async fn bar() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -62,7 +62,7 @@ LL |         async fn bar() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:26:9
+  --> $DIR/edition-deny-async-fns-2015.rs:28:9
    |
 LL |         async fn foo() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -71,7 +71,7 @@ LL |         async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:31:13
+  --> $DIR/edition-deny-async-fns-2015.rs:33:13
    |
 LL |             async fn bar() {}
    |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -80,7 +80,7 @@ LL |             async fn bar() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/edition-deny-async-fns-2015.rs:18:5
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
    |
 LL |     async fn foo() {}
    |     -----^^^^^^^^^
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.next.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.next.stderr
new file mode 100644
index 00000000000..c47b99e657e
--- /dev/null
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.next.stderr
@@ -0,0 +1,98 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:5:1
+   |
+LL | async fn foo() {}
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:7:12
+   |
+LL | fn baz() { async fn foo() {} }
+   |            ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:9:1
+   |
+LL | async fn async_baz() {
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:10:5
+   |
+LL |     async fn bar() {}
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:16:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:38:9
+   |
+LL |         async fn bar() {}
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:28:9
+   |
+LL |         async fn foo() {}
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:33:13
+   |
+LL |             async fn bar() {}
+   |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {}
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.rs b/tests/ui/async-await/edition-deny-async-fns-2015.rs
index 6bd6d879a4a..d4c30dc9d82 100644
--- a/tests/ui/async-await/edition-deny-async-fns-2015.rs
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.rs
@@ -1,4 +1,6 @@
 // edition:2015
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
 
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr
index 61a826258d0..2142ee232ca 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/async-default-fn-overridden.rs:4:12
+  --> $DIR/async-default-fn-overridden.rs:6:12
    |
 LL | #![feature(async_fn_in_trait)]
    |            ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr
new file mode 100644
index 00000000000..2142ee232ca
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/async-default-fn-overridden.rs:6:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
index 0fd1a2703db..dd1af93d706 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -1,5 +1,7 @@
 // run-pass
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 //~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.current.stderr
index f1f0d7e5907..780da068962 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.current.stderr
@@ -1,33 +1,33 @@
 error[E0311]: the parameter type `U` may not live long enough
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
    |
 note: the parameter type `U` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics-and-bounds.rs:12:18
+  --> $DIR/async-generics-and-bounds.rs:14:18
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
 
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics-and-bounds.rs:12:18
+  --> $DIR/async-generics-and-bounds.rs:14:18
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr
new file mode 100644
index 00000000000..780da068962
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:14:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:14:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
index a73d55adfec..146e74ec2d0 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
@@ -1,6 +1,8 @@
 // check-fail
 // known-bug: #102682
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.current.stderr
index 2f05564564c..04e1ab6d769 100644
--- a/tests/ui/async-await/in-trait/async-generics.stderr
+++ b/tests/ui/async-await/in-trait/async-generics.current.stderr
@@ -1,33 +1,33 @@
 error[E0311]: the parameter type `U` may not live long enough
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
    |
 note: the parameter type `U` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics.rs:9:18
+  --> $DIR/async-generics.rs:11:18
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
 
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics.rs:9:18
+  --> $DIR/async-generics.rs:11:18
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-generics.next.stderr b/tests/ui/async-await/in-trait/async-generics.next.stderr
new file mode 100644
index 00000000000..04e1ab6d769
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.next.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:11:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:11:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs
index 67000e5770e..507500abf4e 100644
--- a/tests/ui/async-await/in-trait/async-generics.rs
+++ b/tests/ui/async-await/in-trait/async-generics.rs
@@ -1,6 +1,8 @@
 // check-fail
 // known-bug: #102682
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/generics-mismatch.current.stderr b/tests/ui/async-await/in-trait/generics-mismatch.current.stderr
new file mode 100644
index 00000000000..be23384e049
--- /dev/null
+++ b/tests/ui/async-await/in-trait/generics-mismatch.current.stderr
@@ -0,0 +1,16 @@
+error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo`
+  --> $DIR/generics-mismatch.rs:13:18
+   |
+LL | trait Foo {
+   |       ---
+LL |     async fn foo<T>();
+   |                  - expected type parameter
+...
+LL | impl Foo for () {
+   | ---------------
+LL |     async fn foo<const N: usize>() {}
+   |                  ^^^^^^^^^^^^^^ found const parameter of type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/generics-mismatch.next.stderr b/tests/ui/async-await/in-trait/generics-mismatch.next.stderr
new file mode 100644
index 00000000000..be23384e049
--- /dev/null
+++ b/tests/ui/async-await/in-trait/generics-mismatch.next.stderr
@@ -0,0 +1,16 @@
+error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo`
+  --> $DIR/generics-mismatch.rs:13:18
+   |
+LL | trait Foo {
+   |       ---
+LL |     async fn foo<T>();
+   |                  - expected type parameter
+...
+LL | impl Foo for () {
+   | ---------------
+LL |     async fn foo<const N: usize>() {}
+   |                  ^^^^^^^^^^^^^^ found const parameter of type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs
new file mode 100644
index 00000000000..fc29783c0e3
--- /dev/null
+++ b/tests/ui/async-await/in-trait/generics-mismatch.rs
@@ -0,0 +1,15 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    async fn foo<T>();
+}
+
+impl Foo for () {
+    async fn foo<const N: usize>() {}
+    //~^ ERROR: method `foo` has an incompatible generic parameter for trait `Foo` [E0053]
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr
new file mode 100644
index 00000000000..3518aa05cec
--- /dev/null
+++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr
@@ -0,0 +1,16 @@
+error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo`
+  --> $DIR/generics-mismatch.rs:11:18
+   |
+LL | trait Foo {
+   |       ---
+LL |     async fn foo<T>();
+   |                  - expected type parameter
+...
+LL | impl Foo for () {
+   | ---------------
+LL |     async fn foo<const N: usize>() {}
+   |                  ^^^^^^^^^^^^^^ found const parameter of type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr
index b8d83d0f28a..a5efc757156 100644
--- a/tests/ui/async-await/in-trait/return-type-suggestion.stderr
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/return-type-suggestion.rs:3:12
+  --> $DIR/return-type-suggestion.rs:5:12
    |
 LL | #![feature(async_fn_in_trait)]
    |            ^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | #![feature(async_fn_in_trait)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0308]: mismatched types
-  --> $DIR/return-type-suggestion.rs:8:9
+  --> $DIR/return-type-suggestion.rs:10:9
    |
 LL |         Ok(())
    |         ^^^^^^- help: consider using a semicolon here: `;`
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr
new file mode 100644
index 00000000000..a5efc757156
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr
@@ -0,0 +1,23 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/return-type-suggestion.rs:5:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/return-type-suggestion.rs:10:9
+   |
+LL |         Ok(())
+   |         ^^^^^^- help: consider using a semicolon here: `;`
+   |         |
+   |         expected `()`, found `Result<(), _>`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<(), _>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs
index 3446761d119..3de66306d9a 100644
--- a/tests/ui/async-await/in-trait/return-type-suggestion.rs
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs
@@ -1,4 +1,6 @@
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 //~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
diff --git a/tests/ui/const-generics/const-arg-in-const-arg.full.stderr b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr
index 8672e79b3e8..463a37d7e3d 100644
--- a/tests/ui/const-generics/const-arg-in-const-arg.full.stderr
+++ b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr
@@ -1,4 +1,4 @@
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:18:23
    |
 LL |     let _: [u8; faz::<'a>(&())];
@@ -10,7 +10,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:21:23
    |
 LL |     let _: [u8; faz::<'b>(&())];
@@ -22,7 +22,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:41:24
    |
 LL |     let _: Foo<{ faz::<'a>(&()) }>;
@@ -34,7 +34,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:44:24
    |
 LL |     let _: Foo<{ faz::<'b>(&()) }>;
@@ -94,7 +94,7 @@ LL |     let _ = [0; bar::<N>()];
    |
    = help: try adding a `where` bound using this expression: `where [(); bar::<N>()]:`
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:30:23
    |
 LL |     let _ = [0; faz::<'a>(&())];
@@ -106,7 +106,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:33:23
    |
 LL |     let _ = [0; faz::<'b>(&())];
@@ -134,7 +134,7 @@ LL |     let _ = Foo::<{ bar::<N>() }>;
    |
    = help: try adding a `where` bound using this expression: `where [(); { bar::<N>() }]:`
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:52:27
    |
 LL |     let _ = Foo::<{ faz::<'a>(&()) }>;
@@ -146,7 +146,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:55:27
    |
 LL |     let _ = Foo::<{ faz::<'b>(&()) }>;
@@ -160,3 +160,4 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
 
 error: aborting due to 16 previous errors
 
+For more information about this error, try `rustc --explain E0794`.
diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr
index f1353aa9943..a7bd9c62b0e 100644
--- a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr
+++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr
@@ -216,7 +216,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
 LL |     let _: [u8; bar::<{ N }>()];
    |                       +   +
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:18:23
    |
 LL |     let _: [u8; faz::<'a>(&())];
@@ -228,7 +228,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:21:23
    |
 LL |     let _: [u8; faz::<'b>(&())];
@@ -251,7 +251,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
 LL |     let _: Foo<{ bar::<{ N }>() }>;
    |                        +   +
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:41:24
    |
 LL |     let _: Foo<{ faz::<'a>(&()) }>;
@@ -263,7 +263,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:44:24
    |
 LL |     let _: Foo<{ faz::<'b>(&()) }>;
@@ -294,7 +294,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
 LL |     let _ = [0; bar::<{ N }>()];
    |                       +   +
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:30:23
    |
 LL |     let _ = [0; faz::<'a>(&())];
@@ -306,7 +306,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:33:23
    |
 LL |     let _ = [0; faz::<'b>(&())];
@@ -329,7 +329,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
 LL |     let _ = Foo::<{ bar::<{ N }>() }>;
    |                           +   +
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:52:27
    |
 LL |     let _ = Foo::<{ faz::<'a>(&()) }>;
@@ -341,7 +341,7 @@ note: the late bound lifetime parameter is introduced here
 LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
    |              ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/const-arg-in-const-arg.rs:55:27
    |
 LL |     let _ = Foo::<{ faz::<'b>(&()) }>;
@@ -355,5 +355,5 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
 
 error: aborting due to 36 previous errors
 
-Some errors have detailed explanations: E0658, E0747.
+Some errors have detailed explanations: E0658, E0747, E0794.
 For more information about an error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr
index d681ecf25e8..05c025cc169 100644
--- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/box-coerce-span-in-default.rs:3:12
+  --> $DIR/box-coerce-span-in-default.rs:5:12
    |
 LL | #![feature(return_position_impl_trait_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr
new file mode 100644
index 00000000000..05c025cc169
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/box-coerce-span-in-default.rs:5:12
+   |
+LL | #![feature(return_position_impl_trait_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
index a4d483dee7a..163bb4fcf77 100644
--- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
@@ -1,4 +1,6 @@
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 //~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr
index cc3bdf0e571..85450e3b0a0 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/default-body-type-err-2.rs:8:9
+  --> $DIR/default-body-type-err-2.rs:10:9
    |
 LL |         42
    |         ^^- help: try using a conversion method: `.to_string()`
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr
new file mode 100644
index 00000000000..85450e3b0a0
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/default-body-type-err-2.rs:10:9
+   |
+LL |         42
+   |         ^^- help: try using a conversion method: `.to_string()`
+   |         |
+   |         expected `String`, found integer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
index 45ae2b8ad3a..62323776310 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
@@ -1,4 +1,6 @@
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![allow(incomplete_features)]
 #![feature(async_fn_in_trait)]
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr
index 4742eb37d3e..c949168a377 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
-  --> $DIR/default-body-type-err.rs:7:22
+  --> $DIR/default-body-type-err.rs:10:22
    |
 LL |     fn lol(&self) -> impl Deref<Target = String> {
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr
new file mode 100644
index 00000000000..c949168a377
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
+  --> $DIR/default-body-type-err.rs:10:22
+   |
+LL |     fn lol(&self) -> impl Deref<Target = String> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
+LL |
+LL |         &1i32
+   |         ----- return type was inferred to be `&i32` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs
index ac9baf91cae..9bd5b777989 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![allow(incomplete_features)]
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.current.stderr
index b5fc9d44d36..3c24eff9ae3 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.current.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/default-body-with-rpit.rs:11:9
+  --> $DIR/default-body-with-rpit.rs:13:9
    |
 LL |         ""
    |         ^^ expected `impl Debug`, got `&'static str`
    |
 note: previous use here
-  --> $DIR/default-body-with-rpit.rs:10:39
+  --> $DIR/default-body-with-rpit.rs:12:39
    |
 LL |       async fn baz(&self) -> impl Debug {
    |  _______________________________________^
@@ -14,7 +14,7 @@ LL | |     }
    | |_____^
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/default-body-with-rpit.rs:10:28
+  --> $DIR/default-body-with-rpit.rs:12:28
    |
 LL |     async fn baz(&self) -> impl Debug {
    |                            ^^^^^^^^^^ cannot resolve opaque type
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr
new file mode 100644
index 00000000000..3c24eff9ae3
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.next.stderr
@@ -0,0 +1,24 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/default-body-with-rpit.rs:13:9
+   |
+LL |         ""
+   |         ^^ expected `impl Debug`, got `&'static str`
+   |
+note: previous use here
+  --> $DIR/default-body-with-rpit.rs:12:39
+   |
+LL |       async fn baz(&self) -> impl Debug {
+   |  _______________________________________^
+LL | |         ""
+LL | |     }
+   | |_____^
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/default-body-with-rpit.rs:12:28
+   |
+LL |     async fn baz(&self) -> impl Debug {
+   |                            ^^^^^^^^^^ cannot resolve opaque type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
index 0558d95128f..6bcc7b9ef95 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -1,5 +1,7 @@
 // edition:2021
 // known-bug: #108304
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs
index b0baf5bb10d..ab6a51c6bcb 100644
--- a/tests/ui/impl-trait/in-trait/default-body.rs
+++ b/tests/ui/impl-trait/in-trait/default-body.rs
@@ -1,5 +1,7 @@
 // check-pass
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr
index 5e18605aa4c..7bb79911f56 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-method-constraint.rs:5:12
+  --> $DIR/default-method-constraint.rs:7:12
    |
 LL | #![feature(return_position_impl_trait_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr
new file mode 100644
index 00000000000..7bb79911f56
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-method-constraint.rs:7:12
+   |
+LL | #![feature(return_position_impl_trait_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
index 8c50cc29586..e85fe3c8626 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.rs
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
@@ -1,4 +1,6 @@
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 // This didn't work in the previous default RPITIT method hack attempt
 
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.current.stderr
index aa5492d285e..653016cf009 100644
--- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `()` doesn't implement `std::fmt::Display`
-  --> $DIR/doesnt-satisfy.rs:9:17
+  --> $DIR/doesnt-satisfy.rs:12:17
    |
 LL |     fn bar() -> () {}
    |                 ^^ `()` cannot be formatted with the default formatter
@@ -7,7 +7,7 @@ LL |     fn bar() -> () {}
    = help: the trait `std::fmt::Display` is not implemented for `()`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 note: required by a bound in `Foo::bar::{opaque#0}`
-  --> $DIR/doesnt-satisfy.rs:5:22
+  --> $DIR/doesnt-satisfy.rs:8:22
    |
 LL |     fn bar() -> impl std::fmt::Display;
    |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}`
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr
new file mode 100644
index 00000000000..bbfa089ceef
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/doesnt-satisfy.rs:12:17
+   |
+LL |     fn bar() -> () {}
+   |                 ^^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `Foo::{opaque#0}`
+  --> $DIR/doesnt-satisfy.rs:8:22
+   |
+LL |     fn bar() -> impl std::fmt::Display;
+   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs
index bb4e0d44f3e..fcd0b51eea4 100644
--- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.current.stderr
index cd42683e022..310edbcb6cd 100644
--- a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr
+++ b/tests/ui/impl-trait/in-trait/generics-mismatch.current.stderr
@@ -1,5 +1,5 @@
 error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/generics-mismatch.rs:11:12
+  --> $DIR/generics-mismatch.rs:14:12
    |
 LL |     fn bar(&self) -> impl Sized;
    |           - expected 0 type parameters
diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr
new file mode 100644
index 00000000000..310edbcb6cd
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/generics-mismatch.next.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/generics-mismatch.rs:14:12
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |           - expected 0 type parameters
+...
+LL |     fn bar<T>(&self) {}
+   |            ^ found 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.rs b/tests/ui/impl-trait/in-trait/generics-mismatch.rs
index cc0fc720ebb..9259ca193d1 100644
--- a/tests/ui/impl-trait/in-trait/generics-mismatch.rs
+++ b/tests/ui/impl-trait/in-trait/generics-mismatch.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.current.stderr
index 87219941d91..cac9a29f644 100644
--- a/tests/ui/impl-trait/in-trait/issue-102571.stderr
+++ b/tests/ui/impl-trait/in-trait/issue-102571.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-102571.rs:20:9
+  --> $DIR/issue-102571.rs:23:9
    |
 LL |     let () = t.bar();
    |         ^^   ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.next.stderr b/tests/ui/impl-trait/in-trait/issue-102571.next.stderr
new file mode 100644
index 00000000000..cac9a29f644
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/issue-102571.next.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-102571.rs:23:9
+   |
+LL |     let () = t.bar();
+   |         ^^   ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+   |         |
+   |         expected associated type, found `()`
+   |
+   = note: expected associated type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+                    found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.rs b/tests/ui/impl-trait/in-trait/issue-102571.rs
index 61c91e64417..f0ddab5e7f2 100644
--- a/tests/ui/impl-trait/in-trait/issue-102571.rs
+++ b/tests/ui/impl-trait/in-trait/issue-102571.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.current.stderr
index dc621d6b8a8..f48e7a1ed14 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.current.stderr
@@ -1,5 +1,5 @@
 error[E0053]: method `bar` has an incompatible type for trait
-  --> $DIR/specialization-broken.rs:16:22
+  --> $DIR/specialization-broken.rs:19:22
    |
 LL | default impl<U> Foo for U
    |              - this type parameter
@@ -11,7 +11,7 @@ LL |     fn bar(&self) -> U {
    |                      help: change the output type to match the trait: `impl Sized`
    |
 note: type in trait
-  --> $DIR/specialization-broken.rs:9:22
+  --> $DIR/specialization-broken.rs:12:22
    |
 LL |     fn bar(&self) -> impl Sized;
    |                      ^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     fn bar(&self) -> impl Sized;
               found signature `fn(&U) -> U`
 
 error: method with return-position `impl Trait` in trait cannot be specialized
-  --> $DIR/specialization-broken.rs:16:5
+  --> $DIR/specialization-broken.rs:19:5
    |
 LL |     fn bar(&self) -> U {
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.next.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.next.stderr
new file mode 100644
index 00000000000..f48e7a1ed14
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.next.stderr
@@ -0,0 +1,31 @@
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/specialization-broken.rs:19:22
+   |
+LL | default impl<U> Foo for U
+   |              - this type parameter
+...
+LL |     fn bar(&self) -> U {
+   |                      ^
+   |                      |
+   |                      expected associated type, found type parameter `U`
+   |                      help: change the output type to match the trait: `impl Sized`
+   |
+note: type in trait
+  --> $DIR/specialization-broken.rs:12:22
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |                      ^^^^^^^^^^
+   = note: expected signature `fn(&U) -> impl Sized`
+              found signature `fn(&U) -> U`
+
+error: method with return-position `impl Trait` in trait cannot be specialized
+  --> $DIR/specialization-broken.rs:19:5
+   |
+LL |     fn bar(&self) -> U {
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: specialization behaves in inconsistent and surprising ways with `#![feature(return_position_impl_trait_in_trait)]`, and for now is disallowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs
index 2fcffdf3f9a..658d0709717 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.rs
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 // FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not.
 // But we fixed an ICE anyways.
 
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
index 03cc4c2b93b..8392f26e7c8 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:9:22
+  --> $DIR/wf-bounds.rs:11:22
    |
 LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,14 +9,14 @@ note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:12:23
+  --> $DIR/wf-bounds.rs:14:23
    |
 LL |     fn nya2() -> impl Wf<[u8]>;
    |                       ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Wf`
-  --> $DIR/wf-bounds.rs:6:10
+  --> $DIR/wf-bounds.rs:8:10
    |
 LL | trait Wf<T> {}
    |          ^ required by this bound in `Wf`
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
new file mode 100644
index 00000000000..8392f26e7c8
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
@@ -0,0 +1,30 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:11:22
+   |
+LL |     fn nya() -> impl Wf<Vec<[u8]>>;
+   |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Vec`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:14:23
+   |
+LL |     fn nya2() -> impl Wf<[u8]>;
+   |                       ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Wf`
+  --> $DIR/wf-bounds.rs:8:10
+   |
+LL | trait Wf<T> {}
+   |          ^ required by this bound in `Wf`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Wf<T: ?Sized> {}
+   |           ++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs
index 2c71583b312..39f41275315 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs
@@ -1,4 +1,6 @@
 // issue #101663
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed
index 0e60c73b67a..0f688fa2823 100644
--- a/tests/ui/imports/issue-99695-b.fixed
+++ b/tests/ui/imports/issue-99695-b.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(unused, nonstandard_style)]
+#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
 mod m {
 
     mod p {
diff --git a/tests/ui/imports/issue-99695-b.rs b/tests/ui/imports/issue-99695-b.rs
index 031443a1f5d..b433997e53f 100644
--- a/tests/ui/imports/issue-99695-b.rs
+++ b/tests/ui/imports/issue-99695-b.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(unused, nonstandard_style)]
+#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
 mod m {
 
     mod p {
diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.fixed
index 6bf228b23aa..17ff409324e 100644
--- a/tests/ui/imports/issue-99695.fixed
+++ b/tests/ui/imports/issue-99695.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(unused, nonstandard_style)]
+#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
 mod m {
     #[macro_export]
     macro_rules! nu {
diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs
index f7199f1497a..b8979bcb734 100644
--- a/tests/ui/imports/issue-99695.rs
+++ b/tests/ui/imports/issue-99695.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(unused, nonstandard_style)]
+#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
 mod m {
     #[macro_export]
     macro_rules! nu {
diff --git a/tests/ui/late-bound-lifetimes/issue-80618.rs b/tests/ui/late-bound-lifetimes/issue-80618.rs
new file mode 100644
index 00000000000..6aa8ff461a9
--- /dev/null
+++ b/tests/ui/late-bound-lifetimes/issue-80618.rs
@@ -0,0 +1,8 @@
+fn foo<'a>(x: &'a str) -> &'a str {
+    x
+}
+
+fn main() {
+    let _ = foo::<'static>;
+//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present [E0794]
+}
diff --git a/tests/ui/late-bound-lifetimes/issue-80618.stderr b/tests/ui/late-bound-lifetimes/issue-80618.stderr
new file mode 100644
index 00000000000..cf7423fc16f
--- /dev/null
+++ b/tests/ui/late-bound-lifetimes/issue-80618.stderr
@@ -0,0 +1,15 @@
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/issue-80618.rs:6:19
+   |
+LL |     let _ = foo::<'static>;
+   |                   ^^^^^^^
+   |
+note: the late bound lifetime parameter is introduced here
+  --> $DIR/issue-80618.rs:1:8
+   |
+LL | fn foo<'a>(x: &'a str) -> &'a str {
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0794`.
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs
index 1c122f42e59..0ae68ad04f7 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.rs
+++ b/tests/ui/lifetimes/unusual-rib-combinations.rs
@@ -25,4 +25,9 @@ fn d<const C: S>() {}
 //~^ ERROR missing lifetime specifier
 //~| ERROR `S<'_>` is forbidden as the type of a const generic parameter
 
+trait Foo<'a> {}
+struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
+//~^ ERROR use of non-static lifetime `'a` in const generic
+//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
+
 fn main() {}
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index 68f4fce0178..20163d289b1 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -9,6 +9,14 @@ help: consider introducing a named lifetime parameter
 LL | fn d<'a, const C: S<'a>>() {}
    |      +++           ++++
 
+error[E0771]: use of non-static lifetime `'a` in const generic
+  --> $DIR/unusual-rib-combinations.rs:29:22
+   |
+LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
+   |                      ^^
+   |
+   = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
+
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/unusual-rib-combinations.rs:7:16
    |
@@ -55,7 +63,16 @@ LL | fn d<const C: S>() {}
    = note: the only supported types are integers, `bool` and `char`
    = help: more complex types are supported with `#![feature(adt_const_params)]`
 
-error: aborting due to 7 previous errors
+error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
+  --> $DIR/unusual-rib-combinations.rs:29:21
+   |
+LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0106, E0214, E0308.
+Some errors have detailed explanations: E0106, E0214, E0308, E0771.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/lint/anonymous-reexport.rs b/tests/ui/lint/anonymous-reexport.rs
new file mode 100644
index 00000000000..5d56ae6f969
--- /dev/null
+++ b/tests/ui/lint/anonymous-reexport.rs
@@ -0,0 +1,21 @@
+#![deny(useless_anonymous_reexport)]
+#![crate_type = "rlib"]
+
+mod my_mod {
+    pub trait Foo {}
+    pub type TyFoo = dyn Foo;
+    pub struct Bar;
+    pub type TyBar = Bar;
+}
+
+pub use self::my_mod::Foo as _;
+pub use self::my_mod::TyFoo as _;
+pub use self::my_mod::Bar as _; //~ ERROR
+pub use self::my_mod::TyBar as _; //~ ERROR
+pub use self::my_mod::{Bar as _}; //~ ERROR
+pub use self::my_mod::{Bar as _, Foo as _}; //~ ERROR
+pub use self::my_mod::{Bar as _, TyBar as _};
+//~^ ERROR
+//~| ERROR
+#[allow(unused_imports)]
+use self::my_mod::TyBar as _;
diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr
new file mode 100644
index 00000000000..f4f8b41c417
--- /dev/null
+++ b/tests/ui/lint/anonymous-reexport.stderr
@@ -0,0 +1,55 @@
+error: useless anonymous re-export
+  --> $DIR/anonymous-reexport.rs:13:1
+   |
+LL | pub use self::my_mod::Bar as _;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: only anonymous re-exports of traits are useful, this is a `struct`
+note: the lint level is defined here
+  --> $DIR/anonymous-reexport.rs:1:9
+   |
+LL | #![deny(useless_anonymous_reexport)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: useless anonymous re-export
+  --> $DIR/anonymous-reexport.rs:14:1
+   |
+LL | pub use self::my_mod::TyBar as _;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: only anonymous re-exports of traits are useful, this is a `type alias`
+
+error: useless anonymous re-export
+  --> $DIR/anonymous-reexport.rs:15:24
+   |
+LL | pub use self::my_mod::{Bar as _};
+   |                        ^^^^^^^^
+   |
+   = note: only anonymous re-exports of traits are useful, this is a `struct`
+
+error: useless anonymous re-export
+  --> $DIR/anonymous-reexport.rs:16:24
+   |
+LL | pub use self::my_mod::{Bar as _, Foo as _};
+   |                        ^^^^^^^^
+   |
+   = note: only anonymous re-exports of traits are useful, this is a `struct`
+
+error: useless anonymous re-export
+  --> $DIR/anonymous-reexport.rs:17:24
+   |
+LL | pub use self::my_mod::{Bar as _, TyBar as _};
+   |                        ^^^^^^^^
+   |
+   = note: only anonymous re-exports of traits are useful, this is a `struct`
+
+error: useless anonymous re-export
+  --> $DIR/anonymous-reexport.rs:17:34
+   |
+LL | pub use self::my_mod::{Bar as _, TyBar as _};
+   |                                  ^^^^^^^^^^
+   |
+   = note: only anonymous re-exports of traits are useful, this is a `type alias`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/macros/issue-109237.rs b/tests/ui/macros/issue-109237.rs
new file mode 100644
index 00000000000..86a193c9e44
--- /dev/null
+++ b/tests/ui/macros/issue-109237.rs
@@ -0,0 +1,7 @@
+macro_rules! statement {
+    () => {;}; //~ ERROR expected expression
+}
+
+fn main() {
+    let _ = statement!();
+}
diff --git a/tests/ui/macros/issue-109237.stderr b/tests/ui/macros/issue-109237.stderr
new file mode 100644
index 00000000000..d125cff63ea
--- /dev/null
+++ b/tests/ui/macros/issue-109237.stderr
@@ -0,0 +1,18 @@
+error: expected expression, found `;`
+  --> $DIR/issue-109237.rs:2:12
+   |
+LL |     () => {;};
+   |            ^ expected expression
+...
+LL |     let _ = statement!();
+   |             ------------ in this macro invocation
+   |
+   = note: the macro call doesn't expand to an expression, but it can expand to a statement
+   = note: this error originates in the macro `statement` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: surround the macro invocation with `{}` to interpret the expansion as a statement
+   |
+LL |     let _ = { statement!(); };
+   |             ~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/methods/method-call-lifetime-args-fail.stderr b/tests/ui/methods/method-call-lifetime-args-fail.stderr
index 34526256f99..645d8b8d14a 100644
--- a/tests/ui/methods/method-call-lifetime-args-fail.stderr
+++ b/tests/ui/methods/method-call-lifetime-args-fail.stderr
@@ -30,7 +30,7 @@ note: method defined here, with 2 lifetime parameters: `'a`, `'b`
 LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
    |        ^^^^^ --  --
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:27:15
    |
 LL |     S::late::<'static>(S, &0, &0);
@@ -42,7 +42,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:29:15
    |
 LL |     S::late::<'static, 'static>(S, &0, &0);
@@ -54,7 +54,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:31:15
    |
 LL |     S::late::<'static, 'static, 'static>(S, &0, &0);
@@ -66,7 +66,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:34:21
    |
 LL |     S::late_early::<'static, 'static>(S, &0);
@@ -78,7 +78,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
    |                   ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:36:21
    |
 LL |     S::late_early::<'static, 'static, 'static>(S, &0);
@@ -90,7 +90,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
    |                   ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:40:24
    |
 LL |     S::late_implicit::<'static>(S, &0, &0);
@@ -102,7 +102,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:42:24
    |
 LL |     S::late_implicit::<'static, 'static>(S, &0, &0);
@@ -114,7 +114,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:44:24
    |
 LL |     S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
@@ -126,7 +126,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit(self, _: &u8, _: &u8) {}
    |                               ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:47:30
    |
 LL |     S::late_implicit_early::<'static, 'static>(S, &0);
@@ -138,7 +138,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
    |                                         ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:49:30
    |
 LL |     S::late_implicit_early::<'static, 'static, 'static>(S, &0);
@@ -150,7 +150,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
    |                                         ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:52:35
    |
 LL |     S::late_implicit_self_early::<'static, 'static>(&S);
@@ -162,7 +162,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
    |                                     ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:54:35
    |
 LL |     S::late_implicit_self_early::<'static, 'static, 'static>(&S);
@@ -174,7 +174,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
    |                                     ^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:57:28
    |
 LL |     S::late_unused_early::<'static, 'static>(S);
@@ -186,7 +186,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
    |                          ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args-fail.rs:59:28
    |
 LL |     S::late_unused_early::<'static, 'static, 'static>(S);
@@ -232,4 +232,5 @@ LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
 
 error: aborting due to 18 previous errors
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0107, E0794.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/methods/method-call-lifetime-args.stderr b/tests/ui/methods/method-call-lifetime-args.stderr
index 64ae79e9bb2..b215d583217 100644
--- a/tests/ui/methods/method-call-lifetime-args.stderr
+++ b/tests/ui/methods/method-call-lifetime-args.stderr
@@ -1,4 +1,4 @@
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args.rs:9:15
    |
 LL |     S::late::<'static>(S, &0, &0);
@@ -10,7 +10,7 @@ note: the late bound lifetime parameter is introduced here
 LL |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
    |             ^^
 
-error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
   --> $DIR/method-call-lifetime-args.rs:11:24
    |
 LL |     S::late_implicit::<'static>(S, &0, &0);
@@ -24,3 +24,4 @@ LL |     fn late_implicit(self, _: &u8, _: &u8) {}
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0794`.
diff --git a/tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs b/tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs
new file mode 100644
index 00000000000..8804186ee1a
--- /dev/null
+++ b/tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs
@@ -0,0 +1,13 @@
+#![feature(staged_api)]
+#![stable(feature = "libfoo", since = "1.0.0")]
+
+#[unstable(feature = "foo", reason = "...", issue = "none")]
+pub fn foo() {}
+
+#[stable(feature = "libfoo", since = "1.0.0")]
+pub struct Foo;
+
+impl Foo {
+    #[unstable(feature = "foo", reason = "...", issue = "none")]
+    pub fn foo(&self) {}
+}
diff --git a/tests/ui/stability-attribute/issue-109177.rs b/tests/ui/stability-attribute/issue-109177.rs
new file mode 100644
index 00000000000..6d052779c6d
--- /dev/null
+++ b/tests/ui/stability-attribute/issue-109177.rs
@@ -0,0 +1,13 @@
+// aux-build: similar-unstable-method.rs
+
+extern crate similar_unstable_method;
+
+fn main() {
+    // FIXME: this function should not suggest the `foo` function.
+    similar_unstable_method::foo1();
+    //~^ ERROR cannot find function `foo1` in crate `similar_unstable_method` [E0425]
+
+    let foo = similar_unstable_method::Foo;
+    foo.foo1();
+    //~^ ERROR no method named `foo1` found for struct `Foo` in the current scope [E0599]
+}
diff --git a/tests/ui/stability-attribute/issue-109177.stderr b/tests/ui/stability-attribute/issue-109177.stderr
new file mode 100644
index 00000000000..9c2ac591ace
--- /dev/null
+++ b/tests/ui/stability-attribute/issue-109177.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find function `foo1` in crate `similar_unstable_method`
+  --> $DIR/issue-109177.rs:7:30
+   |
+LL |     similar_unstable_method::foo1();
+   |                              ^^^^ help: a function with a similar name exists: `foo`
+   |
+  ::: $DIR/auxiliary/similar-unstable-method.rs:5:1
+   |
+LL | pub fn foo() {}
+   | ------------ similarly named function `foo` defined here
+
+error[E0599]: no method named `foo1` found for struct `Foo` in the current scope
+  --> $DIR/issue-109177.rs:11:9
+   |
+LL |     foo.foo1();
+   |         ^^^^ method not found in `Foo`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0425, E0599.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/bad-infer-in-trait-impl.rs b/tests/ui/suggestions/bad-infer-in-trait-impl.rs
new file mode 100644
index 00000000000..87db2636fb2
--- /dev/null
+++ b/tests/ui/suggestions/bad-infer-in-trait-impl.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    fn bar();
+}
+
+impl Foo for () {
+    fn bar(s: _) {}
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/bad-infer-in-trait-impl.stderr b/tests/ui/suggestions/bad-infer-in-trait-impl.stderr
new file mode 100644
index 00000000000..418690ff85f
--- /dev/null
+++ b/tests/ui/suggestions/bad-infer-in-trait-impl.stderr
@@ -0,0 +1,14 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/bad-infer-in-trait-impl.rs:6:15
+   |
+LL |     fn bar(s: _) {}
+   |               ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn bar<T>(s: T) {}
+   |           +++    ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs
new file mode 100644
index 00000000000..459b94f943b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs
@@ -0,0 +1,11 @@
+// edition: 2021
+
+// Make sure we don't ICE when suggesting a return type
+// for an async fn that has late-bound vars...
+
+async fn ice(_: &i32) {
+    true
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
new file mode 100644
index 00000000000..bff864b222b
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-ret-on-async-w-late.rs:7:5
+   |
+LL | async fn ice(_: &i32) {
+   |                       - help: try adding a return type: `-> bool`
+LL |     true
+   |     ^^^^ expected `()`, found `bool`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
new file mode 100644
index 00000000000..50f0152e904
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn f()
+where
+    for<B> B::Item: Send,
+    //~^ ERROR ambiguous associated type
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr
new file mode 100644
index 00000000000..be6955c111e
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr
@@ -0,0 +1,18 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/missing-assoc-item.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0223]: ambiguous associated type
+  --> $DIR/missing-assoc-item.rs:6:12
+   |
+LL |     for<B> B::Item: Send,
+   |            ^^^^^^^ help: use the fully-qualified path: `<B as IntoIterator>::Item`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs
index a450dbb82d1..e6f7dc410b6 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_item.rs
@@ -228,5 +228,4 @@ fn evens_squared(n: usize) -> _ {
 
 const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
 //~^ ERROR the trait bound
-//~| ERROR the trait bound
 //~| ERROR the placeholder
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index bc6c9fd0779..9144ab9e3a6 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ {
    |                               not allowed in type signatures
    |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
 
-error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied
-  --> $DIR/typeck_type_placeholder_item.rs:229:22
-   |
-LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-   |                      ^^^^^^ `std::ops::Range<{integer}>` is not an iterator
-   |
-   = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>`
-note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const`
-  --> $DIR/typeck_type_placeholder_item.rs:229:14
-   |
-LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-   |              ^^^^^^^
-
 error[E0277]: the trait bound `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied
   --> $DIR/typeck_type_placeholder_item.rs:229:45
    |
@@ -677,7 +664,7 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace with the correct type: `i32`
 
-error: aborting due to 73 previous errors
+error: aborting due to 72 previous errors
 
 Some errors have detailed explanations: E0121, E0277, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.