about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-11 12:13:04 +0000
committerbors <bors@rust-lang.org>2023-05-11 12:13:04 +0000
commit2a8221dbdfd180a2d56d4b0089f4f3952d8c2bcd (patch)
treeb17d172e9d53a91eab56bd3d5f64db86c0c6f76d
parentf8d8ffa2eba53928662dc57bc3a6c5608beb26f1 (diff)
parentb0b76a5db31c57aace6fd7c6302f02b3dd63fae0 (diff)
downloadrust-2a8221dbdfd180a2d56d4b0089f4f3952d8c2bcd.tar.gz
rust-2a8221dbdfd180a2d56d4b0089f4f3952d8c2bcd.zip
Auto merge of #111454 - RalfJung:miri, r=RalfJung
update Miri

r? `@ghost`
-rw-r--r--Cargo.lock4
-rw-r--r--src/tools/miri/Cargo.lock364
-rw-r--r--src/tools/miri/Cargo.toml2
-rw-r--r--src/tools/miri/README.md2
-rw-r--r--src/tools/miri/bench-cargo-miri/zip-equal/Cargo.lock7
-rw-r--r--src/tools/miri/bench-cargo-miri/zip-equal/Cargo.toml8
-rw-r--r--src/tools/miri/bench-cargo-miri/zip-equal/src/main.rs22
-rw-r--r--src/tools/miri/cargo-miri/Cargo.lock303
-rwxr-xr-xsrc/tools/miri/ci.sh3
-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/stacked_borrows/mod.rs6
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs110
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs33
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs31
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs181
-rw-r--r--src/tools/miri/src/machine.rs18
-rw-r--r--src/tools/miri/src/range_map.rs51
-rw-r--r--src/tools/miri/test-cargo-miri/subcrate/src/lib.rs13
-rw-r--r--src/tools/miri/tests/compiletest.rs102
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-bad-size.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-twice.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/global_system_mixup.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/reallocate-bad-size.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/reallocate-dangling.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/stack_free.rs2
-rw-r--r--src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs2
-rw-r--r--src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr4
-rw-r--r--src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr4
-rw-r--r--src/tools/miri/tests/fail/concurrency/windows_join_detached.rs2
-rw-r--r--src/tools/miri/tests/fail/const-ub-checks.rs1
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_read_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_race.rs1
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/relax_acquire_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/rmw_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/deny_lint.rs8
-rw-r--r--src/tools/miri/tests/fail/deny_lint.stderr17
-rw-r--r--src/tools/miri/tests/fail/erroneous_const.stderr2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-gather.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-scatter.rs2
-rw-r--r--src/tools/miri/tests/fail/layout_cycle.rs2
-rw-r--r--src/tools/miri/tests/fail/memleak.rs2
-rw-r--r--src/tools/miri/tests/fail/memleak_no_backtrace.rs2
-rw-r--r--src/tools/miri/tests/fail/memleak_rc.rs2
-rw-r--r--src/tools/miri/tests/fail/no_main.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr5
-rw-r--r--src/tools/miri/tests/fail/panic/no_std.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort1.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort1.stderr5
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort2.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort2.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort3.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort3.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort4.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort4.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/fs/isolated_file.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs2
-rw-r--r--src/tools/miri/tests/fail/tokio/sleep.rs2
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/strongly-protected.rs2
-rw-r--r--src/tools/miri/tests/fail/tree-borrows/strongly-protected.stderr6
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs2
-rw-r--r--src/tools/miri/tests/panic/panic1.stderr8
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-misc.rs1
-rw-r--r--src/tools/miri/tests/pass/0weak_memory_consistency.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/data_race.rs22
-rw-r--r--src/tools/miri/tests/pass/concurrency/disable_data_race_detector.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/sync.rs12
-rw-r--r--src/tools/miri/tests/pass/concurrency/thread_locals.rs1
-rw-r--r--src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs8
-rw-r--r--src/tools/miri/tests/pass/concurrency/windows_init_once.rs4
-rw-r--r--src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs6
-rw-r--r--src/tools/miri/tests/pass/panic/catch_panic.rs5
-rw-r--r--src/tools/miri/tests/pass/panic/catch_panic.stderr2
-rw-r--r--src/tools/miri/tests/pass/panic/concurrent-panic.rs2
-rw-r--r--src/tools/miri/tests/pass/sysroot.rs9
109 files changed, 1122 insertions, 411 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6539bd393fb..e0c72d6899e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5122,9 +5122,9 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
 
 [[package]]
 name = "ui_test"
-version = "0.6.2"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e10f5f88ce8c331a388deda1e6e2bd533c73ca89cc5f539a3df02ed35c8efba"
+checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
 dependencies = [
  "bstr 1.3.0",
  "cargo-platform",
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 10079ba85b6..e2a7d484c23 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -19,18 +19,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.20"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.70"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "atty"
@@ -38,7 +38,7 @@ version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
  "winapi",
 ]
