about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2025-09-17 05:00:44 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2025-09-17 05:00:44 +0000
commit1672251dad4ffe70c95dd233b2c044045acd2fd3 (patch)
treec247b3719ca59935abd7e225e202cf8609bcb48c /src/tools
parent06e881042d3f58fdb60fde58de5bf112b2184b11 (diff)
parent3f1552a273e43e15f6ed240d00e1efdd6a53e65e (diff)
Merge ref '3f1552a273e4' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: 3f1552a273e43e15f6ed240d00e1efdd6a53e65e
Filtered ref: fbfa7b30a3ad5abd6a5db7e3ef15adc8da1ecc37
Upstream diff: https://github.com/rust-lang/rust/compare/9d82de19dfae60e55c291f5f28e28cfc2c1b9630...3f1552a273e43e15f6ed240d00e1efdd6a53e65e

This merge was created using https://github.com/rust-lang/josh-sync.
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/compiletest/src/common.rs4
-rw-r--r--src/tools/compiletest/src/directives.rs9
-rw-r--r--src/tools/compiletest/src/directives/needs.rs13
-rw-r--r--src/tools/compiletest/src/directives/tests.rs8
-rw-r--r--src/tools/compiletest/src/executor.rs14
-rw-r--r--src/tools/compiletest/src/lib.rs39
-rw-r--r--src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr2
-rw-r--r--src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs18
-rw-r--r--src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr15
-rw-r--r--src/tools/miri/tests/fail/validity/nonzero.stderr2
-rw-r--r--src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs19
-rw-r--r--src/tools/opt-dist/src/training.rs1
-rw-r--r--src/tools/tidy/src/deps.rs177
-rw-r--r--src/tools/tidy/src/extdeps.rs12
21 files changed, 276 insertions, 71 deletions
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 143ccdcb9e5..6da102b1b5f 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -203,6 +203,10 @@ impl CodegenBackend {
             Self::Llvm => "llvm",
         }
     }
