about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/compiletest/src/header.rs710
-rw-r--r--src/tools/compiletest/src/header/tests.rs147
-rw-r--r--src/tools/miri/src/bin/miri.rs5
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs14
-rw-r--r--src/tools/miri/src/concurrency/init_once.rs1
-rw-r--r--src/tools/miri/src/concurrency/sync.rs9
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/src/helpers.rs4
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs2
-rw-r--r--src/tools/miri/tests/pass/intrinsics.rs2
-rw-r--r--src/tools/tidy/src/style.rs13
-rw-r--r--src/tools/tidy/src/ui_tests.rs3
14 files changed, 593 insertions, 324 deletions
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 8d5bcd665ad..47195fcc17b 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -335,7 +335,7 @@ fn check_terminator<'tcx>(
                 // within const fns. `transmute` is allowed in all other const contexts.
                 // This won't really scale to more intrinsics or functions. Let's allow const
                 // transmutes in const fn before we add more hacks to this.
-                if tcx.is_intrinsic(fn_def_id) && tcx.item_name(fn_def_id) == sym::transmute {
+                if matches!(tcx.intrinsic(fn_def_id), Some(sym::transmute)) {
                     return Err((
                         span,
                         "can only call `transmute` from const items, not `const fn`".into(),
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index daec3914145..4ceb8a646e0 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,6 +6,7 @@ use std::io::BufReader;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use regex::Regex;
 use tracing::*;
 
 use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
@@ -46,18 +47,32 @@ impl EarlyProps {
 
     pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
         let mut props = EarlyProps::default();
-        iter_header(testfile, rdr, &mut |_, ln, _| {
-            config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
-                r.trim().to_string()
-            });
-            config.push_name_value_directive(
-                ln,
-                directives::AUX_CRATE,
-                &mut props.aux_crate,
-                Config::parse_aux_crate,
-            );
-            config.parse_and_update_revisions(ln, &mut props.revisions);
-        });
+        let mut poisoned = false;
+        iter_header(
+            config.mode,
+            &config.suite,
+            &mut poisoned,
+            testfile,
+            rdr,
+            &mut |_, _, ln, _| {
+                config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
+                    r.trim().to_string()
+                });
+                config.push_name_value_directive(
+                    ln,
+                    directives::AUX_CRATE,
+                    &mut props.aux_crate,
+                    Config::parse_aux_crate,
+                );
+                config.parse_and_update_revisions(ln, &mut props.revisions);
+            },
+        );
+
+        if poisoned {
+            eprintln!("errors encountered during EarlyProps parsing: {}", testfile.display());
+            panic!("errors encountered during EarlyProps parsing");
+        }
+
         return props;
     }
 }
@@ -306,205 +321,233 @@ impl TestProps {
         if !testfile.is_dir() {
             let file = File::open(testfile).unwrap();
 
-            iter_header(testfile, file, &mut |revision, ln, _| {
-                if revision.is_some() && revision != cfg {
-                    return;
-                }
+            let mut poisoned = false;
 
-                use directives::*;
+            iter_header(
+                config.mode,
+                &config.suite,
+                &mut poisoned,
+                testfile,
+                file,
+                &mut |revision, _, ln, _| {
+                    if revision.is_some() && revision != cfg {
+                        return;
+                    }
 
-                config.push_name_value_directive(
-                    ln,
-                    ERROR_PATTERN,
-                    &mut self.error_patterns,
-                    |r| r,
-                );
-                config.push_name_value_directive(
-                    ln,
-                    REGEX_ERROR_PATTERN,
-                    &mut self.regex_error_patterns,
-                    |r| r,
-                );
+                    use directives::*;
+
+                    config.push_name_value_directive(
+                        ln,
+                        ERROR_PATTERN,
+                        &mut self.error_patterns,
+                        |r| r,
+                    );
+                    config.push_name_value_directive(
+                        ln,
+                        REGEX_ERROR_PATTERN,
+                        &mut self.regex_error_patterns,
+                        |r| r,
+                    );
 
-                fn split_flags(flags: &str) -> Vec<String> {
-                    // Individual flags can be single-quoted to preserve spaces; see
-                    // <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
-                    flags
-                        .split("'")
-                        .enumerate()
-                        .flat_map(
-                            |(i, f)| {
+                    fn split_flags(flags: &str) -> Vec<String> {
+                        // Individual flags can be single-quoted to preserve spaces; see
+                        // <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
+                        flags
+                            .split("'")
+                            .enumerate()
+                            .flat_map(|(i, f)| {
                                 if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() }
-                            },
-                        )
-                        .map(move |s| s.to_owned())
-                        .collect::<Vec<_>>()
-                }
+                            })
+                            .map(move |s| s.to_owned())
+                            .collect::<Vec<_>>()
+                    }
 
-                if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
-                    self.compile_flags.extend(split_flags(&flags));
-                }
-                if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
-                    panic!("`compiler-flags` directive should be spelled `compile-flags`");
-                }
+                    if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
+                        self.compile_flags.extend(split_flags(&flags));
+                    }
+                    if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
+                        panic!("`compiler-flags` directive should be spelled `compile-flags`");
+                    }
 
-                if let Some(edition) = config.parse_edition(ln) {
-                    self.compile_flags.push(format!("--edition={}", edition.trim()));
-                    has_edition = true;
-                }
+                    if let Some(edition) = config.parse_edition(ln) {
+                        self.compile_flags.push(format!("--edition={}", edition.trim()));
+                        has_edition = true;
+                    }
 
-                config.parse_and_update_revisions(ln, &mut self.revisions);
+                    config.parse_and_update_revisions(ln, &mut self.revisions);
 
-                config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r);
+                    config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r);
 
-                if self.pp_exact.is_none() {
-                    self.pp_exact = config.parse_pp_exact(ln, testfile);
-                }
+                    if self.pp_exact.is_none() {
+                        self.pp_exact = config.parse_pp_exact(ln, testfile);
+                    }
 
