From 1fbabc622f1791dbbddf2ab5cda7c392a21d94ba Mon Sep 17 00:00:00 2001
From: Zalathar <Zalathar@users.noreply.github.com>
Date: Sat, 4 May 2024 18:30:06 +1000
Subject: [PATCH 1/3] Include the line number in tidy's `iter_header`

---
 src/tools/tidy/src/iter_header.rs                          | 7 ++++---
 src/tools/tidy/src/target_specific_tests.rs                | 2 +-
 .../tidy/src/tests_revision_unpaired_stdout_stderr.rs      | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/tools/tidy/src/iter_header.rs b/src/tools/tidy/src/iter_header.rs
index ae635904607e7..684c789039f6b 100644
--- a/src/tools/tidy/src/iter_header.rs
+++ b/src/tools/tidy/src/iter_header.rs
@@ -3,6 +3,7 @@ const COMMENT: &str = "//@";
 /// A header line, like `//@name: value` consists of the prefix `//@` and the directive
 /// `name: value`. It is also possibly revisioned, e.g. `//@[revision] name: value`.
 pub(crate) struct HeaderLine<'ln> {
+    pub(crate) line_number: usize,
     pub(crate) revision: Option<&'ln str>,
     pub(crate) directive: &'ln str,
 }
@@ -11,7 +12,7 @@ pub(crate) struct HeaderLine<'ln> {
 ///
 /// Adjusted from compiletest/src/header.rs.
 pub(crate) fn iter_header<'ln>(contents: &'ln str, it: &mut dyn FnMut(HeaderLine<'ln>)) {
-    for ln in contents.lines() {
+    for (line_number, ln) in (1..).zip(contents.lines()) {
         let ln = ln.trim();
 
         // We're left with potentially `[rev]name: value`.
@@ -24,9 +25,9 @@ pub(crate) fn iter_header<'ln>(contents: &'ln str, it: &mut dyn FnMut(HeaderLine
                 panic!("malformed revision directive: expected `//@[rev]`, found `{ln}`");
             };
             // We trimmed off the `[rev]` portion, left with `name: value`.
-            it(HeaderLine { revision: Some(revision), directive: remainder.trim() });
+            it(HeaderLine { line_number, revision: Some(revision), directive: remainder.trim() });
         } else {
-            it(HeaderLine { revision: None, directive: remainder.trim() });
+            it(HeaderLine { line_number, revision: None, directive: remainder.trim() });
         }
     }
 }
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index cb242bff05d1d..c876aae494dd5 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -20,7 +20,7 @@ pub fn check(path: &Path, bad: &mut bool) {
     crate::walk::walk(path, |path, _is_dir| filter_not_rust(path), &mut |entry, content| {
         let file = entry.path().display();
         let mut header_map = BTreeMap::new();
-        iter_header(content, &mut |HeaderLine { revision, directive }| {
+        iter_header(content, &mut |HeaderLine { revision, directive, .. }| {
             if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
                 let info = header_map.entry(revision).or_insert(RevisionInfo::default());
                 let comp_vec = info.llvm_components.get_or_insert(Vec::new());
diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
index a0773c85bef5e..00edf99a30dbd 100644
--- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
+++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
@@ -61,7 +61,7 @@ pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
             let contents = std::fs::read_to_string(test).unwrap();
 
             // Collect directives.
-            iter_header(&contents, &mut |HeaderLine { revision, directive }| {
+            iter_header(&contents, &mut |HeaderLine { revision, directive, .. }| {
                 // We're trying to *find* `//@ revision: xxx` directives themselves, not revisioned
                 // directives.
                 if revision.is_some() {

From be590d388714db600f20224464f53a5eb08fe3b9 Mon Sep 17 00:00:00 2001
From: Zalathar <Zalathar@users.noreply.github.com>
Date: Sat, 4 May 2024 18:06:16 +1000
Subject: [PATCH 2/3] Tidy check for test revisions that are mentioned but not
 declared

If a `[revision]` name appears in a test header directive or error annotation,
but isn't declared in the `//@ revisions:` header, that is almost always a
mistake.

In cases where a revision needs to be temporarily disabled, adding it to an
`//@ unused-revision-names:` header will suppress these checks for that name.

Adding the wildcard name `*` to the unused list will suppress these checks for
the entire file.
---
 src/tools/compiletest/src/header.rs    |   2 +
 src/tools/tidy/src/lib.rs              |   1 +
 src/tools/tidy/src/main.rs             |   1 +
 src/tools/tidy/src/unknown_revision.rs | 114 +++++++++++++++++++++++++
 4 files changed, 118 insertions(+)
 create mode 100644 src/tools/tidy/src/unknown_revision.rs

diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 42159b147d582..c7c807d3e6846 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -932,6 +932,8 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "test-mir-pass",
     "unset-exec-env",
     "unset-rustc-env",
+    // Used by the tidy check `unknown_revision`.
+    "unused-revision-names",
     // tidy-alphabetical-end
 ];
 
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index c15081a56d1a8..ae9d2b8b8dc87 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -87,6 +87,7 @@ pub mod tests_placement;
 pub mod tests_revision_unpaired_stdout_stderr;
 pub mod ui_tests;
 pub mod unit_tests;
+pub mod unknown_revision;
 pub mod unstable_book;
 pub mod walk;
 pub mod x_version;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 77691815830a6..1d2b2e4d03472 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -110,6 +110,7 @@ fn main() {
         check!(rustdoc_gui_tests, &tests_path);
         check!(rustdoc_css_themes, &librustdoc_path);
         check!(known_bug, &crashes_path);
+        check!(unknown_revision, &tests_path);
 
         // Checks that only make sense for the compiler.
         check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
diff --git a/src/tools/tidy/src/unknown_revision.rs b/src/tools/tidy/src/unknown_revision.rs
new file mode 100644
index 0000000000000..abfff1d632ad8
--- /dev/null
+++ b/src/tools/tidy/src/unknown_revision.rs
@@ -0,0 +1,114 @@
+//! Checks that test revision names appearing in header directives and error
+//! annotations have actually been declared in `revisions`.
+
+// FIXME(jieyouxu) Ideally these checks would be integrated into compiletest's
+// own directive and revision handling, but for now they've been split out as a
+// separate `tidy` check to avoid making compiletest even messier.
+
+use std::collections::{BTreeSet, HashMap, HashSet};
+use std::path::Path;
+use std::sync::OnceLock;
+
+use ignore::DirEntry;
+use regex::Regex;
+
+use crate::iter_header::{iter_header, HeaderLine};
+use crate::walk::{filter_dirs, filter_not_rust, walk};
+
+pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
+    walk(
+        tests_path.as_ref(),
+        |path, is_dir| {
+            filter_dirs(path) || filter_not_rust(path) || {
+                // Auxiliary source files for incremental tests can refer to revisions
+                // declared by the main file, which this check doesn't handle.
+                is_dir && path.file_name().is_some_and(|name| name == "auxiliary")
+            }
+        },
+        &mut |entry, contents| visit_test_file(entry, contents, bad),
+    );
+}
+
+fn visit_test_file(entry: &DirEntry, contents: &str, bad: &mut bool) {
+    let mut revisions = HashSet::new();
+    let mut unused_revision_names = HashSet::new();
+
+    // Maps each mentioned revision to the first line it was mentioned on.
+    let mut mentioned_revisions = HashMap::<&str, usize>::new();
+    let mut add_mentioned_revision = |line_number: usize, revision| {
+        let first_line = mentioned_revisions.entry(revision).or_insert(line_number);
+        *first_line = (*first_line).min(line_number);
+    };
+
+    // Scan all `//@` headers to find declared revisions and mentioned revisions.
+    iter_header(contents, &mut |HeaderLine { line_number, revision, directive }| {
+        if let Some(revs) = directive.strip_prefix("revisions:") {
+            revisions.extend(revs.split_whitespace());
+        } else if let Some(revs) = directive.strip_prefix("unused-revision-names:") {
+            unused_revision_names.extend(revs.split_whitespace());
+        }
+
+        if let Some(revision) = revision {
+            add_mentioned_revision(line_number, revision);
+        }
+    });
+
+    // If a wildcard appears in `unused-revision-names`, skip all revision name
+    // checking for this file.
+    if unused_revision_names.contains(&"*") {
+        return;
+    }
+
+    // Scan all `//[rev]~` error annotations to find mentioned revisions.
+    for_each_error_annotation_revision(contents, &mut |ErrorAnnRev { line_number, revision }| {
+        add_mentioned_revision(line_number, revision);
+    });
+
+    let path = entry.path().display();
+
+    // Fail if any revision names appear in both places, since that's probably a mistake.
+    for rev in revisions.intersection(&unused_revision_names).copied().collect::<BTreeSet<_>>() {
+        tidy_error!(
+            bad,
+            "revision name [{rev}] appears in both `revisions` and `unused-revision-names` in {path}"
+        );
+    }
+
+    // Compute the set of revisions that were mentioned but not declared,
+    // sorted by the first line number they appear on.
+    let mut bad_revisions = mentioned_revisions
+        .into_iter()
+        .filter(|(rev, _)| !revisions.contains(rev) && !unused_revision_names.contains(rev))
+        .map(|(rev, line_number)| (line_number, rev))
+        .collect::<Vec<_>>();
+    bad_revisions.sort();
+
+    for (line_number, rev) in bad_revisions {
+        tidy_error!(bad, "unknown revision [{rev}] at {path}:{line_number}");
+    }
+}
+
+struct ErrorAnnRev<'a> {
+    line_number: usize,
+    revision: &'a str,
+}
+
+fn for_each_error_annotation_revision<'a>(
+    contents: &'a str,
+    callback: &mut dyn FnMut(ErrorAnnRev<'a>),
+) {
+    let error_regex = {
+        // Simplified from the regex used by `parse_expected` in `src/tools/compiletest/src/errors.rs`,
+        // because we only care about extracting revision names.
+        static RE: OnceLock<Regex> = OnceLock::new();
+        RE.get_or_init(|| Regex::new(r"//\[(?<revs>[^]]*)\]~").unwrap())
+    };
+
+    for (line_number, line) in (1..).zip(contents.lines()) {
+        let Some(captures) = error_regex.captures(line) else { continue };
+
+        for revision in captures.name("revs").unwrap().as_str().split(',') {
+            callback(ErrorAnnRev { line_number, revision });
+        }
+    }
+}

From 14d56e833848b94c8c257c53886d0331a4ac735e Mon Sep 17 00:00:00 2001
From: Zalathar <Zalathar@users.noreply.github.com>
Date: Sat, 4 May 2024 18:58:31 +1000
Subject: [PATCH 3/3] Fix test problems discovered by the revision check

Most of these changes either add revision names that were apparently missing,
or explicitly mark a revision name as currently unused.
---
 .../bound-lifetime-constrained.ok.stderr      |  8 +++++++
 .../bound-lifetime-constrained.rs             |  2 +-
 ...ion-sharing-interference.nll_target.stderr |  6 ++---
 ...o-phase-activation-sharing-interference.rs |  8 ++-----
 ...ccess-during-reservation.nll_target.stderr |  4 ++--
 ...o-phase-allow-access-during-reservation.rs |  1 +
 .../two-phase-nonrecv-autoref.base.stderr     | 22 +++++++++----------
 .../ui/borrowck/two-phase-nonrecv-autoref.rs  |  1 +
 ...ion-sharing-interference.nll_target.stderr |  2 +-
 ...-phase-reservation-sharing-interference.rs |  1 +
 .../exhaustive-names-values.empty_cfg.stderr  |  2 +-
 tests/ui/check-cfg/exhaustive-names-values.rs | 10 ++++-----
 .../ui/check-cfg/values-none.concat_1.stderr  | 13 +++++++++++
 .../ui/check-cfg/values-none.concat_2.stderr  | 13 +++++++++++
 tests/ui/check-cfg/values-none.rs             |  2 +-
 tests/ui/check-cfg/values-none.simple.stderr  | 13 +++++++++++
 .../param-env-region-infer.current.stderr     |  2 +-
 tests/ui/dyn-star/param-env-region-infer.rs   |  3 ++-
 .../instrument-coverage/coverage-options.rs   |  2 +-
 .../meta-expected-error-wrong-rev.a.stderr    |  2 +-
 .../ui/meta/meta-expected-error-wrong-rev.rs  |  1 +
 tests/ui/methods/method-lookup-order.rs       |  1 +
 tests/ui/target-feature/tied-features-cli.rs  |  2 +-
 .../ui/transmutability/primitives/bool-mut.rs |  1 -
 .../primitives/bool-mut.stderr                |  4 ++--
 tests/ui/version/version-info-flags.rs        |  2 +-
 26 files changed, 87 insertions(+), 41 deletions(-)
 create mode 100644 tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
 create mode 100644 tests/ui/check-cfg/values-none.concat_1.stderr
 create mode 100644 tests/ui/check-cfg/values-none.concat_2.stderr
 create mode 100644 tests/ui/check-cfg/values-none.simple.stderr

diff --git a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
new file mode 100644
index 0000000000000..9082044fe068b
--- /dev/null
+++ b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/bound-lifetime-constrained.rs:48:1
+   |
+LL | fn main() { }
+   | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs
index 880d350bdf602..1dc3b2f5c2b77 100644
--- a/tests/ui/associated-types/bound-lifetime-constrained.rs
+++ b/tests/ui/associated-types/bound-lifetime-constrained.rs
@@ -1,4 +1,4 @@
-//@ revisions: func object clause
+//@ revisions: func object clause ok
 
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
diff --git a/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
index aacf178932e6e..6cd64c58cab2f 100644
--- a/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-activation-sharing-interference.rs:28:15
+  --> $DIR/two-phase-activation-sharing-interference.rs:29:15
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
@@ -10,7 +10,7 @@ LL |     *y += 1;
    |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-activation-sharing-interference.rs:36:13
+  --> $DIR/two-phase-activation-sharing-interference.rs:37:13
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
@@ -32,7 +32,7 @@ LL |     *y += 1;
    |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-activation-sharing-interference.rs:58:14
+  --> $DIR/two-phase-activation-sharing-interference.rs:56:14
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
diff --git a/tests/ui/borrowck/two-phase-activation-sharing-interference.rs b/tests/ui/borrowck/two-phase-activation-sharing-interference.rs
index beee9916fca2c..1b4526a13a85b 100644
--- a/tests/ui/borrowck/two-phase-activation-sharing-interference.rs
+++ b/tests/ui/borrowck/two-phase-activation-sharing-interference.rs
@@ -1,6 +1,7 @@
 //@ revisions: nll_target
 
 // The following revisions are disabled due to missing support from two-phase beyond autorefs
+//@ unused-revision-names: nll_beyond
 //@[nll_beyond] compile-flags: -Z two-phase-beyond-autoref
 
 // This is an important corner case pointed out by Niko: one is
@@ -36,8 +37,7 @@ fn not_ok() {
     let z = &x;
     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
     *y += 1;
-    //[lxl_beyond]~^   ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    //[nll_beyond]~^^  ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
+    //[nll_beyond]~^   ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
     read(z);
 }
 
@@ -48,8 +48,6 @@ fn should_be_ok_with_nll() {
     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
     read(z);
     *y += 1;
-    //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    // (okay with (generalized) nll today)
 }
 
 fn should_also_eventually_be_ok_with_nll() {
@@ -58,8 +56,6 @@ fn should_also_eventually_be_ok_with_nll() {
     let _z = &x;
     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
     *y += 1;
-    //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
-    // (okay with (generalized) nll today)
 }
 
 fn main() { }
diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
index 1356c80493cdb..b7a1de02a4f61 100644
--- a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
@@ -1,5 +1,5 @@
 error[E0503]: cannot use `i` because it was mutably borrowed
-  --> $DIR/two-phase-allow-access-during-reservation.rs:26:19
+  --> $DIR/two-phase-allow-access-during-reservation.rs:27:19
    |
 LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
    |                   ------ `i` is borrowed here
@@ -11,7 +11,7 @@ LL |     /*3*/ *p += 1;        // (mutable borrow of `i` starts here, since `p`
    |           ------- borrow later used here
 
 error[E0503]: cannot use `i` because it was mutably borrowed
-  --> $DIR/two-phase-allow-access-during-reservation.rs:31:19
+  --> $DIR/two-phase-allow-access-during-reservation.rs:32:19
    |
 LL |     /*1*/ let p = &mut i; // (reservation of `i` starts here)
    |                   ------ `i` is borrowed here
diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs b/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs
index e6b2501c1ebde..6b5a2f5e62365 100644
--- a/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs
+++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs
@@ -1,6 +1,7 @@
 //@ revisions: nll_target
 
 // The following revisions are disabled due to missing support for two_phase_beyond_autoref
+//@ unused-revision-names: nll_beyond
 //@[nll_beyond] compile-flags: -Z two_phase_beyond_autoref
 
 // This is the second counter-example from Niko's blog post
diff --git a/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr b/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr
index e122977b9f2e0..c9d49b8756d87 100644
--- a/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr
+++ b/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
-  --> $DIR/two-phase-nonrecv-autoref.rs:50:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:51:11
    |
 LL |         f(f(10));
    |         - ^ second mutable borrow occurs here
@@ -8,7 +8,7 @@ LL |         f(f(10));
    |         first borrow later used by call
 
 error[E0382]: use of moved value: `f`
-  --> $DIR/two-phase-nonrecv-autoref.rs:57:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:58:11
    |
 LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
    |                                            - move occurs because `f` has type `Box<F>`, which does not implement the `Copy` trait
@@ -18,7 +18,7 @@ LL |         f(f(10));
    |         value moved here
 
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
-  --> $DIR/two-phase-nonrecv-autoref.rs:62:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:63:11
    |
 LL |         f(f(10));
    |         - ^ second mutable borrow occurs here
@@ -27,7 +27,7 @@ LL |         f(f(10));
    |         first borrow later used by call
 
 error[E0382]: use of moved value: `f`
-  --> $DIR/two-phase-nonrecv-autoref.rs:69:11
+  --> $DIR/two-phase-nonrecv-autoref.rs:70:11
    |
 LL |     fn twice_ten_oo(f: Box<dyn FnOnce(i32) -> i32>) {
    |                     - move occurs because `f` has type `Box<dyn FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
@@ -37,7 +37,7 @@ LL |         f(f(10));
    |         value moved here
 
 error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:107:27
+  --> $DIR/two-phase-nonrecv-autoref.rs:108:27
    |
 LL |     double_access(&mut a, &a);
    |     ------------- ------  ^^ immutable borrow occurs here
@@ -46,7 +46,7 @@ LL |     double_access(&mut a, &a);
    |     mutable borrow later used by call
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:132:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:133:7
    |
 LL |     i[i[3]] = 4;
    |     --^----
@@ -56,18 +56,18 @@ LL |     i[i[3]] = 4;
    |     mutable borrow occurs here
    |
 help: try adding a local storing this...
-  --> $DIR/two-phase-nonrecv-autoref.rs:132:8
+  --> $DIR/two-phase-nonrecv-autoref.rs:133:8
    |
 LL |     i[i[3]] = 4;
    |        ^^^
 help: ...and then using that local here
-  --> $DIR/two-phase-nonrecv-autoref.rs:132:6
+  --> $DIR/two-phase-nonrecv-autoref.rs:133:6
    |
 LL |     i[i[3]] = 4;
    |      ^^^^^^
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:138:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:139:7
    |
 LL |     i[i[3]] = i[4];
    |     --^----
@@ -77,12 +77,12 @@ LL |     i[i[3]] = i[4];
    |     mutable borrow occurs here
    |
 help: try adding a local storing this...
-  --> $DIR/two-phase-nonrecv-autoref.rs:138:8
+  --> $DIR/two-phase-nonrecv-autoref.rs:139:8
    |
 LL |     i[i[3]] = i[4];
    |        ^^^
 help: ...and then using that local here
-  --> $DIR/two-phase-nonrecv-autoref.rs:138:6
+  --> $DIR/two-phase-nonrecv-autoref.rs:139:6
    |
 LL |     i[i[3]] = i[4];
    |      ^^^^^^
diff --git a/tests/ui/borrowck/two-phase-nonrecv-autoref.rs b/tests/ui/borrowck/two-phase-nonrecv-autoref.rs
index f52e9c2e3fdcb..3a8ab4ef3b0f4 100644
--- a/tests/ui/borrowck/two-phase-nonrecv-autoref.rs
+++ b/tests/ui/borrowck/two-phase-nonrecv-autoref.rs
@@ -1,5 +1,6 @@
 //@ revisions: base
 
+//@ unused-revision-names: g2p
 //@[g2p]compile-flags: -Z two-phase-beyond-autoref
 // the above revision is disabled until two-phase-beyond-autoref support is better
 
diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
index b1e4392989fee..5eda482801276 100644
--- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
-  --> $DIR/two-phase-reservation-sharing-interference.rs:32:17
+  --> $DIR/two-phase-reservation-sharing-interference.rs:33:17
    |
 LL |         let shared = &vec;
    |                      ---- immutable borrow occurs here
diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
index b6bcf7b66173e..61446577db29b 100644
--- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
+++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
@@ -1,6 +1,7 @@
 //@ revisions: nll_target
 
 // The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs
+//@ unused-revision-names: nll_beyond
 //@[nll_beyond]compile-flags: -Z two-phase-beyond-autoref
 //@[nll_beyond]should-fail
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index c196f607376fb..755373d7b77af 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -30,7 +30,7 @@ LL | #[cfg(feature = "unk")]
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
-  --> $DIR/exhaustive-names-values.rs:25:7
+  --> $DIR/exhaustive-names-values.rs:24:7
    |
 LL | #[cfg(feature = "std")]
    |       ^^^^^^^^^^^^^^^
diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs
index a6190f15dbb4b..7b2d89b5781dd 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.rs
+++ b/tests/ui/check-cfg/exhaustive-names-values.rs
@@ -16,15 +16,13 @@ pub fn f() {}
 pub fn f() {}
 
 #[cfg(feature = "unk")]
-//[empty_names_values]~^ WARNING unexpected `cfg` condition name
-//[empty_cfg]~^^ WARNING unexpected `cfg` condition name
-//[feature]~^^^ WARNING unexpected `cfg` condition value
-//[full]~^^^^ WARNING unexpected `cfg` condition value
+//[empty_cfg]~^ WARNING unexpected `cfg` condition name
+//[feature]~^^ WARNING unexpected `cfg` condition value
+//[full]~^^^ WARNING unexpected `cfg` condition value
 pub fn feat() {}
 
 #[cfg(feature = "std")]
-//[empty_names_values]~^ WARNING unexpected `cfg` condition name
-//[empty_cfg]~^^ WARNING unexpected `cfg` condition name
+//[empty_cfg]~^ WARNING unexpected `cfg` condition name
 pub fn feat() {}
 
 #[cfg(windows)]
diff --git a/tests/ui/check-cfg/values-none.concat_1.stderr b/tests/ui/check-cfg/values-none.concat_1.stderr
new file mode 100644
index 0000000000000..b8f0b02b4c563
--- /dev/null
+++ b/tests/ui/check-cfg/values-none.concat_1.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition value: `bar`
+  --> $DIR/values-none.rs:16:7
+   |
+LL | #[cfg(foo = "bar")]
+   |       ^^^^^^^^^^^
+   |
+   = note: expected values for `foo` are: (none), `too`
+   = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/values-none.concat_2.stderr b/tests/ui/check-cfg/values-none.concat_2.stderr
new file mode 100644
index 0000000000000..b8f0b02b4c563
--- /dev/null
+++ b/tests/ui/check-cfg/values-none.concat_2.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition value: `bar`
+  --> $DIR/values-none.rs:16:7
+   |
+LL | #[cfg(foo = "bar")]
+   |       ^^^^^^^^^^^
+   |
+   = note: expected values for `foo` are: (none), `too`
+   = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/values-none.rs b/tests/ui/check-cfg/values-none.rs
index 6856d2f33af07..447fde2bfcce0 100644
--- a/tests/ui/check-cfg/values-none.rs
+++ b/tests/ui/check-cfg/values-none.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 //
 //@ no-auto-check-cfg
-//@ revisions: explicit implicit
+//@ revisions: explicit implicit simple concat_1 concat_2
 //@ [explicit]compile-flags: --check-cfg=cfg(foo,values(none()))
 //@ [implicit]compile-flags: --check-cfg=cfg(foo)
 //@ [simple]  compile-flags: --check-cfg=cfg(foo,values(none(),"too"))
diff --git a/tests/ui/check-cfg/values-none.simple.stderr b/tests/ui/check-cfg/values-none.simple.stderr
new file mode 100644
index 0000000000000..b8f0b02b4c563
--- /dev/null
+++ b/tests/ui/check-cfg/values-none.simple.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition value: `bar`
+  --> $DIR/values-none.rs:16:7
+   |
+LL | #[cfg(foo = "bar")]
+   |       ^^^^^^^^^^^
+   |
+   = note: expected values for `foo` are: (none), `too`
+   = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/dyn-star/param-env-region-infer.current.stderr b/tests/ui/dyn-star/param-env-region-infer.current.stderr
index b50117c1efb40..6e464c17014cc 100644
--- a/tests/ui/dyn-star/param-env-region-infer.current.stderr
+++ b/tests/ui/dyn-star/param-env-region-infer.current.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/param-env-region-infer.rs:19:10
+  --> $DIR/param-env-region-infer.rs:20:10
    |
 LL |     t as _
    |          ^ cannot infer type
diff --git a/tests/ui/dyn-star/param-env-region-infer.rs b/tests/ui/dyn-star/param-env-region-infer.rs
index c53861065c7da..842964ad284cc 100644
--- a/tests/ui/dyn-star/param-env-region-infer.rs
+++ b/tests/ui/dyn-star/param-env-region-infer.rs
@@ -1,9 +1,10 @@
 //@ revisions: current
 //@ incremental
 
-// FIXME(-Znext-solver): THis currently results in unstable query results:
+// FIXME(-Znext-solver): This currently results in unstable query results:
 // `normalizes-to(opaque, opaque)` changes from `Maybe(Ambiguous)` to `Maybe(Overflow)`
 // once the hidden type of the opaque is already defined to be itself.
+//@ unused-revision-names: next
 
 // checks that we don't ICE if there are region inference variables in the environment
 // when computing `PointerLike` builtin candidates.
diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs
index 332da32e435dc..2a80ce4ab2e91 100644
--- a/tests/ui/instrument-coverage/coverage-options.rs
+++ b/tests/ui/instrument-coverage/coverage-options.rs
@@ -1,5 +1,5 @@
 //@ needs-profiler-support
-//@ revisions: block branch bad
+//@ revisions: block branch mcdc bad
 //@ compile-flags -Cinstrument-coverage
 
 //@ [block] check-pass
diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr
index 4221dd04cfaac..a489040f32df6 100644
--- a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr
+++ b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/meta-expected-error-wrong-rev.rs:13:18
+  --> $DIR/meta-expected-error-wrong-rev.rs:14:18
    |
 LL |     let x: u32 = 22_usize;
    |            ---   ^^^^^^^^ expected `u32`, found `usize`
diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.rs b/tests/ui/meta/meta-expected-error-wrong-rev.rs
index de27629948290..1c3a3fc492329 100644
--- a/tests/ui/meta/meta-expected-error-wrong-rev.rs
+++ b/tests/ui/meta/meta-expected-error-wrong-rev.rs
@@ -1,6 +1,7 @@
 //@ ignore-compare-mode-polonius
 
 //@ revisions: a
+//@ unused-revision-names: b
 //@ should-fail
 
 // This is a "meta-test" of the compilertest framework itself.  In
diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs
index f794e5a72415e..ad56da966867d 100644
--- a/tests/ui/methods/method-lookup-order.rs
+++ b/tests/ui/methods/method-lookup-order.rs
@@ -17,6 +17,7 @@
 // {mutbar_for_foo, valbar_for_etmut_foo} (which are lower precedent than the inherent `&mut self` method on `Foo`; e.g. b10101 *is* included.
 
 //@ revisions: b00001 b00010 b00011 b00100 b00101 b00110 b00111 b01000 b01001 b01100 b01101 b10000 b10001 b10010 b10011 b10101 b10111 b11000 b11001 b11101
+//@ unused-revision-names: b01010 b01011 b01110 b01111 b10100 b10110 b11010 b11011 b11100 b11110 b11111
 
 //@ compile-flags: --check-cfg=cfg(inherent_mut,bar_for_foo,mutbar_for_foo)
 //@ compile-flags: --check-cfg=cfg(valbar_for_et_foo,valbar_for_etmut_foo)
diff --git a/tests/ui/target-feature/tied-features-cli.rs b/tests/ui/target-feature/tied-features-cli.rs
index 1168245461fd0..17c13826ce9e6 100644
--- a/tests/ui/target-feature/tied-features-cli.rs
+++ b/tests/ui/target-feature/tied-features-cli.rs
@@ -1,4 +1,4 @@
-//@ revisions: one two three
+//@ revisions: one two three four
 //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
 //@ needs-llvm-components: aarch64
 //
diff --git a/tests/ui/transmutability/primitives/bool-mut.rs b/tests/ui/transmutability/primitives/bool-mut.rs
index 5f3f4f3a8c5b4..09b6d582d871c 100644
--- a/tests/ui/transmutability/primitives/bool-mut.rs
+++ b/tests/ui/transmutability/primitives/bool-mut.rs
@@ -1,5 +1,4 @@
 //@ check-fail
-//@[next] compile-flags: -Znext-solver
 
 #![feature(transmutability)]
 mod assert {
diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr
index 464c2755e11b6..a6cf146659e62 100644
--- a/tests/ui/transmutability/primitives/bool-mut.stderr
+++ b/tests/ui/transmutability/primitives/bool-mut.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `u8` cannot be safely transmuted into `bool`
-  --> $DIR/bool-mut.rs:15:50
+  --> $DIR/bool-mut.rs:14:50
    |
 LL |     assert::is_transmutable::<&'static mut bool, &'static mut u8>()
    |                                                  ^^^^^^^^^^^^^^^ at least one value of `u8` isn't a bit-valid value of `bool`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/bool-mut.rs:10:14
+  --> $DIR/bool-mut.rs:9:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/version/version-info-flags.rs b/tests/ui/version/version-info-flags.rs
index 612113452c41f..96be9c5385b28 100644
--- a/tests/ui/version/version-info-flags.rs
+++ b/tests/ui/version/version-info-flags.rs
@@ -4,6 +4,6 @@
 //@ check-pass
 //@[version] compile-flags: -V
 //@[verbose-version] compile-flags: -vV
-//@[long-verbose-verison] compile-flags: --version --verbose
+//@[long-verbose-version] compile-flags: --version --verbose
 
 fn main() {}