+
+    pub fn is_llvm(self) -> bool {
+        matches!(self, Self::Llvm)
+    }
 }
 
 /// Configuration for `compiletest` *per invocation*.
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 857953072c4..1277fd225eb 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -1446,6 +1446,7 @@ pub(crate) fn make_test_description<R: Read>(
     cache: &DirectivesCache,
     name: String,
     path: &Utf8Path,
+    filterable_path: &Utf8Path,
     src: R,
     test_revision: Option<&str>,
     poisoned: &mut bool,
@@ -1520,7 +1521,13 @@ pub(crate) fn make_test_description<R: Read>(
         _ => ShouldPanic::No,
     };
 
-    CollectedTestDesc { name, ignore, ignore_message, should_panic }
+    CollectedTestDesc {
+        name,
+        filterable_path: filterable_path.to_owned(),
+        ignore,
+        ignore_message,
+        should_panic,
+    }
 }
 
 fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision {
diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs
index ee46f4c70cb..3b7a9478717 100644
--- a/src/tools/compiletest/src/directives/needs.rs
+++ b/src/tools/compiletest/src/directives/needs.rs
@@ -81,8 +81,8 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-enzyme",
-            condition: config.has_enzyme,
-            ignore_reason: "ignored when LLVM Enzyme is disabled",
+            condition: config.has_enzyme && config.default_codegen_backend.is_llvm(),
+            ignore_reason: "ignored when LLVM Enzyme is disabled or LLVM is not the default codegen backend",
         },
         Need {
             name: "needs-run-enabled",
@@ -161,8 +161,8 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-llvm-zstd",
-            condition: cache.llvm_zstd,
-            ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
+            condition: cache.llvm_zstd && config.default_codegen_backend.is_llvm(),
+            ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression or LLVM is not the default codegen backend",
         },
         Need {
             name: "needs-rustc-debug-assertions",
@@ -279,7 +279,10 @@ pub(super) fn handle_needs(
 
     // Handled elsewhere.
     if name == "needs-llvm-components" {
-        return IgnoreDecision::Continue;
+        if config.default_codegen_backend.is_llvm() {
+            return IgnoreDecision::Continue;
+        }
+        return IgnoreDecision::Ignore { reason: "LLVM specific test".into() };
     }
 
     let mut found_valid = false;
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs
index 33a02eb29fd..16cf76be9a5 100644
--- a/src/tools/compiletest/src/directives/tests.rs
+++ b/src/tools/compiletest/src/directives/tests.rs
@@ -14,6 +14,7 @@ fn make_test_description<R: Read>(
     config: &Config,
     name: String,
     path: &Utf8Path,
+    filterable_path: &Utf8Path,
     src: R,
     revision: Option<&str>,
 ) -> CollectedTestDesc {
@@ -24,6 +25,7 @@ fn make_test_description<R: Read>(
         &cache,
         name,
         path,
+        filterable_path,
         src,
         revision,
         &mut poisoned,
@@ -221,7 +223,7 @@ fn parse_rs(config: &Config, contents: &str) -> EarlyProps {
 fn check_ignore(config: &Config, contents: &str) -> bool {
     let tn = String::new();
     let p = Utf8Path::new("a.rs");
-    let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None);
+    let d = make_test_description(&config, tn, p, p, std::io::Cursor::new(contents), None);
     d.ignore
 }
 
@@ -231,9 +233,9 @@ fn should_fail() {
     let tn = String::new();
     let p = Utf8Path::new("a.rs");
 
-    let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
+    let d = make_test_description(&config, tn.clone(), p, p, std::io::Cursor::new(""), None);
     assert_eq!(d.should_panic, ShouldPanic::No);
-    let d = make_test_description(&config, tn, p, std::io::Cursor::new("//@ should-fail"), None);
+    let d = make_test_description(&config, tn, p, p, std::io::Cursor::new("//@ should-fail"), None);
     assert_eq!(d.should_panic, ShouldPanic::Yes);
 }
 
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index b0dc24798b6..c8e13d44573 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -12,6 +12,8 @@ use std::num::NonZero;
 use std::sync::{Arc, Mutex, mpsc};
 use std::{env, hint, io, mem, panic, thread};
 
+use camino::Utf8PathBuf;
+
 use crate::common::{Config, TestPaths};
 use crate::output_capture::{self, ConsoleOut};
 use crate::panic_hook;
@@ -293,8 +295,15 @@ fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest>
     let mut filtered = tests;
 
     let matches_filter = |test: &CollectedTest, filter_str: &str| {
-        let test_name = &test.desc.name;
-        if opts.filter_exact { test_name == filter_str } else { test_name.contains(filter_str) }
+        if opts.filter_exact {
+            // When `--exact` is used we must use `filterable_path` to get
+            // reasonable filtering behavior.
+            test.desc.filterable_path.as_str() == filter_str
+        } else {
+            // For compatibility we use the name (which includes the full path)
+            // if `--exact` is not used.
+            test.desc.name.contains(filter_str)
+        }
     };
 
     // Remove tests that don't match the test filter
@@ -339,6 +348,7 @@ pub(crate) struct CollectedTest {
 /// Information that was historically needed to create a libtest `TestDesc`.
 pub(crate) struct CollectedTestDesc {
     pub(crate) name: String,
+    pub(crate) filterable_path: Utf8PathBuf,
     pub(crate) ignore: bool,
     pub(crate) ignore_message: Option<Cow<'static, str>>,
     pub(crate) should_panic: ShouldPanic,
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index f647f96a9bf..ce2a3d4b5fb 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -317,11 +317,17 @@ pub fn parse_config(args: Vec<String>) -> Config {
             .free
             .iter()
             .map(|f| {
+                // Here `f` is relative to `./tests/run-make`. So if you run
+                //
+                //   ./x test tests/run-make/crate-loading
+                //
+                //  then `f` is "crate-loading".
                 let path = Utf8Path::new(f);
                 let mut iter = path.iter().skip(1);
 
-                // We skip the test folder and check if the user passed `rmake.rs`.
                 if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() {
+                    // Strip the "rmake.rs" suffix. For example, if `f` is
+                    // "crate-loading/rmake.rs" then this gives us "crate-loading".
                     path.parent().unwrap().to_string()
                 } else {
                     f.to_string()
@@ -329,6 +335,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             })
             .collect::<Vec<_>>()
     } else {
+        // Note that the filters are relative to the root dir of the different test
+        // suites. For example, with:
+        //
+        //   ./x test tests/ui/lint/unused
+        //
+        // the filter is "lint/unused".
         matches.free.clone()
     };
     let compare_mode = matches.opt_str("compare-mode").map(|s| {
@@ -472,7 +484,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             let value = matches
                 .opt_str("new-output-capture")
                 .or_else(|| env::var("COMPILETEST_NEW_OUTPUT_CAPTURE").ok())
-                .unwrap_or_else(|| "off".to_owned());
+                .unwrap_or_else(|| "on".to_owned());
             parse_bool_option(&value)
                 .unwrap_or_else(|| panic!("unknown `--new-output-capture` value `{value}` given"))
         },
@@ -911,7 +923,8 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
     collector.tests.extend(revisions.into_iter().map(|revision| {
         // Create a test name and description to hand over to the executor.
         let src_file = fs::File::open(&test_path).expect("open test file to parse ignores");
-        let test_name = make_test_name(&cx.config, testpaths, revision);
+        let (test_name, filterable_path) =
+            make_test_name_and_filterable_path(&cx.config, testpaths, revision);
         // Create a description struct for the test/revision.
         // This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
         // because they historically needed to set the libtest ignored flag.
@@ -920,6 +933,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
             &cx.cache,
             test_name,
             &test_path,
+            &filterable_path,
             src_file,
             revision,
             &mut collector.poisoned,
@@ -1072,7 +1086,11 @@ impl Stamp {
 }
 
 /// Creates a name for this test/revision that can be handed over to the executor.
-fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String {
+fn make_test_name_and_filterable_path(
+    config: &Config,
+    testpaths: &TestPaths,
+    revision: Option<&str>,
+) -> (String, Utf8PathBuf) {
     // Print the name of the file, relative to the sources root.
     let path = testpaths.file.strip_prefix(&config.src_root).unwrap();
     let debugger = match config.debugger {
@@ -1084,14 +1102,23 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
         None => String::new(),
     };
 
-    format!(
+    let name = format!(
         "[{}{}{}] {}{}",
         config.mode,
         debugger,
         mode_suffix,
         path,
         revision.map_or("".to_string(), |rev| format!("#{}", rev))
-    )
+    );
+
+    // `path` is the full path from the repo root like, `tests/ui/foo/bar.rs`.
+    // Filtering is applied without the `tests/ui/` part, so strip that off.
+    // First strip off "tests" to make sure we don't have some unexpected path.
+    let mut filterable_path = path.strip_prefix("tests").unwrap().to_owned();
+    // Now strip off e.g. "ui" or "run-make" component.
+    filterable_path = filterable_path.components().skip(1).collect();
+
+    (name, filterable_path)
 }
 
 /// Checks that test discovery didn't find any tests whose name stem is a prefix
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
index dd7dae9cecf..d907c5de797 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
@@ -1,4 +1,6 @@
 //@revisions: stack tree
+// Ensure this even hits the aliasing model
+//@compile-flags: -Zmiri-disable-validation
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@error-in-other-file: pointer not dereferenceable
 
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs
index 5c947e64142..b54f27bb8b2 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs
@@ -1,4 +1,6 @@
 //@revisions: stack tree
+// Ensure this even hits the aliasing model
+//@compile-flags: -Zmiri-disable-validation
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@error-in-other-file: is a dangling pointer
 use std::ptr::NonNull;
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr
index d52143500c4..7c4fe748701 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr
@@ -11,7 +11,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8]
    |
 LL |     let ret = unsafe { &(*xraw).1 };
    |                        ^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
+help: <TAG> was later invalidated at offsets [0x4..0x8] by a write access
   --> tests/fail/both_borrows/return_invalid_shr.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr
index ee0f313d980..a8e3553aae2 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Frozen
    |
 LL |     let ret = unsafe { &(*xraw).1 };
    |                        ^^^^^^^^^^
-help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
   --> tests/fail/both_borrows/return_invalid_shr.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
index d66c8eeb1af..8411437ea4c 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8]
    |
 LL |     let ret = Some(unsafe { &(*xraw).1 });
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
+help: <TAG> was later invalidated at offsets [0x4..0x8] by a write access
   --> tests/fail/both_borrows/return_invalid_shr_option.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
index 16110e5b062..39da45ad6db 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Frozen
    |
 LL |     let ret = Some(unsafe { &(*xraw).1 });
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
   --> tests/fail/both_borrows/return_invalid_shr_option.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
index 727b52ec729..a7c422aa73f 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8]
    |
 LL |     let ret = (unsafe { &(*xraw).1 },);
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
+help: <TAG> was later invalidated at offsets [0x4..0x8] by a write access
   --> tests/fail/both_borrows/return_invalid_shr_tuple.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
index f93698f570e..66b03e57905 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Frozen
    |
 LL |     let ret = (unsafe { &(*xraw).1 },);
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
-help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
   --> tests/fail/both_borrows/return_invalid_shr_tuple.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs
new file mode 100644
index 00000000000..8d7b1946242
--- /dev/null
+++ b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs
@@ -0,0 +1,18 @@
+//! This is like `pass/overlapping_assignment_aggregate_scalar.rs` but with a non-scalar
+//! type, and that makes it definite UB.
+#![feature(custom_mir, core_intrinsics)]
+#![allow(internal_features)]
+
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime")]
+fn main() {
+    mir! {
+        let _1: ([u8; 1],);
+        {
+            _1.0 = [0_u8; 1];
+            _1 = (_1.0, ); //~ERROR: overlapping ranges
+            Return()
+        }
+    }
+}
diff --git a/src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr
new file mode 100644
index 00000000000..f2a6d326b71
--- /dev/null
+++ b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
+  --> tests/fail/overlapping_assignment_aggregate.rs:LL:CC
+   |
+LL |             _1 = (_1.0, );
+   |             ^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |
+   = 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 `main` at tests/fail/overlapping_assignment_aggregate.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/validity/nonzero.stderr b/src/tools/miri/tests/fail/validity/nonzero.stderr
index 0c3a35d6b9f..7be3ef46639 100644
--- a/src/tools/miri/tests/fail/validity/nonzero.stderr
+++ b/src/tools/miri/tests/fail/validity/nonzero.stderr
@@ -2,7 +2,7 @@ error: Undefined Behavior: constructing invalid value: encountered 0, but expect
   --> tests/fail/validity/nonzero.rs:LL:CC
    |
 LL |     let _x = Some(unsafe { NonZero(0) });
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |                            ^^^^^^^^^^ Undefined Behavior occurred here
    |
    = 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
diff --git a/src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs b/src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs
new file mode 100644
index 00000000000..0cb2f764242
--- /dev/null
+++ b/src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs
@@ -0,0 +1,19 @@
+#![feature(custom_mir, core_intrinsics)]
+#![allow(internal_features)]
+
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime")]
+fn main() {
+    mir! {
+        let _1: (u8,);
+        {
+            _1.0 = 0_u8;
+            // This is a scalar type, so overlap is (for now) not UB.
+            // However, we used to treat such overlapping assignments incorrectly
+            // (see <https://github.com/rust-lang/rust/issues/146383#issuecomment-3273224645>).
+            _1 = (_1.0, );
+            Return()
+        }
+    }
+}
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 4f9352d11b1..b3e95e087e3 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -39,7 +39,6 @@ fn init_compiler_benchmarks(
         "--exact-match",
         crates.join(",").as_str(),
     ])
-    .env("RUST_LOG", "collector=debug")
     .env("RUSTC", env.rustc_stage_0().as_str())
     .env("RUSTC_BOOTSTRAP", "1")
     .workdir(&env.rustc_perf_dir());
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index a9804761400..568ec0c1198 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -48,40 +48,116 @@ const LICENSES: &[&str] = &[
 
 type ExceptionList = &'static [(&'static str, &'static str)];
 
+#[derive(Clone, Copy)]
+pub(crate) struct WorkspaceInfo<'a> {
+    /// Path to the directory containing the workspace root Cargo.toml file.
+    pub(crate) path: &'a str,
+    /// The list of license exceptions.
+    pub(crate) exceptions: ExceptionList,
+    /// Optionally:
+    /// * A list of crates for which dependencies need to be explicitly allowed.
+    /// * The list of allowed dependencies.
+    /// * The source code location of the allowed dependencies list
+    crates_and_deps: Option<(&'a [&'a str], &'a [&'a str], ListLocation)>,
+    /// Submodules required for the workspace
+    pub(crate) submodules: &'a [&'a str],
+}
+
 /// The workspaces to check for licensing and optionally permitted dependencies.
-///
-/// Each entry consists of a tuple with the following elements:
-///
-/// * The path to the workspace root Cargo.toml file.
-/// * The list of license exceptions.
-/// * Optionally a tuple of:
-///     * A list of crates for which dependencies need to be explicitly allowed.
-///     * The list of allowed dependencies.
-/// * Submodules required for the workspace.
 // FIXME auto detect all cargo workspaces
-pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, &[&str])] = &[
+pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[
     // The root workspace has to be first for check_rustfix to work.
-    (".", EXCEPTIONS, Some((&["rustc-main"], PERMITTED_RUSTC_DEPENDENCIES)), &[]),
-    ("library", EXCEPTIONS_STDLIB, Some((&["sysroot"], PERMITTED_STDLIB_DEPENDENCIES)), &[]),
-    // Outside of the alphabetical section because rustfmt formats it using multiple lines.
-    (
-        "compiler/rustc_codegen_cranelift",
-        EXCEPTIONS_CRANELIFT,
-        Some((&["rustc_codegen_cranelift"], PERMITTED_CRANELIFT_DEPENDENCIES)),
-        &[],
-    ),
-    // tidy-alphabetical-start
-    ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None, &[]),
-    ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None, &[]),
-    ("src/tools/cargo", EXCEPTIONS_CARGO, None, &["src/tools/cargo"]),
-    //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
-    //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
-    ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]),
-    ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
-    ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
-    ("src/tools/test-float-parse", EXCEPTIONS, None, &[]),
-    ("tests/run-make-cargo/uefi-qemu/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None, &[]),
-    // tidy-alphabetical-end
+    WorkspaceInfo {
+        path: ".",
+        exceptions: EXCEPTIONS,
+        crates_and_deps: Some((
+            &["rustc-main"],
+            PERMITTED_RUSTC_DEPENDENCIES,
+            PERMITTED_RUSTC_DEPS_LOCATION,
+        )),
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "library",
+        exceptions: EXCEPTIONS_STDLIB,
+        crates_and_deps: Some((
+            &["sysroot"],
+            PERMITTED_STDLIB_DEPENDENCIES,
+            PERMITTED_STDLIB_DEPS_LOCATION,
+        )),
+        submodules: &[],
+    },
+    {
+        WorkspaceInfo {
+            path: "compiler/rustc_codegen_cranelift",
+            exceptions: EXCEPTIONS_CRANELIFT,
+            crates_and_deps: Some((
+                &["rustc_codegen_cranelift"],
+                PERMITTED_CRANELIFT_DEPENDENCIES,
+                PERMITTED_CRANELIFT_DEPS_LOCATION,
+            )),
+            submodules: &[],
+        }
+    },
+    WorkspaceInfo {
+        path: "compiler/rustc_codegen_gcc",
+        exceptions: EXCEPTIONS_GCC,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "src/bootstrap",
+        exceptions: EXCEPTIONS_BOOTSTRAP,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "src/tools/cargo",
+        exceptions: EXCEPTIONS_CARGO,
+        crates_and_deps: None,
+        submodules: &["src/tools/cargo"],
+    },
+    // FIXME uncomment once all deps are vendored
+    //  WorkspaceInfo {
+    //      path: "src/tools/miri/test-cargo-miri",
+    //      crates_and_deps: None
+    //      submodules: &[],
+    //  },
+    // WorkspaceInfo {
+    //      path: "src/tools/miri/test_dependencies",
+    //      crates_and_deps: None,
+    //      submodules: &[],
+    //  }
+    WorkspaceInfo {
+        path: "src/tools/rust-analyzer",
+        exceptions: EXCEPTIONS_RUST_ANALYZER,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "src/tools/rustbook",
+        exceptions: EXCEPTIONS_RUSTBOOK,
+        crates_and_deps: None,
+        submodules: &["src/doc/book", "src/doc/reference"],
+    },
+    WorkspaceInfo {
+        path: "src/tools/rustc-perf",
+        exceptions: EXCEPTIONS_RUSTC_PERF,
+        crates_and_deps: None,
+        submodules: &["src/tools/rustc-perf"],
+    },
+    WorkspaceInfo {
+        path: "src/tools/test-float-parse",
+        exceptions: EXCEPTIONS,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "tests/run-make-cargo/uefi-qemu/uefi_qemu_test",
+        exceptions: EXCEPTIONS_UEFI_QEMU_TEST,
+        crates_and_deps: None,
+        submodules: &[],
+    },
 ];
 
 /// These are exceptions to Rust's permissive licensing policy, and
@@ -226,7 +302,20 @@ const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
     ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptable, but we use it under MIT OR Apache-2.0
 ];
 