-                config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
-                config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
-                config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
-                config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
-                config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
-                config.set_name_directive(
-                    ln,
-                    DONT_CHECK_COMPILER_STDOUT,
-                    &mut self.dont_check_compiler_stdout,
-                );
-                config.set_name_directive(
-                    ln,
-                    DONT_CHECK_COMPILER_STDERR,
-                    &mut self.dont_check_compiler_stderr,
-                );
-                config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic);
-                config.set_name_directive(ln, PRETTY_EXPANDED, &mut self.pretty_expanded);
+                    config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
+                    config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
+                    config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
+                    config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
+                    config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
+                    config.set_name_directive(
+                        ln,
+                        DONT_CHECK_COMPILER_STDOUT,
+                        &mut self.dont_check_compiler_stdout,
+                    );
+                    config.set_name_directive(
+                        ln,
+                        DONT_CHECK_COMPILER_STDERR,
+                        &mut self.dont_check_compiler_stderr,
+                    );
+                    config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic);
+                    config.set_name_directive(ln, PRETTY_EXPANDED, &mut self.pretty_expanded);
 
-                if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) {
-                    self.pretty_mode = m;
-                }
+                    if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) {
+                        self.pretty_mode = m;
+                    }
 
-                config.set_name_directive(ln, PRETTY_COMPARE_ONLY, &mut self.pretty_compare_only);
-                config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
-                    r.trim().to_string()
-                });
-                config.push_name_value_directive(
-                    ln,
-                    AUX_CRATE,
-                    &mut self.aux_crates,
-                    Config::parse_aux_crate,
-                );
-                config.push_name_value_directive(
-                    ln,
-                    EXEC_ENV,
-                    &mut self.exec_env,
-                    Config::parse_env,
-                );
-                config.push_name_value_directive(
-                    ln,
-                    UNSET_EXEC_ENV,
-                    &mut self.unset_exec_env,
-                    |r| r,
-                );
-                config.push_name_value_directive(
-                    ln,
-                    RUSTC_ENV,
-                    &mut self.rustc_env,
-                    Config::parse_env,
-                );
-                config.push_name_value_directive(
-                    ln,
-                    UNSET_RUSTC_ENV,
-                    &mut self.unset_rustc_env,
-                    |r| r,
-                );
-                config.push_name_value_directive(ln, FORBID_OUTPUT, &mut self.forbid_output, |r| r);
-                config.set_name_directive(
-                    ln,
-                    CHECK_TEST_LINE_NUMBERS_MATCH,
-                    &mut self.check_test_line_numbers_match,
-                );
+                    config.set_name_directive(
+                        ln,
+                        PRETTY_COMPARE_ONLY,
+                        &mut self.pretty_compare_only,
+                    );
+                    config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
+                        r.trim().to_string()
+                    });
+                    config.push_name_value_directive(
+                        ln,
+                        AUX_CRATE,
+                        &mut self.aux_crates,
+                        Config::parse_aux_crate,
+                    );
+                    config.push_name_value_directive(
+                        ln,
+                        EXEC_ENV,
+                        &mut self.exec_env,
+                        Config::parse_env,
+                    );
+                    config.push_name_value_directive(
+                        ln,
+                        UNSET_EXEC_ENV,
+                        &mut self.unset_exec_env,
+                        |r| r,
+                    );
+                    config.push_name_value_directive(
+                        ln,
+                        RUSTC_ENV,
+                        &mut self.rustc_env,
+                        Config::parse_env,
+                    );
+                    config.push_name_value_directive(
+                        ln,
+                        UNSET_RUSTC_ENV,
+                        &mut self.unset_rustc_env,
+                        |r| r,
+                    );
+                    config.push_name_value_directive(
+                        ln,
+                        FORBID_OUTPUT,
+                        &mut self.forbid_output,
+                        |r| r,
+                    );
+                    config.set_name_directive(
+                        ln,
+                        CHECK_TEST_LINE_NUMBERS_MATCH,
+                        &mut self.check_test_line_numbers_match,
+                    );
 
-                self.update_pass_mode(ln, cfg, config);
-                self.update_fail_mode(ln, config);
+                    self.update_pass_mode(ln, cfg, config);
+                    self.update_fail_mode(ln, config);
 
-                config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass);
+                    config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass);
 
-                if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
-                    self.normalize_stdout.push(rule);
-                }
-                if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
-                    self.normalize_stderr.push(rule);
-                }
+                    if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
+                        self.normalize_stdout.push(rule);
+                    }
+                    if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
+                        self.normalize_stderr.push(rule);
+                    }
 
-                if let Some(code) = config
-                    .parse_name_value_directive(ln, FAILURE_STATUS)
-                    .and_then(|code| code.trim().parse::<i32>().ok())
-                {
-                    self.failure_status = Some(code);
-                }
+                    if let Some(code) = config
+                        .parse_name_value_directive(ln, FAILURE_STATUS)
+                        .and_then(|code| code.trim().parse::<i32>().ok())
+                    {
+                        self.failure_status = Some(code);
+                    }
 
-                config.set_name_directive(
-                    ln,
-                    DONT_CHECK_FAILURE_STATUS,
-                    &mut self.dont_check_failure_status,
-                );
+                    config.set_name_directive(
+                        ln,
+                        DONT_CHECK_FAILURE_STATUS,
+                        &mut self.dont_check_failure_status,
+                    );
 
-                config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix);
-                config.set_name_directive(
-                    ln,
-                    RUSTFIX_ONLY_MACHINE_APPLICABLE,
-                    &mut self.rustfix_only_machine_applicable,
-                );
-                config.set_name_value_directive(
-                    ln,
-                    ASSEMBLY_OUTPUT,
-                    &mut self.assembly_output,
-                    |r| r.trim().to_string(),
-                );
-                config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth);
-                config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
-
-                // Unlike the other `name_value_directive`s this needs to be handled manually,
-                // because it sets a `bool` flag.
-                if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) {
-                    let known_bug = known_bug.trim();
-                    if known_bug == "unknown"
-                        || known_bug.split(',').all(|issue_ref| {
-                            issue_ref
-                                .trim()
-                                .split_once('#')
-                                .filter(|(_, number)| {
-                                    number.chars().all(|digit| digit.is_numeric())
-                                })
-                                .is_some()
-                        })
-                    {
-                        self.known_bug = true;
-                    } else {
+                    config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix);
+                    config.set_name_directive(
+                        ln,
+                        RUSTFIX_ONLY_MACHINE_APPLICABLE,
+                        &mut self.rustfix_only_machine_applicable,
+                    );
+                    config.set_name_value_directive(
+                        ln,
+                        ASSEMBLY_OUTPUT,
+                        &mut self.assembly_output,
+                        |r| r.trim().to_string(),
+                    );
+                    config.set_name_directive(
+                        ln,
+                        STDERR_PER_BITWIDTH,
+                        &mut self.stderr_per_bitwidth,
+                    );
+                    config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
+
+                    // Unlike the other `name_value_directive`s this needs to be handled manually,
+                    // because it sets a `bool` flag.
+                    if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) {
+                        let known_bug = known_bug.trim();
+                        if known_bug == "unknown"
+                            || known_bug.split(',').all(|issue_ref| {
+                                issue_ref
+                                    .trim()
+                                    .split_once('#')
+                                    .filter(|(_, number)| {
+                                        number.chars().all(|digit| digit.is_numeric())
+                                    })
+                                    .is_some()
+                            })
+                        {
+                            self.known_bug = true;
+                        } else {
+                            panic!(
+                                "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
+                            );
+                        }
+                    } else if config.parse_name_directive(ln, KNOWN_BUG) {
                         panic!(
-                            "Invalid known-bug value: {known_bug}\nIt requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
+                            "Invalid known-bug attribute, requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
                         );
                     }