@@ -72,9 +72,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bstr"
-version = "1.1.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
+checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
 dependencies = [
  "memchr",
  "once_cell",
@@ -84,9 +84,9 @@ dependencies = [
 
 [[package]]
 name = "camino"
-version = "1.1.1"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e"
+checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
 dependencies = [
  "serde",
 ]
@@ -102,9 +102,9 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.15.2"
+version = "0.15.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a"
+checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
 dependencies = [
  "camino",
  "cargo-platform",
@@ -116,9 +116,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.78"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 
 [[package]]
 name = "cfg-if"
@@ -166,9 +166,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.6"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
 dependencies = [
  "cfg-if",
  "crossbeam-utils",
@@ -176,9 +176,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.14"
+version = "0.8.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
 dependencies = [
  "cfg-if",
 ]
@@ -203,6 +203,27 @@ dependencies = [
 ]
 
 [[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
 name = "eyre"
 version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -214,18 +235,18 @@ dependencies = [
 
 [[package]]
 name = "fastrand"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
 dependencies = [
  "instant",
 ]
 
 [[package]]
 name = "getrandom"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
 dependencies = [
  "cfg-if",
  "libc",
@@ -234,9 +255,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.27.0"
+version = "0.27.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
+checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
 
 [[package]]
 name = "hermit-abi"
@@ -248,6 +269,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "humantime"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -269,10 +296,21 @@ dependencies = [
 ]
 
 [[package]]
+name = "io-lifetimes"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "itoa"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "lazy_static"
@@ -282,9 +320,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.139"
+version = "0.2.142"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
 
 [[package]]
 name = "libffi"
@@ -316,6 +354,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "linux-raw-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
+
+[[package]]
 name = "lock_api"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -336,9 +380,9 @@ dependencies = [
 
 [[package]]
 name = "measureme"
-version = "10.1.0"
+version = "10.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbdc226fa10994e8f66a4d2f6f000148bc563a1c671b6dcd2135737018033d8a"
+checksum = "1930d162935fecd56fc4e0f6729eb3483bac1264542eb4ea31570b86a434b6bc"
 dependencies = [
  "log",
  "memmap2",
@@ -395,18 +439,18 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.30.0"
+version = "0.30.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
+checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.16.0"
+version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "owo-colors"
@@ -434,16 +478,16 @@ dependencies = [
  "cfg-if",
  "instant",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.2.16",
  "smallvec",
  "winapi",
 ]
 
 [[package]]
 name = "perf-event-open-sys"
-version = "1.0.1"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce9bedf5da2c234fdf2391ede2b90fabf585355f33100689bc364a3ea558561a"
+checksum = "b29be2ba35c12c6939f6bc73187f728bba82c3c062ecdc5fa90ea739282a1f58"
 dependencies = [
  "libc",
 ]
@@ -462,18 +506,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.49"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -518,10 +562,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
 name = "regex"
-version = "1.7.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
+checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -536,24 +589,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.28"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.21"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
 [[package]]
 name = "rustc-hash"
@@ -589,10 +633,24 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustix"
+version = "0.37.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "ryu"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "scopeguard"
@@ -602,27 +660,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
 name = "semver"
-version = "1.0.16"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.152"
+version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -631,9 +689,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
  "itoa",
  "ryu",
@@ -657,9 +715,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
 name = "syn"
-version = "1.0.107"
+version = "2.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -668,41 +726,40 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.3.0"
+version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
 dependencies = [
  "cfg-if",
  "fastrand",
- "libc",
- "redox_syscall",
- "remove_dir_all",
- "winapi",
+ "redox_syscall 0.3.5",
+ "rustix",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
 name = "termcolor"
-version = "1.1.3"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
 dependencies = [
  "winapi-util",
 ]
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -711,10 +768,11 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "1.1.4"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
+checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
 dependencies = [
+ "cfg-if",
  "once_cell",
 ]
 
@@ -751,9 +809,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.3.16"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
 dependencies = [
  "sharded-slab",
  "thread_local",
@@ -762,9 +820,9 @@ dependencies = [
 
 [[package]]
 name = "ui_test"
-version = "0.6.2"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e10f5f88ce8c331a388deda1e6e2bd533c73ca89cc5f539a3df02ed35c8efba"
+checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
 dependencies = [
  "bstr",
  "cargo-platform",
@@ -784,9 +842,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.6"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
 [[package]]
 name = "valuable"
@@ -830,3 +888,135 @@ name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index b962d0c1096..f6f81836804 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -39,7 +39,7 @@ libloading = "0.7"
 
 [dev-dependencies]
 colored = "2"
-ui_test = "0.6.2"
+ui_test = "0.9"
 rustc_version = "0.4"
 # Features chosen to match those required by env_logger, to avoid rebuilds
 regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 640a953dac9..79b0daf9e82 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -389,7 +389,7 @@ to Miri failing to detect cases of undefined behavior in a program.
   Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365).
 * `-Zmiri-measureme=<name>` enables `measureme` profiling for the interpreted program.
    This can be used to find which parts of your program are executing slowly under Miri.
-   The profile is written out to a file with the prefix `<name>`, and can be processed
+   The profile is written out to a file inside a directory called `<name>`, and can be processed
    using the tools in the repository https://github.com/rust-lang/measureme.
 * `-Zmiri-mute-stdout-stderr` silently ignores all writes to stdout and stderr,
   but reports to the program that it did actually write. This is useful when you
diff --git a/src/tools/miri/bench-cargo-miri/zip-equal/Cargo.lock b/src/tools/miri/bench-cargo-miri/zip-equal/Cargo.lock
new file mode 100644
index 00000000000..de6760a0359
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/zip-equal/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "zip-equal"
+version = "0.1.0"
diff --git a/src/tools/miri/bench-cargo-miri/zip-equal/Cargo.toml b/src/tools/miri/bench-cargo-miri/zip-equal/Cargo.toml
new file mode 100644
index 00000000000..f4208de727d
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/zip-equal/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "zip-equal"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/miri/bench-cargo-miri/zip-equal/src/main.rs b/src/tools/miri/bench-cargo-miri/zip-equal/src/main.rs
new file mode 100644
index 00000000000..ba4e9b41d1d
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/zip-equal/src/main.rs
@@ -0,0 +1,22 @@
+//! This is a pathological pattern in which opportunities to merge
+//! adjacent identical items in the RangeMap are not properly detected
+//! because `RangeMap::iter_mut` is never called on overlapping ranges
+//! and thus never merges previously split ranges. This does not produce any
+//! additional cost for access operations, but it makes the job of the Tree Borrows
+//! GC procedure much more costly.
+//! See https://github.com/rust-lang/miri/issues/2863
+
+const LENGTH: usize = (1 << 14) - 1;
+const LONG: &[u8] = &[b'x'; LENGTH];
+
+fn main() {
+    assert!(eq(LONG, LONG))
+}
+
+fn eq(s1: &[u8], s2: &[u8]) -> bool {
+    if s1.len() != s2.len() {
+        return false;
+    }
+
+    s1.iter().zip(s2).all(|(c1, c2)| *c1 == *c2)
+}
diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock
index 76badcf94af..727e46a028d 100644
--- a/src/tools/miri/cargo-miri/Cargo.lock
+++ b/src/tools/miri/cargo-miri/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "anyhow"
-version = "1.0.68"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "bitflags"
@@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "camino"
-version = "1.1.1"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e"
+checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
 dependencies = [
  "serde",
 ]
@@ -48,9 +48,9 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.15.2"
+version = "0.15.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a"
+checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
 dependencies = [
  "camino",
  "cargo-platform",
@@ -61,6 +61,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -87,19 +93,40 @@ dependencies = [
 ]
 
 [[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
 name = "fastrand"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
 dependencies = [
  "instant",
 ]
 
 [[package]]
 name = "getrandom"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
 dependencies = [
  "cfg-if",
  "libc",
@@ -107,6 +134,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "instant"
 version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -116,31 +149,48 @@ dependencies = [
 ]
 
 [[package]]
+name = "io-lifetimes"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "itoa"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "libc"
-version = "0.2.139"
+version = "0.2.142"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.49"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -155,30 +205,30 @@ dependencies = [
 ]
 
 [[package]]
-name = "redox_users"
-version = "0.4.3"
+name = "redox_syscall"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 dependencies = [
- "getrandom",
- "redox_syscall",
- "thiserror",
+ "bitflags",
 ]
 
 [[package]]
-name = "remove_dir_all"
-version = "0.5.3"
+name = "redox_users"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
- "winapi",
+ "getrandom",
+ "redox_syscall 0.2.16",
+ "thiserror",
 ]
 
 [[package]]
 name = "rustc-build-sysroot"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d65b1271cdac365b71b59570ea35d945dea2dd2cc47eba3d33b4bd1e0190ac6d"
+checksum = "8ed2a90dfa5232ed5ff21d53d4df655f315ab316ea06fc508f1c74bcedb1ce6c"
 dependencies = [
  "anyhow",
  "rustc_version",
@@ -207,34 +257,48 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustix"
+version = "0.37.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "ryu"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "semver"
-version = "1.0.16"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.152"
+version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -243,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
  "itoa",
  "ryu",
@@ -254,9 +318,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.107"
+version = "2.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -265,32 +329,31 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.3.0"
+version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
 dependencies = [
  "cfg-if",
  "fastrand",
- "libc",
- "redox_syscall",
- "remove_dir_all",
- "winapi",
+ "redox_syscall 0.3.5",
+ "rustix",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -299,9 +362,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.6"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
 [[package]]
 name = "wasi"
@@ -330,3 +393,135 @@ name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh
index b5b3b211b05..76cc2e94927 100755
--- a/src/tools/miri/ci.sh
+++ b/src/tools/miri/ci.sh
@@ -45,7 +45,8 @@ function run_tests {
     # them. Also error locations change so we don't run the failing tests.
     # We explicitly enable debug-assertions here, they are disabled by -O but we have tests
     # which exist to check that we panic on debug assertion failures.
-    MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
+    #FIXME: Disabled due to <https://github.com/rust-lang/rust/issues/111422>.
+    #MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
 
     # Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
     for FILE in tests/many-seeds/*.rs; do
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index d4bffe5f945..25304fc19f7 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-eb62877597000ccf8bb99ab131b5977344afdfa3
+65dfca8488d635552eb246eb8e15df646e987cff
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 65bc004fc4a..28f9912e283 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -63,7 +63,9 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
         queries: &'tcx rustc_interface::Queries<'tcx>,
     ) -> Compilation {
         queries.global_ctxt().unwrap().enter(|tcx| {
-            tcx.sess.abort_if_errors();
+            if tcx.sess.compile_status().is_err() {
+                tcx.sess.fatal("miri cannot be run on programs that fail compilation");
+            }
 
             init_late_loggers(tcx);
             if !tcx.sess.crate_types().contains(&CrateType::Executable) {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 4d7bbb643b8..29881bbcfca 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -459,7 +459,7 @@ impl<'tcx> Stack {
 impl Stacks {
     pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet<BorTag>) {
         if self.modified_since_last_gc {
-            for stack in self.stacks.iter_mut_all() {
+            for (_stack_range, stack) in self.stacks.iter_mut_all() {
                 if stack.len() > 64 {
                     stack.retain(live_tags);
                 }
@@ -511,8 +511,8 @@ impl<'tcx> Stacks {
         ) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx> {
         self.modified_since_last_gc = true;
-        for (offset, stack) in self.stacks.iter_mut(range.start, range.size) {
-            let mut dcx = dcx_builder.build(&mut self.history, offset);
+        for (stack_range, stack) in self.stacks.iter_mut(range.start, range.size) {
+            let mut dcx = dcx_builder.build(&mut self.history, Size::from_bytes(stack_range.start));
             f(stack, &mut dcx, &mut self.exposed_tags)?;
             dcx_builder = dcx.unbuild();
         }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
index 2c6d27ced01..10873c46a6c 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
@@ -3,7 +3,6 @@ use std::ops::Range;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::{Span, SpanData};
-use rustc_target::abi::Size;
 
 use crate::borrow_tracker::tree_borrows::{
     perms::{PermTransition, Permission},
@@ -14,18 +13,30 @@ use crate::borrow_tracker::{AccessKind, ProtectorKind};
 use crate::*;
 
 /// Complete data for an event:
-/// - `kind` is what happened to the permissions
-/// - `access_kind` and `access_range` describe the access that caused the event
-/// - `offset` allows filtering only the relevant events for a given memory location
-/// (see how we perform the filtering in `History::extract_relevant`.
-/// - `span` is the line of code in question
 #[derive(Clone, Debug)]
 pub struct Event {
+    /// Transformation of permissions that occured because of this event
     pub transition: PermTransition,
+    /// Kind of the access that triggered this event
     pub access_kind: AccessKind,
+    /// Relative position of the tag to the one used for the access
     pub is_foreign: bool,
+    /// User-visible range of the access
     pub access_range: AllocRange,
-    pub offset: Size,
+    /// The transition recorded by this event only occured on a subrange of
+    /// `access_range`: a single access on `access_range` triggers several events,
+    /// each with their own mutually disjoint `transition_range`. No-op transitions
+    /// should not be recorded as events, so the union of all `transition_range` is not
+    /// necessarily the entire `access_range`.
+    ///
+    /// No data from any `transition_range` should ever be user-visible, because
+    /// both the start and end of `transition_range` are entirely dependent on the
+    /// internal representation of `RangeMap` which is supposed to be opaque.
+    /// What will be shown in the error message is the first byte `error_offset` of
+    /// the `TbError`, which should satisfy
+    /// `event.transition_range.contains(error.error_offset)`.
+    pub transition_range: Range<u64>,
+    /// Line of code that triggered this event
     pub span: Span,
 }
 
@@ -35,9 +46,9 @@ pub struct Event {
 /// Available filtering methods include `History::forget` and `History::extract_relevant`.
 #[derive(Clone, Debug)]
 pub struct History {
-    pub tag: BorTag,
-    pub created: (Span, Permission),
-    pub events: Vec<Event>,
+    tag: BorTag,
+    created: (Span, Permission),
+    events: Vec<Event>,
 }
 
 /// History formatted for use by `src/diagnostics.rs`.
@@ -60,12 +71,7 @@ impl HistoryData {
     // Format events from `new_history` into those recorded by `self`.
     //
     // NOTE: also converts `Span` to `SpanData`.
-    pub fn extend(
-        &mut self,
-        new_history: History,
-        tag_name: &'static str,
-        show_initial_state: bool,
-    ) {
+    fn extend(&mut self, new_history: History, tag_name: &'static str, show_initial_state: bool) {
         let History { tag, created, events } = new_history;
         let this = format!("the {tag_name} tag {tag:?}");
         let msg_initial_state = format!(", in the initial state {}", created.1);
@@ -75,9 +81,16 @@ impl HistoryData {
         );
 
         self.events.push((Some(created.0.data()), msg_creation));
-        for &Event { transition, access_kind, is_foreign, access_range, span, offset: _ } in &events
+        for &Event {
+            transition,
+            access_kind,
+            is_foreign,
+            access_range,
+            span,
+            transition_range: _,
+        } in &events
         {
-            // NOTE: `offset` is explicitly absent from the error message, it has no significance
+            // NOTE: `transition_range` is explicitly absent from the error message, it has no significance
             // to the user. The meaningful one is `access_range`.
             self.events.push((Some(span.data()), format!("{this} then transitioned {transition} due to a {rel} {access_kind} at offsets {access_range:?}", rel = if is_foreign { "foreign" } else { "child" })));
             self.events.push((None, format!("this corresponds to {}", transition.summary())));
@@ -197,44 +210,19 @@ impl History {
         History { events: Vec::new(), created: self.created, tag: self.tag }
     }
 
-    /// Reconstruct the history relevant to `error_offset` knowing that
-    /// its permission followed `complete_transition`.
-    ///
-    /// Here's how we do this:
-    /// - we know `full := complete_transition` the transition of the permission from
-    /// its initialization to the state just before the error was caused,
-    /// we want to find a chain of events that produces `full`
-    /// - we decompose `full` into `pre o post` where
-    /// `pre` is the best applicable transition from recorded events
-    /// - we select the event that caused `pre` and iterate
-    /// to find the chain of events that produces `full := post`
-    ///
-    /// To find the "best applicable transition" for full:
-    /// - eliminate events that cannot be applied because their offset is too big
-    /// - eliminate events that cannot be applied because their starting point is wrong
-    /// - select the one that happened closest to the range of interest
-    fn extract_relevant(&self, complete_transition: PermTransition, error_offset: Size) -> Self {
-        let mut selected_events: Vec<Event> = Vec::new();
-        let mut full = complete_transition;
-        while !full.is_noop() {
-            let (pre, post) = self
+    /// Reconstruct the history relevant to `error_offset` by filtering
+    /// only events whose range contains the offset we are interested in.
+    fn extract_relevant(&self, error_offset: u64) -> Self {
+        History {
+            events: self
                 .events
                 .iter()
-                .filter(|e| e.offset <= error_offset)
-                .filter_map(|pre_canditate| {
-                    full.apply_start(pre_canditate.transition)
-                        .map(|post_canditate| (pre_canditate, post_canditate))
-                })
-                .max_by_key(|(pre_canditate, _post_candidate)| pre_canditate.offset)
-                .unwrap();
-            // If this occurs we will loop infinitely !
-            // Make sure to only put non-noop transitions in `History`.
-            assert!(!pre.transition.is_noop());
-            full = post;
-            selected_events.push(pre.clone());
+                .filter(|e| e.transition_range.contains(&error_offset))
+                .cloned()
+                .collect::<Vec<_>>(),
+            created: self.created,
+            tag: self.tag,
         }
-
-        History { events: selected_events, created: self.created, tag: self.tag }
     }
 }
 
@@ -242,8 +230,8 @@ impl History {
 pub(super) struct TbError<'node> {
     /// What failure occurred.
     pub error_kind: TransitionError,
-    /// The byte at which the conflict occured.
-    pub error_offset: Size,
+    /// The offset (into the allocation) at which the conflict occurred.
+    pub error_offset: u64,
     /// 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
@@ -261,12 +249,11 @@ impl TbError<'_> {
     /// Produce a UB error.
     pub fn build<'tcx>(self) -> InterpError<'tcx> {
         use TransitionError::*;
-        let started_as = self.conflicting_info.history.created.1;
         let kind = self.access_kind;
         let accessed = self.accessed_info;
         let conflicting = self.conflicting_info;
         let accessed_is_conflicting = accessed.tag == conflicting.tag;
-        let (pre_error, title, details, conflicting_tag_name) = match self.error_kind {
+        let (title, details, conflicting_tag_name) = match self.error_kind {
             ChildAccessForbidden(perm) => {
                 let conflicting_tag_name =
                     if accessed_is_conflicting { "accessed" } else { "conflicting" };
@@ -280,7 +267,7 @@ impl TbError<'_> {
                 details.push(format!(
                     "the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids child {kind}es"
                 ));
-                (perm, title, details, conflicting_tag_name)
+                (title, details, conflicting_tag_name)
             }
             ProtectedTransition(transition) => {
                 let conflicting_tag_name = "protected";
@@ -297,7 +284,7 @@ impl TbError<'_> {
                         loss = transition.summary(),
                     ),
                 ];
-                (transition.started(), title, details, conflicting_tag_name)
+                (title, details, conflicting_tag_name)
             }
             ProtectedDealloc => {
                 let conflicting_tag_name = "strongly protected";
@@ -308,16 +295,15 @@ impl TbError<'_> {
                     ),
                     format!("the {conflicting_tag_name} tag {conflicting} disallows deallocations"),
                 ];
-                (started_as, title, details, conflicting_tag_name)
+                (title, details, conflicting_tag_name)
             }
         };
-        let pre_transition = PermTransition::from(started_as, pre_error).unwrap();
         let mut history = HistoryData::default();
         if !accessed_is_conflicting {
             history.extend(self.accessed_info.history.forget(), "accessed", false);
         }
         history.extend(
-            self.conflicting_info.history.extract_relevant(pre_transition, self.error_offset),
+            self.conflicting_info.history.extract_relevant(self.error_offset),
             conflicting_tag_name,
             true,
         );
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index 6392f5101ad..52947aa0f9f 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -311,7 +311,7 @@ impl<'tcx> Tree {
         parent_tag: BorTag,
         new_tag: BorTag,
         default_initial_perm: Permission,
-        range: AllocRange,
+        reborrow_range: AllocRange,
         span: Span,
     ) -> InterpResult<'tcx> {
         assert!(!self.tag_mapping.contains_key(&new_tag));
@@ -332,7 +332,8 @@ impl<'tcx> Tree {
         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) {
+        for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size)
+        {
             perms.insert(idx, perm);
         }
         Ok(())
@@ -344,12 +345,12 @@ impl<'tcx> Tree {
     pub fn dealloc(
         &mut self,
         tag: BorTag,
-        range: AllocRange,
+        access_range: AllocRange,
         global: &GlobalState,
         span: Span, // diagnostics
     ) -> InterpResult<'tcx> {
-        self.perform_access(AccessKind::Write, tag, range, global, span)?;
-        for (offset, perms) in self.rperms.iter_mut(range.start, range.size) {
+        self.perform_access(AccessKind::Write, tag, access_range, global, span)?;
+        for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) {
             TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
                 .traverse_parents_this_children_others(
                     tag,
@@ -368,7 +369,7 @@ impl<'tcx> Tree {
                         TbError {
                             conflicting_info,
                             access_kind: AccessKind::Write,
-                            error_offset: offset,
+                            error_offset: perms_range.start,
                             error_kind,
                             accessed_info,
                         }
@@ -388,11 +389,11 @@ impl<'tcx> Tree {
         &mut self,
         access_kind: AccessKind,
         tag: BorTag,
-        range: AllocRange,
+        access_range: AllocRange,
         global: &GlobalState,
         span: Span, // diagnostics
     ) -> InterpResult<'tcx> {
-        for (offset, perms) in self.rperms.iter_mut(range.start, range.size) {
+        for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) {
             TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
                 .traverse_parents_this_children_others(
                     tag,
@@ -456,9 +457,9 @@ impl<'tcx> Tree {
                             node.debug_info.history.push(diagnostics::Event {
                                 transition,
                                 access_kind,
-                                access_range: range,
                                 is_foreign: rel_pos.is_foreign(),
-                                offset,
+                                access_range,
+                                transition_range: perms_range.clone(),
                                 span,
                             });
                             old_state.permission =
@@ -472,7 +473,7 @@ impl<'tcx> Tree {
                         TbError {
                             conflicting_info,
                             access_kind,
-                            error_offset: offset,
+                            error_offset: perms_range.start,
                             error_kind,
                             accessed_info,
                         }
@@ -487,7 +488,13 @@ impl<'tcx> Tree {
 /// 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
+        let root_is_needed = self.keep_only_needed(self.root, live_tags); // root can't be removed
+        assert!(root_is_needed);
+        // Right after the GC runs is a good moment to check if we can
+        // merge some adjacent ranges that were made equal by the removal of some
+        // tags (this does not necessarily mean that they have identical internal representations,
+        // see the `PartialEq` impl for `UniValMap`)
+        self.rperms.merge_adjacent_thorough();
     }
 
     /// Traverses the entire tree looking for useless tags.
@@ -530,7 +537,7 @@ impl Tree {
             // the tag from the mapping.
             let tag = node.tag;
             self.nodes.remove(idx);
-            for perms in self.rperms.iter_mut_all() {
+            for (_perms_range, perms) in self.rperms.iter_mut_all() {
                 perms.remove(idx);
             }
             self.tag_mapping.remove(&tag);
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs
index c1d452ca89e..58af32385c5 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs
@@ -36,13 +36,42 @@ pub struct UniKeyMap<K> {
 }
 
 /// From UniIndex to V
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, 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: PartialEq> UniValMap<V> {
+    /// Exact equality of two maps.
+    /// Less accurate but faster than `equivalent`, mostly because
+    /// of the fast path when the lengths are different.
+    pub fn identical(&self, other: &Self) -> bool {
+        self.data == other.data
+    }
+
+    /// Equality up to trailing `None`s of two maps, i.e.
+    /// do they represent the same mapping ?
+    pub fn equivalent(&self, other: &Self) -> bool {
+        let min_len = self.data.len().min(other.data.len());
+        self.data[min_len..].iter().all(Option::is_none)
+            && other.data[min_len..].iter().all(Option::is_none)
+            && (self.data[..min_len] == other.data[..min_len])
+    }
+}
+
+impl<V: PartialEq> PartialEq for UniValMap<V> {
+    /// 2023-05: We found that using `equivalent` rather than `identical`
+    /// in the equality testing of the `RangeMap` is neutral for most
+    /// benchmarks, while being quite beneficial for `zip-equal`
+    /// and to a lesser extent for `unicode`, `slice-get-unchecked` and
+    /// `backtraces` as well.
+    fn eq(&self, other: &Self) -> bool {
+        self.equivalent(other)
+    }
+}
+
 impl<V> Default for UniValMap<V> {
     fn default() -> Self {
         Self { data: Vec::default() }
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 13306b4809c..f6252c43f9f 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -275,20 +275,20 @@ impl MemoryCellClocks {
     /// not used previously as atomic memory.
     fn load_acquire(
         &mut self,
-        clocks: &mut ThreadClockSet,
+        thread_clocks: &mut ThreadClockSet,
         index: VectorIdx,
     ) -> Result<(), DataRace> {
-        self.atomic_read_detect(clocks, index)?;
+        self.atomic_read_detect(thread_clocks, index)?;
         if let Some(atomic) = self.atomic() {
-            clocks.clock.join(&atomic.sync_vector);
+            thread_clocks.clock.join(&atomic.sync_vector);
         }
         Ok(())
     }
 
     /// Checks if the memory cell access is ordered with all prior atomic reads and writes
-    fn race_free_with_atomic(&self, clocks: &ThreadClockSet) -> bool {
+    fn race_free_with_atomic(&self, thread_clocks: &ThreadClockSet) -> bool {
         if let Some(atomic) = self.atomic() {
-            atomic.read_vector <= clocks.clock && atomic.write_vector <= clocks.clock
+            atomic.read_vector <= thread_clocks.clock && atomic.write_vector <= thread_clocks.clock
         } else {
             true
         }
@@ -299,54 +299,70 @@ impl MemoryCellClocks {
     /// not used previously as atomic memory.
     fn load_relaxed(
         &mut self,
-        clocks: &mut ThreadClockSet,
+        thread_clocks: &mut ThreadClockSet,
         index: VectorIdx,
     ) -> Result<(), DataRace> {
-        self.atomic_read_detect(clocks, index)?;
+        self.atomic_read_detect(thread_clocks, index)?;
         if let Some(atomic) = self.atomic() {
-            clocks.fence_acquire.join(&atomic.sync_vector);
+            thread_clocks.fence_acquire.join(&atomic.sync_vector);
         }
         Ok(())
     }
 
     /// Update the memory cell data-race tracking for atomic
     /// store release semantics.
-    fn store_release(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
-        self.atomic_write_detect(clocks, index)?;
+    fn store_release(
+        &mut self,
+        thread_clocks: &ThreadClockSet,
+        index: VectorIdx,
+    ) -> Result<(), DataRace> {
+        self.atomic_write_detect(thread_clocks, index)?;
         let atomic = self.atomic_mut();
-        atomic.sync_vector.clone_from(&clocks.clock);
+        atomic.sync_vector.clone_from(&thread_clocks.clock);
         Ok(())
     }
 
     /// Update the memory cell data-race tracking for atomic
     /// store relaxed semantics.
-    fn store_relaxed(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
-        self.atomic_write_detect(clocks, index)?;
+    fn store_relaxed(
+        &mut self,
+        thread_clocks: &ThreadClockSet,
+        index: VectorIdx,
+    ) -> Result<(), DataRace> {
+        self.atomic_write_detect(thread_clocks, index)?;
 
         // The handling of release sequences was changed in C++20 and so
         // the code here is different to the paper since now all relaxed
         // stores block release sequences. The exception for same-thread
         // relaxed stores has been removed.
         let atomic = self.atomic_mut();
-        atomic.sync_vector.clone_from(&clocks.fence_release);
+        atomic.sync_vector.clone_from(&thread_clocks.fence_release);
         Ok(())
     }
 
     /// Update the memory cell data-race tracking for atomic
     /// store release semantics for RMW operations.
-    fn rmw_release(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
-        self.atomic_write_detect(clocks, index)?;
+    fn rmw_release(
+        &mut self,
+        thread_clocks: &ThreadClockSet,
+        index: VectorIdx,
+    ) -> Result<(), DataRace> {
+        self.atomic_write_detect(thread_clocks, index)?;
         let atomic = self.atomic_mut();
-        atomic.sync_vector.join(&clocks.clock);
+        atomic.sync_vector.join(&thread_clocks.clock);
         Ok(())
     }
 
     /// Update the memory cell data-race tracking for atomic
     /// store relaxed semantics for RMW operations.
-    fn rmw_relaxed(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
-        self.atomic_write_detect(clocks, index)?;
+    fn rmw_relaxed(
+        &mut self,
+        thread_clocks: &ThreadClockSet,
+        index: VectorIdx,
+    ) -> Result<(), DataRace> {
+        self.atomic_write_detect(thread_clocks, index)?;
         let atomic = self.atomic_mut();
-        atomic.sync_vector.join(&clocks.fence_release);
+        atomic.sync_vector.join(&thread_clocks.fence_release);
         Ok(())
     }
 
@@ -354,26 +370,26 @@ impl MemoryCellClocks {
     /// not happen-before the atomic-read.
     fn atomic_read_detect(
         &mut self,
-        clocks: &ThreadClockSet,
+        thread_clocks: &ThreadClockSet,
         index: VectorIdx,
     ) -> Result<(), DataRace> {
-        log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, clocks);
+        log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, thread_clocks);
         let atomic = self.atomic_mut();
-        atomic.read_vector.set_at_index(&clocks.clock, index);
-        if self.write <= clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
+        atomic.read_vector.set_at_index(&thread_clocks.clock, index);
+        if self.write <= thread_clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
     }
 
     /// Detect data-races with an atomic write, either with a non-atomic read or with
     /// a non-atomic write.
     fn atomic_write_detect(
         &mut self,
-        clocks: &ThreadClockSet,
+        thread_clocks: &ThreadClockSet,
         index: VectorIdx,
     ) -> Result<(), DataRace> {
-        log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, clocks);
+        log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, thread_clocks);
         let atomic = self.atomic_mut();
-        atomic.write_vector.set_at_index(&clocks.clock, index);
-        if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
+        atomic.write_vector.set_at_index(&thread_clocks.clock, index);
+        if self.write <= thread_clocks.clock[self.write_index] && self.read <= thread_clocks.clock {
             Ok(())
         } else {
             Err(DataRace)
@@ -384,21 +400,21 @@ impl MemoryCellClocks {
     /// returns true if a data-race is detected.
     fn read_race_detect(
         &mut self,
-        clocks: &mut ThreadClockSet,
+        thread_clocks: &mut ThreadClockSet,
         index: VectorIdx,
         current_span: Span,
     ) -> Result<(), DataRace> {
-        log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks);
+        log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, thread_clocks);
         if !current_span.is_dummy() {
-            clocks.clock[index].span = current_span;
+            thread_clocks.clock[index].span = current_span;
         }
-        if self.write <= clocks.clock[self.write_index] {
+        if self.write <= thread_clocks.clock[self.write_index] {
             let race_free = if let Some(atomic) = self.atomic() {
-                atomic.write_vector <= clocks.clock
+                atomic.write_vector <= thread_clocks.clock
             } else {
                 true
             };
-            self.read.set_at_index(&clocks.clock, index);
+            self.read.set_at_index(&thread_clocks.clock, index);
             if race_free { Ok(()) } else { Err(DataRace) }
         } else {
             Err(DataRace)
@@ -409,22 +425,23 @@ impl MemoryCellClocks {
     /// returns true if a data-race is detected.
     fn write_race_detect(
         &mut self,
-        clocks: &mut ThreadClockSet,
+        thread_clocks: &mut ThreadClockSet,
         index: VectorIdx,
         write_type: WriteType,
         current_span: Span,
     ) -> Result<(), DataRace> {
-        log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks);
+        log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, thread_clocks);
         if !current_span.is_dummy() {
-            clocks.clock[index].span = current_span;
+            thread_clocks.clock[index].span = current_span;
         }
-        if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
+        if self.write <= thread_clocks.clock[self.write_index] && self.read <= thread_clocks.clock {
             let race_free = if let Some(atomic) = self.atomic() {
-                atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock
+                atomic.write_vector <= thread_clocks.clock
+                    && atomic.read_vector <= thread_clocks.clock
             } else {
                 true
             };
-            self.write = clocks.clock[index];
+            self.write = thread_clocks.clock[index];
             self.write_index = index;
             self.write_type = write_type;
             if race_free {
@@ -764,24 +781,24 @@ impl VClockAlloc {
     fn report_data_race<'tcx>(
         global: &GlobalState,
         thread_mgr: &ThreadManager<'_, '_>,
-        range: &MemoryCellClocks,
+        mem_clocks: &MemoryCellClocks,
         action: &str,
         is_atomic: bool,
         ptr_dbg: Pointer<AllocId>,
     ) -> InterpResult<'tcx> {
         let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
         let write_clock;
-        let (other_action, other_thread, other_clock) = if range.write
-            > current_clocks.clock[range.write_index]
+        let (other_action, other_thread, other_clock) = if mem_clocks.write
+            > current_clocks.clock[mem_clocks.write_index]
         {
             // Convert the write action into the vector clock it
             // represents for diagnostic purposes.
-            write_clock = VClock::new_with_index(range.write_index, range.write);
-            (range.write_type.get_descriptor(), range.write_index, &write_clock)
-        } else if let Some(idx) = Self::find_gt_index(&range.read, &current_clocks.clock) {
-            ("Read", idx, &range.read)
+            write_clock = VClock::new_with_index(mem_clocks.write_index, mem_clocks.write);
+            (mem_clocks.write_type.get_descriptor(), mem_clocks.write_index, &write_clock)
+        } else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) {
+            ("Read", idx, &mem_clocks.read)
         } else if !is_atomic {
-            if let Some(atomic) = range.atomic() {
+            if let Some(atomic) = mem_clocks.atomic() {
                 if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
                 {
                     ("Atomic Store", idx, &atomic.write_vector)
@@ -832,10 +849,10 @@ impl VClockAlloc {
         thread_mgr: &ThreadManager<'_, '_>,
     ) -> bool {
         if global.race_detecting() {
-            let (_, clocks) = global.current_thread_state(thread_mgr);
+            let (_, thread_clocks) = global.current_thread_state(thread_mgr);
             let alloc_ranges = self.alloc_ranges.borrow();
-            for (_, range) in alloc_ranges.iter(range.start, range.size) {
-                if !range.race_free_with_atomic(&clocks) {
+            for (_, mem_clocks) in alloc_ranges.iter(range.start, range.size) {
+                if !mem_clocks.race_free_with_atomic(&thread_clocks) {
                     return false;
                 }
             }
@@ -851,25 +868,29 @@ impl VClockAlloc {
     pub fn read<'tcx>(
         &self,
         alloc_id: AllocId,
-        range: AllocRange,
+        access_range: AllocRange,
         machine: &MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
         let current_span = machine.current_span();
         let global = machine.data_race.as_ref().unwrap();
         if global.race_detecting() {
-            let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
+            let (index, mut thread_clocks) = global.current_thread_state_mut(&machine.threads);
             let mut alloc_ranges = self.alloc_ranges.borrow_mut();
-            for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
-                if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) {
-                    drop(clocks);
+            for (mem_clocks_range, mem_clocks) in
+                alloc_ranges.iter_mut(access_range.start, access_range.size)
+            {
+                if let Err(DataRace) =
+                    mem_clocks.read_race_detect(&mut thread_clocks, index, current_span)
+                {
+                    drop(thread_clocks);
                     // Report data-race.
                     return Self::report_data_race(
                         global,
                         &machine.threads,
-                        range,
+                        mem_clocks,
                         "Read",
                         false,
-                        Pointer::new(alloc_id, offset),
+                        Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
                     );
                 }
             }
@@ -883,27 +904,32 @@ impl VClockAlloc {
     fn unique_access<'tcx>(
         &mut self,
         alloc_id: AllocId,
-        range: AllocRange,
+        access_range: AllocRange,
         write_type: WriteType,
         machine: &mut MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
         let current_span = machine.current_span();
         let global = machine.data_race.as_mut().unwrap();
         if global.race_detecting() {
-            let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
-            for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
-                if let Err(DataRace) =
-                    range.write_race_detect(&mut clocks, index, write_type, current_span)
-                {
-                    drop(clocks);
+            let (index, mut thread_clocks) = global.current_thread_state_mut(&machine.threads);
+            for (mem_clocks_range, mem_clocks) in
+                self.alloc_ranges.get_mut().iter_mut(access_range.start, access_range.size)
+            {
+                if let Err(DataRace) = mem_clocks.write_race_detect(
+                    &mut thread_clocks,
+                    index,
+                    write_type,
+                    current_span,
+                ) {
+                    drop(thread_clocks);
                     // Report data-race
                     return Self::report_data_race(
                         global,
                         &machine.threads,
-                        range,
+                        mem_clocks,
                         write_type.get_descriptor(),
                         false,
-                        Pointer::new(alloc_id, offset),
+                        Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
                     );
                 }
             }
@@ -1125,19 +1151,23 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                 data_race.maybe_perform_sync_operation(
                     &this.machine.threads,
                     current_span,
-                    |index, mut clocks| {
-                        for (offset, range) in
+                    |index, mut thread_clocks| {
+                        for (mem_clocks_range, mem_clocks) in
                             alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size)
                         {
-                            if let Err(DataRace) = op(range, &mut clocks, index, atomic) {
-                                mem::drop(clocks);
+                            if let Err(DataRace) = op(mem_clocks, &mut thread_clocks, index, atomic)
+                            {
+                                mem::drop(thread_clocks);
                                 return VClockAlloc::report_data_race(
                                     data_race,
                                     &this.machine.threads,
-                                    range,
+                                    mem_clocks,
                                     description,
                                     true,
-                                    Pointer::new(alloc_id, offset),
+                                    Pointer::new(
+                                        alloc_id,
+                                        Size::from_bytes(mem_clocks_range.start),
+                                    ),
                                 )
                                 .map(|_| true);
                             }
@@ -1150,13 +1180,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
 
                 // Log changes to atomic memory.
                 if log::log_enabled!(log::Level::Trace) {
-                    for (_offset, range) in alloc_meta.alloc_ranges.borrow().iter(base_offset, size)
+                    for (_offset, mem_clocks) in
+                        alloc_meta.alloc_ranges.borrow().iter(base_offset, size)
                     {
                         log::trace!(
                             "Updated atomic memory({:?}, size={}) to {:#?}",
                             place.ptr,
                             size.bytes(),
-                            range.atomic_ops
+                            mem_clocks.atomic_ops
                         );
                     }
                 }
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 21c5a9c1b70..32717a0d28b 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -4,6 +4,8 @@
 use std::borrow::Cow;
 use std::cell::RefCell;
 use std::fmt;
+use std::path::Path;
+use std::process;
 
 use rand::rngs::StdRng;
 use rand::SeedableRng;
@@ -498,7 +500,21 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         let layouts =
             PrimitiveLayouts::new(layout_cx).expect("Couldn't get layouts of primitive types");
         let profiler = config.measureme_out.as_ref().map(|out| {
-            measureme::Profiler::new(out).expect("Couldn't create `measureme` profiler")
+            let crate_name = layout_cx
+                .tcx
+                .sess
+                .opts
+                .crate_name
+                .clone()
+                .unwrap_or_else(|| "unknown-crate".to_string());
+            let pid = process::id();
+            // We adopt the same naming scheme for the profiler output that rustc uses. In rustc,
+            // the PID is padded so that the nondeterministic value of the PID does not spread
+            // nondeterminisim to the allocator. In Miri we are not aiming for such performance
+            // control, we just pad for consistency with rustc.
+            let filename = format!("{crate_name}-{pid:07}");
+            let path = Path::new(out).join(filename);
+            measureme::Profiler::new(path).expect("Couldn't create `measureme` profiler")
         });
         let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0));
         let borrow_tracker = config.borrow_tracker.map(|bt| bt.instantiate_global_state(config));
diff --git a/src/tools/miri/src/range_map.rs b/src/tools/miri/src/range_map.rs
index 62198061827..146715ddda2 100644
--- a/src/tools/miri/src/range_map.rs
+++ b/src/tools/miri/src/range_map.rs
@@ -62,8 +62,10 @@ impl<T> RangeMap<T> {
     /// *not* split items if they overlap with the edges. Do not use this to mutate
     /// through interior mutability.
     ///
-    /// The iterator also provides the offset of the given element.
-    pub fn iter(&self, offset: Size, len: Size) -> impl Iterator<Item = (Size, &T)> {
+    /// The iterator also provides the range of the given element.
+    /// How exactly the ranges are split can differ even for otherwise identical
+    /// maps, so user-visible behavior should never depend on the exact range.
+    pub fn iter(&self, offset: Size, len: Size) -> impl Iterator<Item = (ops::Range<u64>, &T)> {
         let offset = offset.bytes();
         let len = len.bytes();
         // Compute a slice starting with the elements we care about.
@@ -84,13 +86,21 @@ impl<T> RangeMap<T> {
         slice
             .iter()
             .take_while(move |elem| elem.range.start < end)
-            .map(|elem| (Size::from_bytes(elem.range.start), &elem.data))
+            .map(|elem| (elem.range.clone(), &elem.data))
     }
 
-    pub fn iter_mut_all(&mut self) -> impl Iterator<Item = &mut T> {
-        self.v.iter_mut().map(|elem| &mut elem.data)
+    /// Provides mutable iteration over all elements.
+    /// The iterator also provides the range of the given element.
+    /// How exactly the ranges are split can differ even for otherwise identical
+    /// maps, so user-visible behavior should never depend on the exact range.
+    pub fn iter_mut_all(&mut self) -> impl Iterator<Item = (ops::Range<u64>, &mut T)> {
+        self.v.iter_mut().map(|elem| (elem.range.clone(), &mut elem.data))
     }
 
+    /// Provides iteration over all elements.
+    /// The iterator also provides the range of the given element.
+    /// How exactly the ranges are split can differ even for otherwise identical
+    /// maps, so user-visible behavior should never depend on the exact range.
     pub fn iter_all(&self) -> impl Iterator<Item = (ops::Range<u64>, &T)> {
         self.v.iter().map(|elem| (elem.range.clone(), &elem.data))
     }
@@ -126,8 +136,15 @@ impl<T> RangeMap<T> {
     /// to make sure that when they are mutated, the effect is constrained to the given range.
     /// Moreover, this will opportunistically merge neighbouring equal blocks.
     ///
-    /// The iterator also provides the offset of the given element.
-    pub fn iter_mut(&mut self, offset: Size, len: Size) -> impl Iterator<Item = (Size, &mut T)>
+    /// The iterator also provides the range of the given element.
+    /// How exactly the ranges are split (both prior to and resulting from the execution of this
+    /// function) can differ even for otherwise identical maps,
+    /// so user-visible behavior should never depend on the exact range.
+    pub fn iter_mut(
+        &mut self,
+        offset: Size,
+        len: Size,
+    ) -> impl Iterator<Item = (ops::Range<u64>, &mut T)>
     where
         T: Clone + PartialEq,
     {
@@ -208,7 +225,25 @@ impl<T> RangeMap<T> {
             // Now we yield the slice. `end` is inclusive.
             &mut self.v[first_idx..=end_idx]
         };
-        slice.iter_mut().map(|elem| (Size::from_bytes(elem.range.start), &mut elem.data))
+        slice.iter_mut().map(|elem| (elem.range.clone(), &mut elem.data))
+    }
+
+    /// Remove all adjacent duplicates
+    pub fn merge_adjacent_thorough(&mut self)
+    where
+        T: PartialEq,
+    {
+        let clean = Vec::with_capacity(self.v.len());
+        for elem in std::mem::replace(&mut self.v, clean) {
+            if let Some(prev) = self.v.last_mut() {
+                if prev.data == elem.data {
+                    assert_eq!(prev.range.end, elem.range.start);
+                    prev.range.end = elem.range.end;
+                    continue;
+                }
+            }
+            self.v.push(elem);
+        }
     }
 }
 
diff --git a/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs b/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs
index 2ccb6704b05..98c22fef076 100644
--- a/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs
+++ b/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs
@@ -1,5 +1,16 @@
+// This is a proc-macro crate.
+
+extern crate proc_macro; // make sure proc_macro is in the sysroot
+
 #[cfg(doctest)]
 compile_error!("rustdoc should not touch me");
 
-#[cfg(test)]
+#[cfg(miri)]
 compile_error!("Miri should not touch me");
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn make_answer(_item: TokenStream) -> TokenStream {
+    "fn answer() -> u32 { 42 }".parse().unwrap()
+}
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index 52deba9108c..fe70ab3f45a 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -2,6 +2,8 @@ use colored::*;
 use regex::bytes::Regex;
 use std::path::{Path, PathBuf};
 use std::{env, process::Command};
+use ui_test::status_emitter::StatusEmitter;
+use ui_test::CommandBuilder;
 use ui_test::{color_eyre::Result, Config, Match, Mode, OutputConflictHandling};
 
 fn miri_path() -> PathBuf {
@@ -44,17 +46,9 @@ fn build_so_for_c_ffi_tests() -> PathBuf {
 }
 
 fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
-    let mut config = Config {
-        target: Some(target.to_owned()),
-        stderr_filters: STDERR.clone(),
-        stdout_filters: STDOUT.clone(),
-        root_dir: PathBuf::from(path),
-        mode,
-        program: miri_path(),
-        quiet: false,
-        edition: Some("2018".into()),
-        ..Config::default()
-    };
+    // Miri is rustc-like, so we create a default builder for rustc and modify it
+    let mut program = CommandBuilder::rustc();
+    program.program = miri_path();
 
     let in_rustc_test_suite = option_env!("RUSTC_STAGE").is_some();
 
@@ -62,22 +56,20 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
     if in_rustc_test_suite {
         // Less aggressive warnings to make the rustc toolstate management less painful.
         // (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
-        config.args.push("-Astable-features".into());
-        config.args.push("-Aunused".into());
+        program.args.push("-Astable-features".into());
+        program.args.push("-Aunused".into());
     } else {
-        config.args.push("-Dwarnings".into());
-        config.args.push("-Dunused".into());
+        program.args.push("-Dwarnings".into());
+        program.args.push("-Dunused".into());
     }
     if let Ok(extra_flags) = env::var("MIRIFLAGS") {
         for flag in extra_flags.split_whitespace() {
-            config.args.push(flag.into());
+            program.args.push(flag.into());
         }
     }
-    config.args.push("-Zui-testing".into());
-    if let Some(target) = &config.target {
-        config.args.push("--target".into());
-        config.args.push(target.into());
-    }
+    program.args.push("-Zui-testing".into());
+    program.args.push("--target".into());
+    program.args.push(target.into());
 
     // If we're on linux, and we're testing the extern-so functionality,
     // then build the shared object file for testing external C function calls
@@ -86,18 +78,31 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
         let so_file_path = build_so_for_c_ffi_tests();
         let mut flag = std::ffi::OsString::from("-Zmiri-extern-so-file=");
         flag.push(so_file_path.into_os_string());
-        config.args.push(flag);
+        program.args.push(flag);
     }
 
     let skip_ui_checks = env::var_os("MIRI_SKIP_UI_CHECKS").is_some();
 
-    config.output_conflict_handling = match (env::var_os("MIRI_BLESS").is_some(), skip_ui_checks) {
+    let output_conflict_handling = match (env::var_os("MIRI_BLESS").is_some(), skip_ui_checks) {
         (false, false) => OutputConflictHandling::Error,
         (true, false) => OutputConflictHandling::Bless,
         (false, true) => OutputConflictHandling::Ignore,
         (true, true) => panic!("cannot use MIRI_BLESS and MIRI_SKIP_UI_CHECKS at the same time"),
     };
 
+    let mut config = Config {
+        target: Some(target.to_owned()),
+        stderr_filters: STDERR.clone(),
+        stdout_filters: STDOUT.clone(),
+        root_dir: PathBuf::from(path),
+        mode,
+        program,
+        output_conflict_handling,
+        quiet: false,
+        edition: Some("2021".into()),
+        ..Config::default()
+    };
+
     // Handle command-line arguments.
     let mut after_dashdash = false;
     config.path_filter.extend(std::env::args().skip(1).filter(|arg| {
@@ -135,7 +140,14 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
             "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
         ];
     }
-    ui_test::run_tests(config)
+    ui_test::run_tests_generic(
+        config,
+        // The files we're actually interested in (all `.rs` files).
+        |path| path.extension().is_some_and(|ext| ext == "rs"),
+        // This could be used to overwrite the `Config` on a per-test basis.
+        |_, _| None,
+        TextAndGha,
+    )
 }
 
 macro_rules! regexes {
@@ -235,3 +247,45 @@ fn main() -> Result<()> {
 
     Ok(())
 }
+
+/// This is a custom renderer for `ui_test` output that does not emit github actions
+/// `group`s, while still producing regular github actions messages on test failures.
+struct TextAndGha;
+impl StatusEmitter for TextAndGha {
+    fn failed_test<'a>(
+        &'a self,
+        revision: &'a str,
+        path: &'a Path,
+        cmd: &'a Command,
+        stderr: &'a [u8],
+    ) -> Box<dyn std::fmt::Debug + 'a> {
+        Box::new((
+            ui_test::status_emitter::Gha::<false>.failed_test(revision, path, cmd, stderr),
+            ui_test::status_emitter::Text.failed_test(revision, path, cmd, stderr),
+        ))
+    }
+
+    fn run_tests(&self, _config: &Config) -> Box<dyn ui_test::status_emitter::DuringTestRun> {
+        Box::new(TextAndGha)
+    }
+
+    fn finalize(
+        &self,
+        failures: usize,
+        succeeded: usize,
+        ignored: usize,
+        filtered: usize,
+    ) -> Box<dyn ui_test::status_emitter::Summary> {
+        Box::new((
+            ui_test::status_emitter::Gha::<false>.finalize(failures, succeeded, ignored, filtered),
+            ui_test::status_emitter::Text.finalize(failures, succeeded, ignored, filtered),
+        ))
+    }
+}
+
+impl ui_test::status_emitter::DuringTestRun for TextAndGha {
+    fn test_result(&mut self, path: &Path, revision: &str, result: &ui_test::TestResult) {
+        ui_test::status_emitter::Text.test_result(path, revision, result);
+        ui_test::status_emitter::Gha::<false>.test_result(path, revision, result);
+    }
+}
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.rs b/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.rs
index a07d8254ad3..e8ba824db71 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.rs
+++ b/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.rs
@@ -1,6 +1,6 @@
 use std::alloc::{alloc, dealloc, Layout};
 
-//@error-pattern: has size 1 and alignment 1, but gave size 1 and alignment 2
+//@error-in-other-file: has size 1 and alignment 1, but gave size 1 and alignment 2
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-bad-size.rs b/src/tools/miri/tests/fail/alloc/deallocate-bad-size.rs
index 47aaef1935e..e3f9a20ac3b 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-bad-size.rs
+++ b/src/tools/miri/tests/fail/alloc/deallocate-bad-size.rs
@@ -1,6 +1,6 @@
 use std::alloc::{alloc, dealloc, Layout};
 
-//@error-pattern: has size 1 and alignment 1, but gave size 2 and alignment 1
+//@error-in-other-file: has size 1 and alignment 1, but gave size 2 and alignment 1
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-twice.rs b/src/tools/miri/tests/fail/alloc/deallocate-twice.rs
index 1eb9bbf91ca..f07bbda4a9b 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-twice.rs
+++ b/src/tools/miri/tests/fail/alloc/deallocate-twice.rs
@@ -1,6 +1,6 @@
 use std::alloc::{alloc, dealloc, Layout};
 
-//@error-pattern: dereferenced after this allocation got freed
+//@error-in-other-file: dereferenced after this allocation got freed
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs
index 47b098c71a2..2e88e5644e4 100644
--- a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs
+++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs
@@ -1,6 +1,6 @@
 // Make sure we detect when the `Global` and `System` allocators are mixed
 // (even when the default `Global` uses `System`).
-//@error-pattern: /deallocating .*, which is Rust heap memory, using .* heap deallocation operation/
+//@error-in-other-file: /deallocating .*, which is Rust heap memory, using .* heap deallocation operation/
 
 //@normalize-stderr-test: "using [A-Za-z]+ heap deallocation operation" -> "using PLATFORM heap deallocation operation"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
diff --git a/src/tools/miri/tests/fail/alloc/reallocate-bad-size.rs b/src/tools/miri/tests/fail/alloc/reallocate-bad-size.rs
index 145c3393d67..49b2c62d7e4 100644
--- a/src/tools/miri/tests/fail/alloc/reallocate-bad-size.rs
+++ b/src/tools/miri/tests/fail/alloc/reallocate-bad-size.rs
@@ -1,6 +1,6 @@
 use std::alloc::{alloc, realloc, Layout};
 
-//@error-pattern: has size 1 and alignment 1, but gave size 2 and alignment 1
+//@error-in-other-file: has size 1 and alignment 1, but gave size 2 and alignment 1
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs b/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs
index 34f1658344a..130e2a8301e 100644
--- a/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs
+++ b/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs
@@ -1,6 +1,6 @@
 use std::alloc::{alloc, dealloc, realloc, Layout};
 
-//@error-pattern: dereferenced after this allocation got freed
+//@error-in-other-file: dereferenced after this allocation got freed
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/alloc/stack_free.rs b/src/tools/miri/tests/fail/alloc/stack_free.rs
index baf53decc44..15a17a25afe 100644
--- a/src/tools/miri/tests/fail/alloc/stack_free.rs
+++ b/src/tools/miri/tests/fail/alloc/stack_free.rs
@@ -1,7 +1,7 @@
 // Validation/SB changes why we fail
 //@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
 
-//@error-pattern: /deallocating .*, which is stack variable memory, using Rust heap deallocation operation/
+//@error-in-other-file: /deallocating .*, which is stack variable memory, using Rust heap deallocation operation/
 
 fn main() {
     let x = 42;
diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs b/src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs
index 065ad2d725f..7e6f490bb3d 100644
--- a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs
+++ b/src/tools/miri/tests/fail/concurrency/libc_pthread_create_main_terminate.rs
@@ -1,5 +1,5 @@
 //@ignore-target-windows: No libc on Windows
-//@error-pattern: the main thread terminated without waiting for all remaining threads
+//@error-in-other-file: the main thread terminated without waiting for all remaining threads
 
 // Check that we terminate the program when the main thread terminates.
 
diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr b/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr
index 94463bef8f0..c2de4afd68f 100644
--- a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr
+++ b/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_few_args.stderr
@@ -7,8 +7,8 @@ LL |     panic!()
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `thread_start` at RUSTLIB/std/src/panic.rs:LL:CC
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr b/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr
index fdbe91cc8a8..85ae930d439 100644
--- a/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr
+++ b/src/tools/miri/tests/fail/concurrency/libc_pthread_create_too_many_args.stderr
@@ -7,8 +7,8 @@ LL |     panic!()
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
-   = note: inside `thread_start` at RUSTLIB/std/src/panic.rs:LL:CC
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs b/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs
index 548ed63534d..b68a07797f8 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs
+++ b/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs
@@ -1,5 +1,5 @@
 //@only-target-windows: Uses win32 api functions
-//@error-pattern: Undefined Behavior: trying to join a detached thread
+//@error-in-other-file: Undefined Behavior: trying to join a detached thread
 
 // Joining a detached thread is undefined behavior.
 
diff --git a/src/tools/miri/tests/fail/const-ub-checks.rs b/src/tools/miri/tests/fail/const-ub-checks.rs
index ff265fba6e2..9cc8b91ff50 100644
--- a/src/tools/miri/tests/fail/const-ub-checks.rs
+++ b/src/tools/miri/tests/fail/const-ub-checks.rs
@@ -1,4 +1,3 @@
-
 const UNALIGNED_READ: () = unsafe {
     let x = &[0u8; 4];
     let ptr = x.as_ptr().cast::<u32>();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
index 2698c63a445..42077dfae2d 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
@@ -26,6 +26,7 @@ pub fn main() {
     //  2. write
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             // Concurrent allocate the memory.
             // Uses relaxed semantics to not generate
             // a release sequence.
@@ -34,6 +35,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
 
             // Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
index b78d5ef27d3..53f4e637a19 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
@@ -25,6 +25,7 @@ pub fn main() {
     //  2. write
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             // Concurrent allocate the memory.
             // Uses relaxed semantics to not generate
             // a release sequence.
@@ -34,6 +35,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
index 3f811d0f64d..9606df1d6ff 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
@@ -16,10 +16,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *(c.0 as *mut usize) = 32;
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
index 34fb3ac066f..0e29ab32eef 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
@@ -17,11 +17,13 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
             atomic_ref.load(Ordering::SeqCst)
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
             *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
index 63b0806f3bb..6f1792bc8f4 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
@@ -17,11 +17,13 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
             atomic_ref.store(32, Ordering::SeqCst)
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
             *atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
index 9092254be21..e84207e655d 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
@@ -16,10 +16,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             let _val = *(c.0 as *mut usize);
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
index 5a713905f4e..ca269b1bd2a 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
@@ -16,10 +16,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *(c.0 as *mut usize) = 32;
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
index 5848aa262b3..0d69a9a332d 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
@@ -17,11 +17,13 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
             atomic_ref.store(64, Ordering::SeqCst);
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             let atomic_ref = &mut *c.0;
             *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
index eecb980e905..0679b81f012 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
@@ -18,6 +18,7 @@ fn main() {
 
     let join = unsafe {
         spawn(move || {
+            let c = c; // capture `c`, not just its field.
             *c.0 = 32;
         })
     };
@@ -34,6 +35,7 @@ fn main() {
 
     let join2 = unsafe {
         spawn(move || {
+            let c = c; // capture `c`, not just its field.
             *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         })
     };
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
index 4c7fbdd7fe6..3c5dd424eb1 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
@@ -18,6 +18,7 @@ fn main() {
 
     let join = unsafe {
         spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 32;
         })
     };
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
index 18593cf56ae..3c25cdc0d8d 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
@@ -20,10 +20,12 @@ pub fn main() {
 
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let _val = *ptr.0;
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             __rust_dealloc(
                 //~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
                 ptr.0 as *mut _,
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
index a6f83d489e5..5d7a0cc1dc9 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
@@ -20,6 +20,7 @@ pub fn main() {
 
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             __rust_dealloc(
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
@@ -28,6 +29,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 //~ ERROR: dereferenced after this allocation got freed
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
index c82bfed09ee..87b5f204816 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
@@ -26,6 +26,7 @@ pub fn main() {
     //  3. stack-deallocate
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             {
                 let mut stack_var = 0usize;
@@ -39,6 +40,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             *pointer.load(Ordering::Acquire)
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
index 1e93a6cb094..b700f50ce19 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
@@ -19,10 +19,12 @@ pub fn main() {
 
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             *ptr.0 = 2;
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             __rust_dealloc(
                 //~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
                 ptr.0 as *mut _,
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
index 385584db27f..a7f43f03c02 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
@@ -19,6 +19,7 @@ pub fn main() {
 
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             __rust_dealloc(
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
@@ -27,6 +28,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
index 259fbdc497a..3d35187a018 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
@@ -26,6 +26,7 @@ pub fn main() {
     //  3. stack-deallocate
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             {
                 let mut stack_var = 0usize;
@@ -39,6 +40,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             *pointer.load(Ordering::Acquire) = 3;
         });
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
index 3d47b1accb3..b44be4ac64e 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
@@ -26,10 +26,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 32;
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.rs b/src/tools/miri/tests/fail/data_race/read_write_race.rs
index d996141db3e..aed3ca767f6 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.rs
@@ -15,10 +15,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             let _val = *c.0;
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
index b4e371f430d..40224ced12d 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
@@ -31,6 +31,7 @@ pub fn main() {
     //  5. read-value
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             // Concurrent allocate the memory.
             // Uses relaxed semantics to not generate
             // a release sequence.
@@ -46,6 +47,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             *pointer.load(Ordering::Acquire) = 3;
         });
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
index b7226fa626f..1b691b996f1 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
@@ -25,6 +25,7 @@ pub fn main() {
     //  4. load acquire : 2
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
         });
@@ -36,6 +37,7 @@ pub fn main() {
         });
 
         let j3 = spawn(move || {
+            let c = c; // avoid field capturing
             if SYNC.load(Ordering::Acquire) == 2 {
                 *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.rs b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
index dff33a42a1c..80b30053fc7 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
@@ -27,6 +27,7 @@ pub fn main() {
     //  4. load acquire : 3
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
             sleep(Duration::from_millis(200));
@@ -39,6 +40,7 @@ pub fn main() {
         });
 
         let j3 = spawn(move || {
+            let c = c; // avoid field capturing
             sleep(Duration::from_millis(500));
             if SYNC.load(Ordering::Acquire) == 3 {
                 *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
index f7a523841b8..33de1f17558 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
@@ -25,6 +25,7 @@ pub fn main() {
     //  3. load acquire : 2
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
 
@@ -36,6 +37,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             if SYNC.load(Ordering::Acquire) == 2 {
                 *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.rs b/src/tools/miri/tests/fail/data_race/rmw_race.rs
index 2201362b167..4d0ce8f9433 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.rs
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.rs
@@ -25,6 +25,7 @@ pub fn main() {
     //  4. load acquire : 3
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // capture `c`, not just its field.
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
         });
@@ -37,6 +38,7 @@ pub fn main() {
         });
 
         let j3 = spawn(move || {
+            let c = c; // capture `c`, not just its field.
             if SYNC.load(Ordering::Acquire) == 3 {
                 *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
index dec5ff274cc..d3c2ab3e4a4 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
@@ -13,7 +13,7 @@ fn main() {
 fn race(local: i32) {
     let ptr = MakeSend(&local as *const i32);
     thread::spawn(move || {
-        let ptr = ptr;
+        let ptr = ptr; // avoid field capturing
         let _val = unsafe { *ptr.0 };
     });
     // Make the other thread go first so that it does not UAF.
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.rs b/src/tools/miri/tests/fail/data_race/write_write_race.rs
index fe02d02f9dc..30e3460f222 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.rs
@@ -15,10 +15,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 32;
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
index c1c1b1fa6e3..25be42bd4eb 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
@@ -28,6 +28,7 @@ pub fn main() {
     //  5. write-value
     unsafe {
         let j1 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             // Concurrent allocate the memory.
             // Uses relaxed semantics to not generate
             // a release sequence.
@@ -46,6 +47,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
+            let ptr = ptr; // avoid field capturing
             let pointer = &*ptr.0;
             *pointer.load(Ordering::Acquire) = 3;
         });
diff --git a/src/tools/miri/tests/fail/deny_lint.rs b/src/tools/miri/tests/fail/deny_lint.rs
new file mode 100644
index 00000000000..f49fa49d09d
--- /dev/null
+++ b/src/tools/miri/tests/fail/deny_lint.rs
@@ -0,0 +1,8 @@
+//@error-in-other-file: miri cannot be run on programs that fail compilation
+
+#![deny(warnings, unused)]
+
+struct Foo;
+//~^ ERROR: struct `Foo` is never constructed
+
+fn main() {}
diff --git a/src/tools/miri/tests/fail/deny_lint.stderr b/src/tools/miri/tests/fail/deny_lint.stderr
new file mode 100644
index 00000000000..d1c9b481807
--- /dev/null
+++ b/src/tools/miri/tests/fail/deny_lint.stderr
@@ -0,0 +1,17 @@
+error: struct `Foo` is never constructed
+  --> $DIR/deny_lint.rs:LL:CC
+   |
+LL | struct Foo;
+   |        ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny_lint.rs:LL:CC
+   |
+LL | #![deny(warnings, unused)]
+   |                   ^^^^^^
+   = note: `#[deny(dead_code)]` implied by `#[deny(unused)]`
+
+error: miri cannot be run on programs that fail compilation
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/miri/tests/fail/erroneous_const.stderr b/src/tools/miri/tests/fail/erroneous_const.stderr
index c32ebf67a11..209c4a932dc 100644
--- a/src/tools/miri/tests/fail/erroneous_const.stderr
+++ b/src/tools/miri/tests/fail/erroneous_const.stderr
@@ -4,7 +4,7 @@ error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
 LL |     const VOID: ! = panic!();
    |                     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/erroneous_const.rs:LL:CC
    |
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
   --> $DIR/erroneous_const.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs
index a5bae36d92a..8905d739078 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs
@@ -1,4 +1,4 @@
-//@error-pattern: cannot be represented in target type `i32`
+//@error-in-other-file: cannot be represented in target type `i32`
 #![feature(portable_simd)]
 use std::simd::*;
 
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.rs b/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
index e394cce9a4f..5dd9bd8a685 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
@@ -1,4 +1,4 @@
-//@error-pattern: pointer to 1 byte starting at offset 9 is out-of-bounds
+//@error-in-other-file: pointer to 1 byte starting at offset 9 is out-of-bounds
 #![feature(portable_simd)]
 use std::simd::*;
 
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
index d2bc7339954..0a64478dc74 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
@@ -1,4 +1,4 @@
-//@error-pattern: pointer to 1 byte starting at offset 9 is out-of-bounds
+//@error-in-other-file: pointer to 1 byte starting at offset 9 is out-of-bounds
 #![feature(portable_simd)]
 use std::simd::*;
 
diff --git a/src/tools/miri/tests/fail/layout_cycle.rs b/src/tools/miri/tests/fail/layout_cycle.rs
index d050310bd80..3e0dd881db8 100644
--- a/src/tools/miri/tests/fail/layout_cycle.rs
+++ b/src/tools/miri/tests/fail/layout_cycle.rs
@@ -1,4 +1,4 @@
-//@error-pattern: a cycle occurred during layout computation
+//@error-in-other-file: a cycle occurred during layout computation
 //~^ ERROR: cycle detected when computing layout of
 
 use std::mem;
diff --git a/src/tools/miri/tests/fail/memleak.rs b/src/tools/miri/tests/fail/memleak.rs
index cbeb163b56c..984b44d6d40 100644
--- a/src/tools/miri/tests/fail/memleak.rs
+++ b/src/tools/miri/tests/fail/memleak.rs
@@ -1,4 +1,4 @@
-//@error-pattern: memory leaked
+//@error-in-other-file: memory leaked
 //@normalize-stderr-test: ".*│.*" -> "$$stripped$$"
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/memleak_no_backtrace.rs b/src/tools/miri/tests/fail/memleak_no_backtrace.rs
index 24d4a02df71..a1f8d9957ff 100644
--- a/src/tools/miri/tests/fail/memleak_no_backtrace.rs
+++ b/src/tools/miri/tests/fail/memleak_no_backtrace.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-disable-leak-backtraces
-//@error-pattern: the evaluated program leaked memory
+//@error-in-other-file: the evaluated program leaked memory
 //@normalize-stderr-test: ".*│.*" -> "$$stripped$$"
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/memleak_rc.rs b/src/tools/miri/tests/fail/memleak_rc.rs
index cf4671912ad..0927612d08e 100644
--- a/src/tools/miri/tests/fail/memleak_rc.rs
+++ b/src/tools/miri/tests/fail/memleak_rc.rs
@@ -1,4 +1,4 @@
-//@error-pattern: memory leaked
+//@error-in-other-file: memory leaked
 //@stderr-per-bitwidth
 //@normalize-stderr-test: ".*│.*" -> "$$stripped$$"
 
diff --git a/src/tools/miri/tests/fail/no_main.rs b/src/tools/miri/tests/fail/no_main.rs
index e2820504087..01b8c7bd66b 100644
--- a/src/tools/miri/tests/fail/no_main.rs
+++ b/src/tools/miri/tests/fail/no_main.rs
@@ -1,2 +1,2 @@
-//@error-pattern: miri can only run programs that have a main function
+//@error-in-other-file: miri can only run programs that have a main function
 #![no_main]
diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs
index c9501d90b3b..9378adb8609 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.rs
+++ b/src/tools/miri/tests/fail/panic/double_panic.rs
@@ -1,4 +1,4 @@
-//@error-pattern: the program aborted
+//@error-in-other-file: the program aborted
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
 //@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 5384f6f6716..77d5fc5d7ce 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -12,7 +12,8 @@ LL |     ABORT();
    = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `<Foo as std::ops::Drop>::drop`
   --> $DIR/double_panic.rs:LL:CC
    |
@@ -24,7 +25,7 @@ note: inside `main`
    |
 LL | }
    | ^
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/no_std.stderr b/src/tools/miri/tests/fail/panic/no_std.stderr
index 39ad0d268b9..f8307c0c23b 100644
--- a/src/tools/miri/tests/fail/panic/no_std.stderr
+++ b/src/tools/miri/tests/fail/panic/no_std.stderr
@@ -11,7 +11,7 @@ note: inside `start`
    |
 LL |     panic!("blarg I am dead")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.rs b/src/tools/miri/tests/fail/panic/panic_abort1.rs
index 00a01ce6e81..300bfa32ecb 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort1.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort1.rs
@@ -1,4 +1,4 @@
-//@error-pattern: the program aborted execution
+//@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
 //@compile-flags: -C panic=abort
diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
index d25dd7be635..d9303fd0d06 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
@@ -11,13 +11,14 @@ LL |                 ABORT();
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
 note: inside `main`
   --> $DIR/panic_abort1.rs:LL:CC
    |
 LL |     std::panic!("panicking from libstd");
    | ^
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.rs b/src/tools/miri/tests/fail/panic/panic_abort2.rs
index dee0de96703..5d691350577 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort2.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort2.rs
@@ -1,4 +1,4 @@
-//@error-pattern: the program aborted execution
+//@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
 //@compile-flags: -C panic=abort
diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
index f56d509a697..54cbc9b5f6d 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
@@ -18,7 +18,7 @@ note: inside `main`
    |
 LL |     std::panic!("{}-panicking from libstd", 42);
    | ^
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.rs b/src/tools/miri/tests/fail/panic/panic_abort3.rs
index a448aab3ea4..25afc315628 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort3.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort3.rs
@@ -1,4 +1,4 @@
-//@error-pattern: the program aborted execution
+//@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
 //@compile-flags: -C panic=abort
diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
index 43792f76993..64eea47b14b 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
@@ -18,7 +18,7 @@ note: inside `main`
    |
 LL |     core::panic!("panicking from libcore");
    | ^
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.rs b/src/tools/miri/tests/fail/panic/panic_abort4.rs
index 4995dad9d71..025b51a5cf5 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort4.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort4.rs
@@ -1,4 +1,4 @@
-//@error-pattern: the program aborted execution
+//@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
 //@compile-flags: -C panic=abort
diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
index 89e181bfb27..21beb100645 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
@@ -18,7 +18,7 @@ note: inside `main`
    |
 LL |     core::panic!("{}-panicking from libcore", 42);
    | ^
-   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/shims/fs/isolated_file.rs b/src/tools/miri/tests/fail/shims/fs/isolated_file.rs
index 9b664ffe52a..2f27e95297b 100644
--- a/src/tools/miri/tests/fail/shims/fs/isolated_file.rs
+++ b/src/tools/miri/tests/fail/shims/fs/isolated_file.rs
@@ -1,5 +1,5 @@
 //@ignore-target-windows: File handling is not implemented yet
-//@error-pattern: `open` not available when isolation is enabled
+//@error-in-other-file: `open` not available when isolation is enabled
 
 fn main() {
     let _file = std::fs::File::open("file.txt").unwrap();
diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs
index 4036dce5beb..a34df7c7fe3 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs
@@ -1,4 +1,4 @@
-//@error-pattern: /deallocating while item \[Unique for .*\] is strongly protected/
+//@error-in-other-file: /deallocating while item \[Unique for .*\] is strongly protected/
 
 fn inner(x: &mut i32, f: fn(&mut i32)) {
     // `f` may mutate, but it may not deallocate!
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs
index 8180e2f03a7..9126b7e8575 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs
@@ -1,7 +1,7 @@
 //! Test that drop_in_place mutably retags the entire place, even for a type that does not need
 //! dropping, ensuring among other things that it is writeable
 
-//@error-pattern: /retag .* for Unique permission .* only grants SharedReadOnly permission/
+//@error-in-other-file: /retag .* for Unique permission .* only grants SharedReadOnly permission/
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.rs
index 670dd4baad8..b2ec23bda02 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.rs
@@ -1,4 +1,4 @@
-//@error-pattern: /deallocation .* tag does not exist in the borrow stack/
+//@error-in-other-file: /deallocation .* tag does not exist in the borrow stack/
 use std::alloc::{alloc, dealloc, Layout};
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.rs b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.rs
index 1e44cc6c800..075efe49412 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.rs
@@ -1,4 +1,4 @@
-//@error-pattern: pointer to 4 bytes starting at offset 0 is out-of-bounds
+//@error-in-other-file: pointer to 4 bytes starting at offset 0 is out-of-bounds
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.rs b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.rs
index 6e90559a9ef..1b43daa9253 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.rs
@@ -1,4 +1,4 @@
-//@error-pattern: is a dangling pointer
+//@error-in-other-file: is a dangling pointer
 use std::ptr::NonNull;
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs
index c19bcb99cc1..1ae6740924c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.rs
@@ -1,4 +1,4 @@
-//@error-pattern: which is strongly protected
+//@error-in-other-file: which is strongly protected
 struct Newtype<'a>(&'a mut i32, i32);
 
 fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs
index 2bbe7122ec7..f106274b811 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.rs
@@ -1,4 +1,4 @@
-//@error-pattern: which is strongly protected
+//@error-in-other-file: which is strongly protected
 struct Newtype<'a>(&'a mut i32);
 
 fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs
index 77daa9c9811..fd51fa6468a 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-strict-provenance
-//@error-pattern: /retag .* tag does not exist in the borrow stack/
+//@error-in-other-file: /retag .* tag does not exist in the borrow stack/
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/tokio/sleep.rs b/src/tools/miri/tests/fail/tokio/sleep.rs
index 6fdfbc9913a..d96d778e6ca 100644
--- a/src/tools/miri/tests/fail/tokio/sleep.rs
+++ b/src/tools/miri/tests/fail/tokio/sleep.rs
@@ -1,6 +1,6 @@
 //@compile-flags: -Zmiri-permissive-provenance -Zmiri-backtrace=full
 //@only-target-x86_64-unknown-linux: support for tokio only on linux and x86
-//@error-pattern: returning ready events from epoll_wait is not yet implemented
+//@error-in-other-file: returning ready events from epoll_wait is not yet implemented
 //@normalize-stderr-test: " += note:.*\n" -> ""
 
 use tokio::time::{sleep, Duration, Instant};
diff --git a/src/tools/miri/tests/fail/tree-borrows/strongly-protected.rs b/src/tools/miri/tests/fail/tree-borrows/strongly-protected.rs
index a68efea890c..484c7c3bbff 100644
--- a/src/tools/miri/tests/fail/tree-borrows/strongly-protected.rs
+++ b/src/tools/miri/tests/fail/tree-borrows/strongly-protected.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-tree-borrows
-//@error-pattern: /deallocation through .* is forbidden/
+//@error-in-other-file: /deallocation through .* is forbidden/
 
 fn inner(x: &mut i32, f: fn(&mut i32)) {
     // `f` may mutate, but it may not deallocate!
diff --git a/src/tools/miri/tests/fail/tree-borrows/strongly-protected.stderr b/src/tools/miri/tests/fail/tree-borrows/strongly-protected.stderr
index 97088d5854c..071b216ff98 100644
--- a/src/tools/miri/tests/fail/tree-borrows/strongly-protected.stderr
+++ b/src/tools/miri/tests/fail/tree-borrows/strongly-protected.stderr
@@ -17,6 +17,12 @@ help: the strongly protected tag <TAG> was created here, in the initial state Re
    |
 LL | fn inner(x: &mut i32, f: fn(&mut i32)) {
    |          ^
+help: the strongly protected tag <TAG> then transitioned from Reserved to Active due to a child write access at offsets [0x0..0x4]
+  --> $DIR/strongly-protected.rs:LL:CC
+   |
+LL |         drop(unsafe { Box::from_raw(raw) });
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: this corresponds to an activation
    = note: BACKTRACE (of the first span):
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
index 8a40e527f0e..d8cab68ac5d 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
@@ -13,7 +13,7 @@ struct PartialDrop {
     b: u8,
 }
 
-//@error-pattern: /alignment 2 is required/
+//@error-in-other-file: /alignment 2 is required/
 fn main() {
     unsafe {
         // Create an unaligned pointer
diff --git a/src/tools/miri/tests/fail/uninit_buffer.rs b/src/tools/miri/tests/fail/uninit_buffer.rs
index d21371225e5..8819c53a4f9 100644
--- a/src/tools/miri/tests/fail/uninit_buffer.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer.rs
@@ -1,4 +1,4 @@
-//@error-pattern: memory is uninitialized at [0x4..0x10]
+//@error-in-other-file: memory is uninitialized at [0x4..0x10]
 
 use std::alloc::{alloc, dealloc, Layout};
 use std::slice::from_raw_parts;
diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
index 170bc6e1ed1..e788c079cb4 100644
--- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
@@ -1,4 +1,4 @@
-//@error-pattern: memory is uninitialized at [0x4..0x8]
+//@error-in-other-file: memory is uninitialized at [0x4..0x8]
 //@normalize-stderr-test: "a[0-9]+" -> "ALLOC"
 #![feature(strict_provenance)]
 
diff --git a/src/tools/miri/tests/panic/panic1.stderr b/src/tools/miri/tests/panic/panic1.stderr
index 15834d58bc6..0f4535e6792 100644
--- a/src/tools/miri/tests/panic/panic1.stderr
+++ b/src/tools/miri/tests/panic/panic1.stderr
@@ -1,9 +1,11 @@
 thread 'main' panicked at 'panicking from libstd', $DIR/panic1.rs:LL:CC
 stack backtrace:
-   0: std::rt::begin_panic
+   0: std::panicking::begin_panic_handler
  at RUSTLIB/std/src/panicking.rs:LL:CC
-   1: main
+   1: std::rt::panic_fmt
+ at RUSTLIB/core/src/panicking.rs:LL:CC
+   2: main
  at $DIR/panic1.rs:LL:CC
-   2: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
+   3: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
  at RUSTLIB/core/src/ops/function.rs:LL:CC
 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
index 82ef59427ae..68504cb1c79 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
@@ -101,7 +101,6 @@ fn test_posix_realpath_errors() {
 
 #[cfg(target_os = "linux")]
 fn test_posix_fadvise() {
-    use std::convert::TryInto;
     use std::io::Write;
 
     let path = tmp().join("miri_test_libc_posix_fadvise.txt");
diff --git a/src/tools/miri/tests/pass/0weak_memory_consistency.rs b/src/tools/miri/tests/pass/0weak_memory_consistency.rs
index 3a531eede67..abfe3b0adeb 100644
--- a/src/tools/miri/tests/pass/0weak_memory_consistency.rs
+++ b/src/tools/miri/tests/pass/0weak_memory_consistency.rs
@@ -116,11 +116,13 @@ fn test_message_passing() {
 
     #[rustfmt::skip]
     let j1 = spawn(move || {
+        let x = x; // avoid field capturing
         unsafe { *x.0 = 1 }; // -----------------------------------------+
         y.store(1, Release); // ---------------------+                   |
     }); //                                           |                   |
     #[rustfmt::skip] //                              |synchronizes-with  | happens-before
     let j2 = spawn(move || { //                      |                   |
+        let x = x; // avoid field capturing          |                   |
         acquires_value(&y, 1); // <------------------+                   |
         unsafe { *x.0 } // <---------------------------------------------+
     });
diff --git a/src/tools/miri/tests/pass/concurrency/data_race.rs b/src/tools/miri/tests/pass/concurrency/data_race.rs
index 4e3c99058a0..d31420380a5 100644
--- a/src/tools/miri/tests/pass/concurrency/data_race.rs
+++ b/src/tools/miri/tests/pass/concurrency/data_race.rs
@@ -17,12 +17,14 @@ fn test_fence_sync() {
     let evil_ptr = EvilSend(ptr);
 
     let j1 = spawn(move || {
+        let evil_ptr = evil_ptr; // avoid field capturing
         unsafe { *evil_ptr.0 = 1 };
         fence(Ordering::Release);
         SYNC.store(1, Ordering::Relaxed)
     });
 
     let j2 = spawn(move || {
+        let evil_ptr = evil_ptr; // avoid field capturing
         if SYNC.load(Ordering::Relaxed) == 1 {
             fence(Ordering::Acquire);
             unsafe { *evil_ptr.0 }
@@ -40,10 +42,10 @@ fn test_multiple_reads() {
     let ptr = &mut var as *mut u32;
     let evil_ptr = EvilSend(ptr);
 
-    let j1 = spawn(move || unsafe { *evil_ptr.0 });
-    let j2 = spawn(move || unsafe { *evil_ptr.0 });
-    let j3 = spawn(move || unsafe { *evil_ptr.0 });
-    let j4 = spawn(move || unsafe { *evil_ptr.0 });
+    let j1 = spawn(move || unsafe { *{ evil_ptr }.0 });
+    let j2 = spawn(move || unsafe { *{ evil_ptr }.0 });
+    let j3 = spawn(move || unsafe { *{ evil_ptr }.0 });
+    let j4 = spawn(move || unsafe { *{ evil_ptr }.0 });
 
     assert_eq!(j1.join().unwrap(), 42);
     assert_eq!(j2.join().unwrap(), 42);
@@ -63,6 +65,7 @@ pub fn test_rmw_no_block() {
 
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
         });
@@ -73,7 +76,10 @@ pub fn test_rmw_no_block() {
             }
         });
 
-        let j3 = spawn(move || if SYNC.load(Ordering::Acquire) == 2 { *c.0 } else { 0 });
+        let j3 = spawn(move || {
+            let c = c; // avoid field capturing
+            if SYNC.load(Ordering::Acquire) == 2 { *c.0 } else { 0 }
+        });
 
         j1.join().unwrap();
         j2.join().unwrap();
@@ -91,11 +97,15 @@ pub fn test_simple_release() {
 
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 1;
             SYNC.store(1, Ordering::Release);
         });
 
-        let j2 = spawn(move || if SYNC.load(Ordering::Acquire) == 1 { *c.0 } else { 0 });
+        let j2 = spawn(move || {
+            let c = c; // avoid field capturing
+            if SYNC.load(Ordering::Acquire) == 1 { *c.0 } else { 0 }
+        });
 
         j1.join().unwrap();
         assert_eq!(j2.join().unwrap(), 1); // relies on thread 2 going last
diff --git a/src/tools/miri/tests/pass/concurrency/disable_data_race_detector.rs b/src/tools/miri/tests/pass/concurrency/disable_data_race_detector.rs
index d71e51b0384..049b5e7f498 100644
--- a/src/tools/miri/tests/pass/concurrency/disable_data_race_detector.rs
+++ b/src/tools/miri/tests/pass/concurrency/disable_data_race_detector.rs
@@ -14,10 +14,12 @@ pub fn main() {
     let c = EvilSend(b);
     unsafe {
         let j1 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 32;
         });
 
         let j2 = spawn(move || {
+            let c = c; // avoid field capturing
             *c.0 = 64; // Data race (but not detected as the detector is disabled)
         });
 
diff --git a/src/tools/miri/tests/pass/concurrency/sync.rs b/src/tools/miri/tests/pass/concurrency/sync.rs
index 3bd1e542407..dccc9d104dd 100644
--- a/src/tools/miri/tests/pass/concurrency/sync.rs
+++ b/src/tools/miri/tests/pass/concurrency/sync.rs
@@ -201,8 +201,10 @@ fn park_timeout() {
     thread::park_timeout(Duration::from_millis(200));
     // Normally, waiting in park/park_timeout may spuriously wake up early, but we
     // know Miri's timed synchronization primitives do not do that.
-
-    assert!((200..1000).contains(&start.elapsed().as_millis()));
+    // We allow much longer sleeps as well since the macOS GHA runners seem very oversubscribed
+    // and sometimes just pause for 1 second or more.
+    let elapsed = start.elapsed();
+    assert!((200..2000).contains(&elapsed.as_millis()), "bad sleep time: {elapsed:?}");
 }
 
 fn park_unpark() {
@@ -219,8 +221,10 @@ fn park_unpark() {
     thread::park();
     // Normally, waiting in park/park_timeout may spuriously wake up early, but we
     // know Miri's timed synchronization primitives do not do that.
-
-    assert!((200..1000).contains(&start.elapsed().as_millis()));
+    // We allow much longer sleeps as well since the macOS GHA runners seem very oversubscribed
+    // and sometimes just pause for 1 second or more.
+    let elapsed = start.elapsed();
+    assert!((200..2000).contains(&elapsed.as_millis()), "bad sleep time: {elapsed:?}");
 
     t2.join().unwrap();
 }
diff --git a/src/tools/miri/tests/pass/concurrency/thread_locals.rs b/src/tools/miri/tests/pass/concurrency/thread_locals.rs
index 13c11b55775..fc4c8a283dd 100644
--- a/src/tools/miri/tests/pass/concurrency/thread_locals.rs
+++ b/src/tools/miri/tests/pass/concurrency/thread_locals.rs
@@ -42,6 +42,7 @@ fn main() {
     };
 
     thread::spawn(move || unsafe {
+        let ptr = ptr; // avoid field capturing
         assert_eq!(*ptr.0, 5);
         assert_eq!(A, 0);
         assert_eq!(B, 0);
diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs b/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs
index d89320bfe59..3b27af9094c 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs
+++ b/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs
@@ -44,6 +44,8 @@ fn all_shared() {
     // waiters
     for i in 0..5 {
         handles.push(thread::spawn(move || {
+            let condvar_ptr = condvar_ptr; // avoid field capture
+            let lock_ptr = lock_ptr; // avoid field capture
             unsafe {
                 AcquireSRWLockShared(lock_ptr.0);
             }
@@ -71,6 +73,7 @@ fn all_shared() {
     // readers
     for i in 0..5 {
         handles.push(thread::spawn(move || {
+            let lock_ptr = lock_ptr; // avoid field capture
             unsafe {
                 AcquireSRWLockShared(lock_ptr.0);
             }
@@ -111,6 +114,8 @@ fn shared_sleep_and_exclusive_lock() {
     let mut waiters = Vec::with_capacity(5);
     for i in 0..5 {
         waiters.push(thread::spawn(move || {
+            let lock_ptr = lock_ptr; // avoid field capture
+            let condvar_ptr = condvar_ptr; // avoid field capture
             unsafe {
                 AcquireSRWLockShared(lock_ptr.0);
             }
@@ -170,6 +175,8 @@ fn exclusive_sleep_and_shared_lock() {
     let mut handles = Vec::with_capacity(10);
     for i in 0..5 {
         handles.push(thread::spawn(move || {
+            let lock_ptr = lock_ptr; // avoid field capture
+            let condvar_ptr = condvar_ptr; // avoid field capture
             unsafe {
                 AcquireSRWLockExclusive(lock_ptr.0);
             }
@@ -193,6 +200,7 @@ fn exclusive_sleep_and_shared_lock() {
 
     for i in 0..5 {
         handles.push(thread::spawn(move || {
+            let lock_ptr = lock_ptr; // avoid field capture
             unsafe {
                 AcquireSRWLockShared(lock_ptr.0);
             }
diff --git a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs b/src/tools/miri/tests/pass/concurrency/windows_init_once.rs
index 4eb88379620..b2412f7dbb0 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs
+++ b/src/tools/miri/tests/pass/concurrency/windows_init_once.rs
@@ -66,6 +66,7 @@ fn block_until_complete() {
     let init_once_ptr = SendPtr(&mut init_once);
 
     let waiter = move || unsafe {
+        let init_once_ptr = init_once_ptr; // avoid field capture
         let mut pending = 0;
 
         assert_eq!(InitOnceBeginInitialize(init_once_ptr.0, 0, &mut pending, null_mut()), TRUE);
@@ -102,6 +103,7 @@ fn retry_on_fail() {
     let init_once_ptr = SendPtr(&mut init_once);
 
     let waiter = move || unsafe {
+        let init_once_ptr = init_once_ptr; // avoid field capture
         let mut pending = 0;
 
         assert_eq!(InitOnceBeginInitialize(init_once_ptr.0, 0, &mut pending, null_mut()), TRUE);
@@ -146,6 +148,8 @@ fn no_data_race_after_complete() {
     let place_ptr = SendPtr(&mut place);
 
     let reader = thread::spawn(move || unsafe {
+        let init_once_ptr = init_once_ptr; // avoid field capture
+        let place_ptr = place_ptr; // avoid field capture
         let mut pending = 0;
 
         // this doesn't block because reader only executes after `InitOnceComplete` is called
diff --git a/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs b/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs
index 986e2b8cc10..5da5497f982 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs
+++ b/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs
@@ -22,10 +22,8 @@ fn main() {
     })
     .into_raw_handle() as usize;
 
-    let waiter = move || {
-        unsafe {
-            assert_eq!(WaitForSingleObject(blocker, INFINITE), 0);
-        }
+    let waiter = move || unsafe {
+        assert_eq!(WaitForSingleObject(blocker, INFINITE), 0);
     };
 
     let waiter1 = thread::spawn(waiter);
diff --git a/src/tools/miri/tests/pass/panic/catch_panic.rs b/src/tools/miri/tests/pass/panic/catch_panic.rs
index 5d57df4e52b..1b00f7cea30 100644
--- a/src/tools/miri/tests/pass/panic/catch_panic.rs
+++ b/src/tools/miri/tests/pass/panic/catch_panic.rs
@@ -49,13 +49,12 @@ fn main() {
 
     // Std panics
     test(None, |_old_val| std::panic!("Hello from panic: std"));
-    test(None, |old_val| std::panic!(format!("Hello from panic: {:?}", old_val)));
+    test(None, |old_val| std::panic::panic_any(format!("Hello from panic: {:?}", old_val)));
     test(None, |old_val| std::panic!("Hello from panic: {:?}", old_val));
-    test(None, |_old_val| std::panic!(1337));
+    test(None, |_old_val| std::panic::panic_any(1337));
 
     // Core panics
     test(None, |_old_val| core::panic!("Hello from panic: core"));
-    test(None, |old_val| core::panic!(&format!("Hello from panic: {:?}", old_val)));
     test(None, |old_val| core::panic!("Hello from panic: {:?}", old_val));
 
     // Built-in panics; also make sure the message is right.
diff --git a/src/tools/miri/tests/pass/panic/catch_panic.stderr b/src/tools/miri/tests/pass/panic/catch_panic.stderr
index 0ced5588cc1..f43434582a2 100644
--- a/src/tools/miri/tests/pass/panic/catch_panic.stderr
+++ b/src/tools/miri/tests/pass/panic/catch_panic.stderr
@@ -11,8 +11,6 @@ thread 'main' panicked at 'Hello from panic: core', $DIR/catch_panic.rs:LL:CC
 Caught panic message (&str): Hello from panic: core
 thread 'main' panicked at 'Hello from panic: 5', $DIR/catch_panic.rs:LL:CC
 Caught panic message (String): Hello from panic: 5
-thread 'main' panicked at 'Hello from panic: 6', $DIR/catch_panic.rs:LL:CC
-Caught panic message (String): Hello from panic: 6
 thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 4', $DIR/catch_panic.rs:LL:CC
 Caught panic message (String): index out of bounds: the len is 3 but the index is 4
 thread 'main' panicked at 'attempt to divide by zero', $DIR/catch_panic.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/panic/concurrent-panic.rs b/src/tools/miri/tests/pass/panic/concurrent-panic.rs
index 776bc2057f3..7cc1e2a973f 100644
--- a/src/tools/miri/tests/pass/panic/concurrent-panic.rs
+++ b/src/tools/miri/tests/pass/panic/concurrent-panic.rs
@@ -57,7 +57,7 @@ fn main() {
         let t2_started_pair = t2_started_pair.clone();
         let block_on_drop = BlockOnDrop::new(t1);
         spawn(move || {
-            let _ = block_on_drop;
+            let _capture = block_on_drop;
 
             let (mutex, condvar) = &*t2_started_pair;
             *mutex.lock().unwrap() = true;
diff --git a/src/tools/miri/tests/pass/sysroot.rs b/src/tools/miri/tests/pass/sysroot.rs
new file mode 100644
index 00000000000..2c80e5bbd84
--- /dev/null
+++ b/src/tools/miri/tests/pass/sysroot.rs
@@ -0,0 +1,9 @@
+//! Just check that some things are available in the sysroot.
+#![feature(test)]
+#![allow(unused)]
+
+extern crate proc_macro;
+extern crate std;
+extern crate test;
+
+fn main() {}