-const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!());
+#[derive(Clone, Copy)]
+struct ListLocation {
+    path: &'static str,
+    line: u32,
+}
+
+/// Creates a [`ListLocation`] for the current location (with an additional offset to the actual list start);
+macro_rules! location {
+    (+ $offset:literal) => {
+        ListLocation { path: file!(), line: line!() + $offset }
+    };
+}
+
+const PERMITTED_RUSTC_DEPS_LOCATION: ListLocation = location!(+6);
 
 /// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
 ///
@@ -458,6 +547,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-end
 ];
 
+const PERMITTED_STDLIB_DEPS_LOCATION: ListLocation = location!(+2);
+
 const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
     "addr2line",
@@ -499,6 +590,8 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-end
 ];
 
+const PERMITTED_CRANELIFT_DEPS_LOCATION: ListLocation = location!(+2);
+
 const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
     "allocator-api2",
@@ -573,29 +666,30 @@ pub fn check(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
 
     check_proc_macro_dep_list(root, cargo, bless, bad);
 
-    for &(workspace, exceptions, permitted_deps, submodules) in WORKSPACES {
+    for &WorkspaceInfo { path, exceptions, crates_and_deps, submodules } in WORKSPACES {
         if has_missing_submodule(root, submodules) {
             continue;
         }
 
-        if !root.join(workspace).join("Cargo.lock").exists() {
-            tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
+        if !root.join(path).join("Cargo.lock").exists() {
+            tidy_error!(bad, "the `{path}` workspace doesn't have a Cargo.lock");
             continue;
         }
 
         let mut cmd = cargo_metadata::MetadataCommand::new();
         cmd.cargo_path(cargo)
-            .manifest_path(root.join(workspace).join("Cargo.toml"))
+            .manifest_path(root.join(path).join("Cargo.toml"))
             .features(cargo_metadata::CargoOpt::AllFeatures)
             .other_options(vec!["--locked".to_owned()]);
         let metadata = t!(cmd.exec());
 
-        check_license_exceptions(&metadata, workspace, exceptions, bad);
-        if let Some((crates, permitted_deps)) = permitted_deps {
-            check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad);
+        check_license_exceptions(&metadata, path, exceptions, bad);
+        if let Some((crates, permitted_deps, location)) = crates_and_deps {
+            let descr = crates.get(0).unwrap_or(&path);
+            check_permitted_dependencies(&metadata, descr, permitted_deps, crates, location, bad);
         }
 
-        if workspace == "library" {
+        if path == "library" {
             check_runtime_license_exceptions(&metadata, bad);
             check_runtime_no_duplicate_dependencies(&metadata, bad);
             check_runtime_no_proc_macros(&metadata, bad);
@@ -840,6 +934,7 @@ fn check_permitted_dependencies(
     descr: &str,
     permitted_dependencies: &[&'static str],
     restricted_dependency_crates: &[&'static str],
+    permitted_location: ListLocation,
     bad: &mut bool,
 ) {
     let mut has_permitted_dep_error = false;
@@ -900,7 +995,7 @@ fn check_permitted_dependencies(
     }
 
     if has_permitted_dep_error {
-        eprintln!("Go to `{PERMITTED_DEPS_LOCATION}` for the list.");
+        eprintln!("Go to `{}:{}` for the list.", permitted_location.path, permitted_location.line);
     }
 }
 
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index bc217a55cc1..2b212cfa67a 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -3,6 +3,8 @@
 use std::fs;
 use std::path::Path;
 
+use crate::deps::WorkspaceInfo;
+
 /// List of allowed sources for packages.
 const ALLOWED_SOURCES: &[&str] = &[
     r#""registry+https://github.com/rust-lang/crates.io-index""#,
@@ -13,22 +15,22 @@ const ALLOWED_SOURCES: &[&str] = &[
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
 pub fn check(root: &Path, bad: &mut bool) {
-    for &(workspace, _, _, submodules) in crate::deps::WORKSPACES {
+    for &WorkspaceInfo { path, submodules, .. } in crate::deps::WORKSPACES {
         if crate::deps::has_missing_submodule(root, submodules) {
             continue;
         }
 
         // FIXME check other workspaces too
         // `Cargo.lock` of rust.
-        let path = root.join(workspace).join("Cargo.lock");
+        let lockfile = root.join(path).join("Cargo.lock");
 
-        if !path.exists() {
-            tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
+        if !lockfile.exists() {
+            tidy_error!(bad, "the `{path}` workspace doesn't have a Cargo.lock");
             continue;
         }
 
         // Open and read the whole file.
-        let cargo_lock = t!(fs::read_to_string(&path));
+        let cargo_lock = t!(fs::read_to_string(&lockfile));
 
         // Process each line.
         for line in cargo_lock.lines() {