-                } else if config.parse_name_directive(ln, KNOWN_BUG) {
-                    panic!(
-                        "Invalid known-bug attribute, requires comma-separated issue references (`#000` or `chalk#000`) or `known-bug: unknown`."
+
+                    config.set_name_value_directive(
+                        ln,
+                        MIR_UNIT_TEST,
+                        &mut self.mir_unit_test,
+                        |s| s.trim().to_string(),
+                    );
+                    config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
+                    config.set_name_directive(
+                        ln,
+                        COMPARE_OUTPUT_LINES_BY_SUBSET,
+                        &mut self.compare_output_lines_by_subset,
                     );
-                }
 
-                config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
-                    s.trim().to_string()
-                });
-                config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
-                config.set_name_directive(
-                    ln,
-                    COMPARE_OUTPUT_LINES_BY_SUBSET,
-                    &mut self.compare_output_lines_by_subset,
-                );
+                    if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
+                        self.llvm_cov_flags.extend(split_flags(&flags));
+                    }
+                },
+            );
 
-                if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
-                    self.llvm_cov_flags.extend(split_flags(&flags));
-                }
-            });
+            if poisoned {
+                eprintln!("errors encountered during TestProps parsing: {}", testfile.display());
+                panic!("errors encountered during TestProps parsing");
+            }
         }
 
         if self.should_ice {
@@ -628,15 +671,143 @@ pub fn line_directive<'line>(
     }
 }
 
-fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str, usize)) {
-    iter_header_extra(testfile, rdr, &[], it)
+fn iter_header<R: Read>(
+    mode: Mode,
+    suite: &str,
+    poisoned: &mut bool,
+    testfile: &Path,
+    rdr: R,
+    it: &mut dyn FnMut(Option<&str>, &str, &str, usize),
+) {
+    iter_header_extra(mode, suite, poisoned, testfile, rdr, &[], it)
 }
 
+/// This is generated by collecting directives from ui tests and then extracting their directive
+/// names. This is **not** an exhaustive list of all possible directives. Instead, this is a
+/// best-effort approximation for diagnostics.
+const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
+    "aux-build",
+    "aux-crate",
+    "build-fail",
+    "build-pass",
+    "check-fail",
+    "check-pass",
+    "check-run-results",
+    "check-stdout",
+    "compile-flags",
+    "dont-check-compiler-stderr",
+    "dont-check-compiler-stdout",
+    "dont-check-failure-status",
+    "edition",
+    "error-pattern",
+    "exec-env",
+    "failure-status",
+    "forbid-output",
+    "force-host",
+    "ignore-32bit",
+    "ignore-64bit",
+    "ignore-aarch64",
+    "ignore-aarch64-unknown-linux-gnu",
+    "ignore-android",
+    "ignore-arm",
+    "ignore-compare-mode-next-solver",
+    "ignore-compare-mode-polonius",
+    "ignore-cross-compile",
+    "ignore-debug",
+    "ignore-emscripten",
+    "ignore-endian-big",
+    "ignore-freebsd",
+    "ignore-fuchsia",
+    "ignore-gnu",
+    "ignore-haiku",
+    "ignore-horizon",
+    "ignore-i686-pc-windows-msvc",
+    "ignore-ios",
+    "ignore-llvm-version",
+    "ignore-macos",
+    "ignore-msvc",
+    "ignore-musl",
+    "ignore-netbsd",
+    "ignore-nightly",
+    "ignore-nto",
+    "ignore-nvptx64",
+    "ignore-openbsd",
+    "ignore-pass",
+    "ignore-sgx",
+    "ignore-spirv",
+    "ignore-test",
+    "ignore-thumbv8m.base-none-eabi",
+    "ignore-thumbv8m.main-none-eabi",
+    "ignore-uwp",
+    "ignore-vxworks",
+    "ignore-wasm",
+    "ignore-wasm32",
+    "ignore-wasm32-bare",
+    "ignore-windows",
+    "ignore-x86",
+    "incremental",
+    "known-bug",
+    "min-llvm-version",
+    "needs-asm-support",
+    "needs-dlltool",
+    "needs-dynamic-linking",
+    "needs-llvm-components",
+    "needs-profiler-support",
+    "needs-relocation-model-pic",
+    "needs-run-enabled",
+    "needs-sanitizer-address",
+    "needs-sanitizer-cfi",
+    "needs-sanitizer-hwaddress",
+    "needs-sanitizer-leak",
+    "needs-sanitizer-memory",
+    "needs-sanitizer-support",
+    "needs-sanitizer-thread",
+    "needs-unwind",
+    "needs-xray",
+    "no-prefer-dynamic",
+    "normalize-stderr-32bit",
+    "normalize-stderr-64bit",
+    "normalize-stderr-test",
+    "normalize-stdout-test",
+    "only-32bit",
+    "only-64bit",
+    "only-aarch64",
+    "only-gnu",
+    "only-i686-pc-windows-msvc",
+    "only-linux",
+    "only-macos",
+    "only-msvc",
+    "only-nightly",
+    "only-wasm32",
+    "only-windows",
+    "only-x86",
+    "only-x86_64",
+    "only-x86_64-pc-windows-msvc",
+    "only-x86_64-unknown-linux-gnu",
+    "pp-exact",
+    "pretty-expanded",
+    "regex-error-pattern",
+    "remap-src-base",
+    "revisions",
+    "run-fail",
+    "run-flags",
+    "run-pass",
+    "run-rustfix",
+    "rustc-env",
+    "rustfix-only-machine-applicable",
+    "should-fail",
+    "stderr-per-bitwidth",
+    "unset-rustc-env",
+];
+
 fn iter_header_extra(
+    mode: Mode,
+    suite: &str,
+    poisoned: &mut bool,
     testfile: &Path,
     rdr: impl Read,
     extra_directives: &[&str],
-    it: &mut dyn FnMut(Option<&str>, &str, usize),
+    it: &mut dyn FnMut(Option<&str>, &str, &str, usize),
 ) {
     if testfile.is_dir() {
         return;
@@ -645,15 +816,21 @@ fn iter_header_extra(
     // Process any extra directives supplied by the caller (e.g. because they
     // are implied by the test mode), with a dummy line number of 0.
     for directive in extra_directives {
-        it(None, directive, 0);
+        it(None, directive, directive, 0);
     }
 
-    let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//" } else { "#" };
+    let comment = if testfile.extension().is_some_and(|e| e == "rs") {
+        if mode == Mode::Ui && suite == "ui" { "//@" } else { "//" }
+    } else {
+        "#"
+    };
 
     let mut rdr = BufReader::with_capacity(1024, rdr);
     let mut ln = String::new();
     let mut line_number = 0;
 
+    let revision_magic_comment = Regex::new("//(\\[.*\\])?~.*").unwrap();
+
     loop {
         line_number += 1;
         ln.clear();
@@ -664,11 +841,56 @@ fn iter_header_extra(
         // Assume that any directives will be found before the first
         // module or function. This doesn't seem to be an optimization
         // with a warm page cache. Maybe with a cold one.
+        let orig_ln = &ln;
         let ln = ln.trim();
         if ln.starts_with("fn") || ln.starts_with("mod") {
             return;
+
+        // First try to accept `ui_test` style comments
         } else if let Some((lncfg, ln)) = line_directive(comment, ln) {
-            it(lncfg, ln, line_number);
+            it(lncfg, orig_ln, ln, line_number);
+        } else if mode == Mode::Ui && suite == "ui" && !revision_magic_comment.is_match(ln) {
+            let Some((_, rest)) = line_directive("//", ln) else {
+                continue;
+            };
+
+            if rest.trim_start().starts_with(':') {
+                // This is likely a markdown link:
+                // `[link_name]: https://example.org`
+                continue;
+            }
+
+            let rest = rest.trim_start();
+
+            for candidate in DIAGNOSTICS_DIRECTIVE_NAMES.iter() {
+                if rest.starts_with(candidate) {
+                    let Some(prefix_removed) = rest.strip_prefix(candidate) else {
+                        // We have a comment that's *successfully* parsed as an legacy-style
+                        // directive. We emit an error here to warn the user.
+                        *poisoned = true;
+                        eprintln!(
+                            "error: detected legacy-style directives in ui test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
+                            testfile.display(),
+                            line_number,
+                            line_directive("//", ln),
+                        );
+                        return;
+                    };
+
+                    if prefix_removed.starts_with([' ', ':']) {
+                        // We have a comment that's *successfully* parsed as an legacy-style
+                        // directive. We emit an error here to warn the user.
+                        *poisoned = true;
+                        eprintln!(
+                            "error: detected legacy-style directives in ui test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
+                            testfile.display(),
+                            line_number,
+                            line_directive("//", ln),
+                        );
+                        return;
+                    }
+                }
+            }
         }
     }
 }
@@ -946,49 +1168,77 @@ pub fn make_test_description<R: Read>(
         _ => &[],
     };
 
-    iter_header_extra(path, src, extra_directives, &mut |revision, ln, line_number| {
-        if revision.is_some() && revision != cfg {
-            return;
-        }
+    let mut local_poisoned = false;
+
+    iter_header_extra(
+        config.mode,
+        &config.suite,
+        &mut local_poisoned,
+        path,
+        src,
+        extra_directives,
+        &mut |revision, og_ln, ln, line_number| {
+            if revision.is_some() && revision != cfg {
+                return;
+            }
 
-        macro_rules! decision {
-            ($e:expr) => {
-                match $e {
-                    IgnoreDecision::Ignore { reason } => {
-                        ignore = true;
-                        // The ignore reason must be a &'static str, so we have to leak memory to
-                        // create it. This is fine, as the header is parsed only at the start of
-                        // compiletest so it won't grow indefinitely.
-                        ignore_message = Some(&*Box::leak(Box::<str>::from(reason)));
+            macro_rules! decision {
+                ($e:expr) => {
+                    match $e {
+                        IgnoreDecision::Ignore { reason } => {
+                            ignore = true;
+                            // The ignore reason must be a &'static str, so we have to leak memory to
+                            // create it. This is fine, as the header is parsed only at the start of
+                            // compiletest so it won't grow indefinitely.
+                            ignore_message = Some(&*Box::leak(Box::<str>::from(reason)));
+                        }
+                        IgnoreDecision::Error { message } => {
+                            eprintln!("error: {}:{line_number}: {message}", path.display());
+                            *poisoned = true;
+                            return;
+                        }
+                        IgnoreDecision::Continue => {}
                     }
-                    IgnoreDecision::Error { message } => {
-                        eprintln!("error: {}:{line_number}: {message}", path.display());
-                        *poisoned = true;
-                        return;
-                    }
-                    IgnoreDecision::Continue => {}
+                };
+            }
+
+            if let Some((_, post)) = og_ln.trim_start().split_once("//") {
+                let post = post.trim_start();
+                if post.starts_with("ignore-tidy")
+                    && config.mode == Mode::Ui
+                    && config.suite == "ui"
+                {
+                    // not handled by compiletest under the ui test mode and ui test suite.
+                } else {
+                    decision!(cfg::handle_ignore(config, ln));
                 }
-            };
-        }
+            } else {
+                decision!(cfg::handle_ignore(config, ln));
+            }
 
-        decision!(cfg::handle_ignore(config, ln));
-        decision!(cfg::handle_only(config, ln));
-        decision!(needs::handle_needs(&cache.needs, config, ln));
-        decision!(ignore_llvm(config, ln));
-        decision!(ignore_cdb(config, ln));
-        decision!(ignore_gdb(config, ln));
-        decision!(ignore_lldb(config, ln));
-
-        if config.target == "wasm32-unknown-unknown" {
-            if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
-                decision!(IgnoreDecision::Ignore {
-                    reason: "ignored when checking the run results on WASM".into(),
-                });
+            decision!(cfg::handle_only(config, ln));
+            decision!(needs::handle_needs(&cache.needs, config, ln));
+            decision!(ignore_llvm(config, ln));
+            decision!(ignore_cdb(config, ln));
+            decision!(ignore_gdb(config, ln));
+            decision!(ignore_lldb(config, ln));
+
+            if config.target == "wasm32-unknown-unknown" {
+                if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
+                    decision!(IgnoreDecision::Ignore {
+                        reason: "ignored when checking the run results on WASM".into(),
+                    });
+                }
             }
-        }
 
-        should_fail |= config.parse_name_directive(ln, "should-fail");
-    });
+            should_fail |= config.parse_name_directive(ln, "should-fail");
+        },
+    );
+
+    if local_poisoned {
+        eprintln!("errors encountered when trying to make test description: {}", path.display());
+        panic!("errors encountered when trying to make test description");
+    }
 
     // The `should-fail` annotation doesn't apply to pretty tests,
     // since we run the pretty printer across all tests by default.
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c859e8acade..274006ae8c1 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -210,7 +210,7 @@ fn should_fail() {
 
     let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
     assert_eq!(d.should_panic, test::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, std::io::Cursor::new("//@ should-fail"), None);
     assert_eq!(d.should_panic, test::ShouldPanic::Yes);
 }
 
@@ -218,7 +218,7 @@ fn should_fail() {
 fn revisions() {
     let config: Config = cfg().build();
 
-    assert_eq!(parse_rs(&config, "// revisions: a b c").revisions, vec!["a", "b", "c"],);
+    assert_eq!(parse_rs(&config, "//@ revisions: a b c").revisions, vec!["a", "b", "c"],);
     assert_eq!(
         parse_makefile(&config, "# revisions: hello there").revisions,
         vec!["hello", "there"],
@@ -233,8 +233,8 @@ fn aux_build() {
         parse_rs(
             &config,
             r"
-        // aux-build: a.rs
-        // aux-build: b.rs
+        //@ aux-build: a.rs
+        //@ aux-build: b.rs
         "
         )
         .aux,
@@ -245,128 +245,128 @@ fn aux_build() {
 #[test]
 fn llvm_version() {
     let config: Config = cfg().llvm_version("8.1.2").build();
-    assert!(check_ignore(&config, "// min-llvm-version: 9.0"));
+    assert!(check_ignore(&config, "//@ min-llvm-version: 9.0"));
 
     let config: Config = cfg().llvm_version("9.0.1").build();
-    assert!(check_ignore(&config, "// min-llvm-version: 9.2"));
+    assert!(check_ignore(&config, "//@ min-llvm-version: 9.2"));
 
     let config: Config = cfg().llvm_version("9.3.1").build();
-    assert!(!check_ignore(&config, "// min-llvm-version: 9.2"));
+    assert!(!check_ignore(&config, "//@ min-llvm-version: 9.2"));
 
     let config: Config = cfg().llvm_version("10.0.0").build();
-    assert!(!check_ignore(&config, "// min-llvm-version: 9.0"));
+    assert!(!check_ignore(&config, "//@ min-llvm-version: 9.0"));
 }
 
 #[test]
 fn system_llvm_version() {
     let config: Config = cfg().system_llvm(true).llvm_version("17.0.0").build();
-    assert!(check_ignore(&config, "// min-system-llvm-version: 18.0"));
+    assert!(check_ignore(&config, "//@ min-system-llvm-version: 18.0"));
 
     let config: Config = cfg().system_llvm(true).llvm_version("18.0.0").build();
-    assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0"));
+    assert!(!check_ignore(&config, "//@ min-system-llvm-version: 18.0"));
 
     let config: Config = cfg().llvm_version("17.0.0").build();
-    assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0"));
+    assert!(!check_ignore(&config, "//@ min-system-llvm-version: 18.0"));
 }
 
 #[test]
 fn ignore_target() {
     let config: Config = cfg().target("x86_64-unknown-linux-gnu").build();
 
-    assert!(check_ignore(&config, "// ignore-x86_64-unknown-linux-gnu"));
-    assert!(check_ignore(&config, "// ignore-x86_64"));
-    assert!(check_ignore(&config, "// ignore-linux"));
-    assert!(check_ignore(&config, "// ignore-gnu"));
-    assert!(check_ignore(&config, "// ignore-64bit"));
+    assert!(check_ignore(&config, "//@ ignore-x86_64-unknown-linux-gnu"));
+    assert!(check_ignore(&config, "//@ ignore-x86_64"));
+    assert!(check_ignore(&config, "//@ ignore-linux"));
+    assert!(check_ignore(&config, "//@ ignore-gnu"));
+    assert!(check_ignore(&config, "//@ ignore-64bit"));
 
-    assert!(!check_ignore(&config, "// ignore-x86"));
-    assert!(!check_ignore(&config, "// ignore-windows"));
-    assert!(!check_ignore(&config, "// ignore-msvc"));
-    assert!(!check_ignore(&config, "// ignore-32bit"));
+    assert!(!check_ignore(&config, "//@ ignore-x86"));
+    assert!(!check_ignore(&config, "//@ ignore-windows"));
+    assert!(!check_ignore(&config, "//@ ignore-msvc"));
+    assert!(!check_ignore(&config, "//@ ignore-32bit"));
 }
 
 #[test]
 fn only_target() {
     let config: Config = cfg().target("x86_64-pc-windows-gnu").build();
 
-    assert!(check_ignore(&config, "// only-x86"));
-    assert!(check_ignore(&config, "// only-linux"));
-    assert!(check_ignore(&config, "// only-msvc"));
-    assert!(check_ignore(&config, "// only-32bit"));
+    assert!(check_ignore(&config, "//@ only-x86"));
+    assert!(check_ignore(&config, "//@ only-linux"));
+    assert!(check_ignore(&config, "//@ only-msvc"));
+    assert!(check_ignore(&config, "//@ only-32bit"));
 
-    assert!(!check_ignore(&config, "// only-x86_64-pc-windows-gnu"));
-    assert!(!check_ignore(&config, "// only-x86_64"));
-    assert!(!check_ignore(&config, "// only-windows"));
-    assert!(!check_ignore(&config, "// only-gnu"));
-    assert!(!check_ignore(&config, "// only-64bit"));
+    assert!(!check_ignore(&config, "//@ only-x86_64-pc-windows-gnu"));
+    assert!(!check_ignore(&config, "//@ only-x86_64"));
+    assert!(!check_ignore(&config, "//@ only-windows"));
+    assert!(!check_ignore(&config, "//@ only-gnu"));
+    assert!(!check_ignore(&config, "//@ only-64bit"));
 }
 
 #[test]
 fn stage() {
     let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build();
 
-    assert!(check_ignore(&config, "// ignore-stage1"));
-    assert!(!check_ignore(&config, "// ignore-stage2"));
+    assert!(check_ignore(&config, "//@ ignore-stage1"));
+    assert!(!check_ignore(&config, "//@ ignore-stage2"));
 }
 
 #[test]
 fn cross_compile() {
     let config: Config = cfg().host("x86_64-apple-darwin").target("wasm32-unknown-unknown").build();
-    assert!(check_ignore(&config, "// ignore-cross-compile"));
+    assert!(check_ignore(&config, "//@ ignore-cross-compile"));
 
     let config: Config = cfg().host("x86_64-apple-darwin").target("x86_64-apple-darwin").build();
-    assert!(!check_ignore(&config, "// ignore-cross-compile"));
+    assert!(!check_ignore(&config, "//@ ignore-cross-compile"));
 }
 
 #[test]
 fn debugger() {
     let mut config = cfg().build();
     config.debugger = None;
-    assert!(!check_ignore(&config, "// ignore-cdb"));
+    assert!(!check_ignore(&config, "//@ ignore-cdb"));
 
     config.debugger = Some(Debugger::Cdb);
-    assert!(check_ignore(&config, "// ignore-cdb"));
+    assert!(check_ignore(&config, "//@ ignore-cdb"));
 
     config.debugger = Some(Debugger::Gdb);
-    assert!(check_ignore(&config, "// ignore-gdb"));
+    assert!(check_ignore(&config, "//@ ignore-gdb"));
 
     config.debugger = Some(Debugger::Lldb);
-    assert!(check_ignore(&config, "// ignore-lldb"));
+    assert!(check_ignore(&config, "//@ ignore-lldb"));
 }
 
 #[test]
 fn git_hash() {
     let config: Config = cfg().git_hash(false).build();
-    assert!(check_ignore(&config, "// needs-git-hash"));
+    assert!(check_ignore(&config, "//@ needs-git-hash"));
 
     let config: Config = cfg().git_hash(true).build();
-    assert!(!check_ignore(&config, "// needs-git-hash"));
+    assert!(!check_ignore(&config, "//@ needs-git-hash"));
 }
 
 #[test]
 fn sanitizers() {
     // Target that supports all sanitizers:
     let config: Config = cfg().target("x86_64-unknown-linux-gnu").build();
-    assert!(!check_ignore(&config, "// needs-sanitizer-address"));
-    assert!(!check_ignore(&config, "// needs-sanitizer-leak"));
-    assert!(!check_ignore(&config, "// needs-sanitizer-memory"));
-    assert!(!check_ignore(&config, "// needs-sanitizer-thread"));
+    assert!(!check_ignore(&config, "//@ needs-sanitizer-address"));
+    assert!(!check_ignore(&config, "//@ needs-sanitizer-leak"));
+    assert!(!check_ignore(&config, "//@ needs-sanitizer-memory"));
+    assert!(!check_ignore(&config, "//@ needs-sanitizer-thread"));
 
     // Target that doesn't support sanitizers:
     let config: Config = cfg().target("wasm32-unknown-emscripten").build();
-    assert!(check_ignore(&config, "// needs-sanitizer-address"));
-    assert!(check_ignore(&config, "// needs-sanitizer-leak"));
-    assert!(check_ignore(&config, "// needs-sanitizer-memory"));
-    assert!(check_ignore(&config, "// needs-sanitizer-thread"));
+    assert!(check_ignore(&config, "//@ needs-sanitizer-address"));
+    assert!(check_ignore(&config, "//@ needs-sanitizer-leak"));
+    assert!(check_ignore(&config, "//@ needs-sanitizer-memory"));
+    assert!(check_ignore(&config, "//@ needs-sanitizer-thread"));
 }
 
 #[test]
 fn profiler_support() {
     let config: Config = cfg().profiler_support(false).build();
-    assert!(check_ignore(&config, "// needs-profiler-support"));
+    assert!(check_ignore(&config, "//@ needs-profiler-support"));
 
     let config: Config = cfg().profiler_support(true).build();
-    assert!(!check_ignore(&config, "// needs-profiler-support"));
+    assert!(!check_ignore(&config, "//@ needs-profiler-support"));
 }
 
 #[test]
@@ -382,7 +382,7 @@ fn asm_support() {
     for (target, has_asm) in asms {
         let config = cfg().target(target).build();
         assert_eq!(config.has_asm_support(), has_asm);
-        assert_eq!(check_ignore(&config, "// needs-asm-support"), !has_asm)
+        assert_eq!(check_ignore(&config, "//@ needs-asm-support"), !has_asm)
     }
 }
 
@@ -390,13 +390,13 @@ fn asm_support() {
 fn channel() {
     let config: Config = cfg().channel("beta").build();
 
-    assert!(check_ignore(&config, "// ignore-beta"));
-    assert!(check_ignore(&config, "// only-nightly"));
-    assert!(check_ignore(&config, "// only-stable"));
+    assert!(check_ignore(&config, "//@ ignore-beta"));
+    assert!(check_ignore(&config, "//@ only-nightly"));
+    assert!(check_ignore(&config, "//@ only-stable"));
 
-    assert!(!check_ignore(&config, "// only-beta"));
-    assert!(!check_ignore(&config, "// ignore-nightly"));
-    assert!(!check_ignore(&config, "// ignore-stable"));
+    assert!(!check_ignore(&config, "//@ only-beta"));
+    assert!(!check_ignore(&config, "//@ ignore-nightly"));
+    assert!(!check_ignore(&config, "//@ ignore-stable"));
 }
 
 #[test]
@@ -418,7 +418,7 @@ fn test_extract_version_range() {
 #[should_panic(expected = "Duplicate revision: `rpass1` in line ` rpass1 rpass1`")]
 fn test_duplicate_revisions() {
     let config: Config = cfg().build();
-    parse_rs(&config, "// revisions: rpass1 rpass1");
+    parse_rs(&config, "//@ revisions: rpass1 rpass1");
 }
 
 #[test]
@@ -432,7 +432,7 @@ fn ignore_arch() {
     for (target, arch) in archs {
         let config: Config = cfg().target(target).build();
         assert!(config.matches_arch(arch), "{target} {arch}");
-        assert!(check_ignore(&config, &format!("// ignore-{arch}")));
+        assert!(check_ignore(&config, &format!("//@ ignore-{arch}")));
     }
 }
 
@@ -447,7 +447,7 @@ fn matches_os() {
     for (target, os) in oss {
         let config = cfg().target(target).build();
         assert!(config.matches_os(os), "{target} {os}");
-        assert!(check_ignore(&config, &format!("// ignore-{os}")));
+        assert!(check_ignore(&config, &format!("//@ ignore-{os}")));
     }
 }
 
@@ -461,7 +461,7 @@ fn matches_env() {
     for (target, env) in envs {
         let config: Config = cfg().target(target).build();
         assert!(config.matches_env(env), "{target} {env}");
-        assert!(check_ignore(&config, &format!("// ignore-{env}")));
+        assert!(check_ignore(&config, &format!("//@ ignore-{env}")));
     }
 }
 
@@ -475,7 +475,7 @@ fn matches_abi() {
     for (target, abi) in abis {
         let config: Config = cfg().target(target).build();
         assert!(config.matches_abi(abi), "{target} {abi}");
-        assert!(check_ignore(&config, &format!("// ignore-{abi}")));
+        assert!(check_ignore(&config, &format!("//@ ignore-{abi}")));
     }
 }
 
@@ -491,7 +491,7 @@ fn is_big_endian() {
     for (target, is_big) in endians {
         let config = cfg().target(target).build();
         assert_eq!(config.is_big_endian(), is_big, "{target} {is_big}");
-        assert_eq!(check_ignore(&config, "// ignore-endian-big"), is_big);
+        assert_eq!(check_ignore(&config, "//@ ignore-endian-big"), is_big);
     }
 }
 
@@ -506,9 +506,9 @@ fn pointer_width() {
     for (target, width) in widths {
         let config: Config = cfg().target(target).build();
         assert_eq!(config.get_pointer_width(), width, "{target} {width}");
-        assert_eq!(check_ignore(&config, "// ignore-16bit"), width == 16);
-        assert_eq!(check_ignore(&config, "// ignore-32bit"), width == 32);
-        assert_eq!(check_ignore(&config, "// ignore-64bit"), width == 64);
+        assert_eq!(check_ignore(&config, "//@ ignore-16bit"), width == 16);
+        assert_eq!(check_ignore(&config, "//@ ignore-32bit"), width == 32);
+        assert_eq!(check_ignore(&config, "//@ ignore-64bit"), width == 64);
     }
 }
 
@@ -534,7 +534,7 @@ fn wasm_special() {
     for (target, pattern, ignore) in ignores {
         let config: Config = cfg().target(target).build();
         assert_eq!(
-            check_ignore(&config, &format!("// ignore-{pattern}")),
+            check_ignore(&config, &format!("//@ ignore-{pattern}")),
             ignore,
             "{target} {pattern}"
         );
@@ -555,8 +555,8 @@ fn families() {
         assert!(config.matches_family(family));
         let other = if family == "windows" { "unix" } else { "windows" };
         assert!(!config.matches_family(other));
-        assert!(check_ignore(&config, &format!("// ignore-{family}")));
-        assert!(!check_ignore(&config, &format!("// ignore-{other}")));
+        assert!(check_ignore(&config, &format!("//@ ignore-{family}")));
+        assert!(!check_ignore(&config, &format!("//@ ignore-{other}")));
     }
 }
 
@@ -566,10 +566,17 @@ fn ignore_mode() {
         // Indicate profiler support so that "coverage-run" tests aren't skipped.
         let config: Config = cfg().mode(mode).profiler_support(true).build();
         let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" };
+
         assert_ne!(mode, other);
         assert_eq!(config.mode, Mode::from_str(mode).unwrap());
         assert_ne!(config.mode, Mode::from_str(other).unwrap());
-        assert!(check_ignore(&config, &format!("// ignore-mode-{mode}")));
-        assert!(!check_ignore(&config, &format!("// ignore-mode-{other}")));
+
+        if mode == "ui" {
+            assert!(check_ignore(&config, &format!("//@ ignore-mode-{mode}")));
+            assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}")));
+        } else {
+            assert!(check_ignore(&config, &format!("// ignore-mode-{mode}")));
+            assert!(!check_ignore(&config, &format!("// ignore-mode-{other}")));
+        }
     }
 }
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 9319877472e..db4c4a28deb 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -1,3 +1,4 @@
+#![feature(generic_nonzero)]
 #![feature(rustc_private, stmt_expr_attributes)]
 #![allow(
     clippy::manual_range_contains,
@@ -19,7 +20,7 @@ extern crate rustc_session;
 extern crate tracing;
 
 use std::env::{self, VarError};
-use std::num::NonZeroU64;
+use std::num::NonZero;
 use std::path::PathBuf;
 use std::str::FromStr;
 
@@ -524,7 +525,7 @@ fn main() {
                 }
             }
         } else if let Some(param) = arg.strip_prefix("-Zmiri-track-alloc-id=") {
-            let ids: Vec<miri::AllocId> = match parse_comma_list::<NonZeroU64>(param) {
+            let ids: Vec<miri::AllocId> = match parse_comma_list::<NonZero<u64>>(param) {
                 Ok(ids) => ids.into_iter().map(miri::AllocId).collect(),
                 Err(err) =>
                     show_error!(
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index f50aaa292fd..711323b51c2 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -1,6 +1,6 @@
 use std::cell::RefCell;
 use std::fmt;
-use std::num::NonZeroU64;
+use std::num::NonZero;
 
 use smallvec::SmallVec;
 
@@ -12,22 +12,22 @@ use crate::*;
 pub mod stacked_borrows;
 pub mod tree_borrows;
 
-pub type CallId = NonZeroU64;
+pub type CallId = NonZero<u64>;
 
 /// Tracking pointer provenance
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct BorTag(NonZeroU64);
+pub struct BorTag(NonZero<u64>);
 
 impl BorTag {
     pub fn new(i: u64) -> Option<Self> {
-        NonZeroU64::new(i).map(BorTag)
+        NonZero::new(i).map(BorTag)
     }
 
     pub fn get(&self) -> u64 {
         self.0.get()
     }
 
-    pub fn inner(&self) -> NonZeroU64 {
+    pub fn inner(&self) -> NonZero<u64> {
         self.0
     }
 
@@ -183,7 +183,7 @@ impl GlobalStateInner {
             borrow_tracker_method,
             next_ptr_tag: BorTag::one(),
             base_ptr_tags: FxHashMap::default(),
-            next_call_id: NonZeroU64::new(1).unwrap(),
+            next_call_id: NonZero::new(1).unwrap(),
             protected_tags: FxHashMap::default(),
             tracked_pointer_tags,
             tracked_call_ids,
@@ -205,7 +205,7 @@ impl GlobalStateInner {
         if self.tracked_call_ids.contains(&call_id) {
             machine.emit_diagnostic(NonHaltingDiagnostic::CreatedCallId(call_id));
         }
-        self.next_call_id = NonZeroU64::new(call_id.get() + 1).unwrap();
+        self.next_call_id = NonZero::new(call_id.get() + 1).unwrap();
         FrameState { call_id, protected_tags: SmallVec::new() }
     }
 
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index 9a848d50341..35dcfecbbe3 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -1,5 +1,4 @@
 use std::collections::VecDeque;
-use std::num::NonZeroU32;
 
 use rustc_index::Idx;
 use rustc_middle::ty::layout::TyAndLayout;
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index 68631190325..956a02ded0f 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -1,5 +1,4 @@
 use std::collections::{hash_map::Entry, VecDeque};
-use std::num::NonZeroU32;
 use std::ops::Not;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -24,12 +23,12 @@ macro_rules! declare_id {
         /// 0 is used to indicate that the id was not yet assigned and,
         /// therefore, is not a valid identifier.
         #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
-        pub struct $name(NonZeroU32);
+        pub struct $name(std::num::NonZero<u32>);
 
         impl SyncId for $name {
             // Panics if `id == 0`.
             fn from_u32(id: u32) -> Self {
-                Self(NonZeroU32::new(id).unwrap())
+                Self(std::num::NonZero::new(id).unwrap())
             }
             fn to_u32(&self) -> u32 {
                 self.0.get()
@@ -42,11 +41,11 @@ macro_rules! declare_id {
                 // therefore, need to shift by one when converting from an index
                 // into a vector.
                 let shifted_idx = u32::try_from(idx).unwrap().checked_add(1).unwrap();
-                $name(NonZeroU32::new(shifted_idx).unwrap())
+                $name(std::num::NonZero::new(shifted_idx).unwrap())
             }
             fn index(self) -> usize {
                 // See the comment in `Self::new`.
-                // (This cannot underflow because self is NonZeroU32.)
+                // (This cannot underflow because `self.0` is `NonZero<u32>`.)
                 usize::try_from(self.0.get() - 1).unwrap()
             }
         }
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 7825673db00..d47f446716b 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -1,5 +1,5 @@
 use std::fmt::{self, Write};
-use std::num::NonZeroU64;
+use std::num::NonZero;
 
 use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Level};
 use rustc_span::{SpanData, Symbol, DUMMY_SP};
@@ -110,7 +110,7 @@ pub enum NonHaltingDiagnostic {
     /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
     ///
     /// new_perm is `None` for base tags.
-    CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
+    CreatedPointerTag(NonZero<u64>, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
     /// This `Item` was popped from the borrow stack. The string explains the reason.
     PoppedPointerTag(Item, String),
     CreatedCallId(CallId),
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 932a35d9bf0..d9b4363d604 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -1,6 +1,6 @@
 use std::cmp;
 use std::iter;
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 use std::time::Duration;
 
 use rustc_apfloat::ieee::{Double, Single};
@@ -572,7 +572,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             fn visit_union(
                 &mut self,
                 _v: &MPlaceTy<'tcx, Provenance>,
-                _fields: NonZeroUsize,
+                _fields: NonZero<usize>,
             ) -> InterpResult<'tcx> {
                 bug!("we should have already handled unions in `visit_value`")
             }
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index adc547aa6cd..c567949102f 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -1,6 +1,7 @@
 #![feature(rustc_private)]
 #![feature(cell_update)]
 #![feature(float_gamma)]
+#![feature(generic_nonzero)]
 #![feature(map_try_insert)]
 #![feature(never_type)]
 #![feature(try_blocks)]
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index f4d69055344..0645c1f176e 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -475,7 +475,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [id, show_unnamed] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let id = this.read_scalar(id)?.to_u64()?;
                 let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?;
-                if let Some(id) = std::num::NonZeroU64::new(id) {
+                if let Some(id) = std::num::NonZero::new(id) {
                     this.print_borrow_state(AllocId(id), show_unnamed)?;
                 }
             }
diff --git a/src/tools/miri/tests/pass/intrinsics.rs b/src/tools/miri/tests/pass/intrinsics.rs
index 8e46bd7ad48..0dda5aadce2 100644
--- a/src/tools/miri/tests/pass/intrinsics.rs
+++ b/src/tools/miri/tests/pass/intrinsics.rs
@@ -37,7 +37,7 @@ fn main() {
     let mut saw_false = false;
 
     for _ in 0..50 {
-        if unsafe { intrinsics::is_val_statically_known(0) } {
+        if intrinsics::is_val_statically_known(0) {
             saw_true = true;
         } else {
             saw_false = true;
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 8b0e80a94b0..a8aae6f5bc9 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -55,11 +55,14 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
     "// CHECK",
     "// EMIT_MIR",
     "// compile-flags",
+    "//@ compile-flags",
     "// error-pattern",
+    "//@ error-pattern",
     "// gdb",
     "// lldb",
     "// cdb",
     "// normalize-stderr-test",
+    "//@ normalize-stderr-test",
 ];
 
 // Intentionally written in decimal rather than hex
@@ -128,7 +131,15 @@ fn should_ignore(line: &str) -> bool {
     // This mirrors the regex in src/tools/compiletest/src/runtest.rs, please
     // update both if either are changed.
     let re = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
-    re.is_match(line) || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
+    // For `ui_test`-style UI test directives, also ignore
+    // - `//@[rev] compile-flags`
+    // - `//@[rev] normalize-stderr-test`
+    let ui_test_long_directives =
+        Regex::new("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*")
+            .unwrap();
+    re.is_match(line)
+        || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
+        || ui_test_long_directives.is_match(line)
 }
 
 /// Returns `true` if `line` is allowed to be longer than the normal limit.
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 1dbd221fde5..5517b9fdcec 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -14,8 +14,9 @@ use std::path::{Path, PathBuf};
 // #73494.
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
+
 const ISSUES_ENTRY_LIMIT: usize = 1781;
-const ROOT_ENTRY_LIMIT: usize = 870;
+const ROOT_ENTRY_LIMIT: usize = 871;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files