about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-10 16:26:18 +0000
committerbors <bors@rust-lang.org>2024-03-10 16:26:18 +0000
commitaf69f4c48c1e1cfbb9ba43b376edcfbdd8cfbca4 (patch)
tree48fd75ad5716e7283c99a0a168a9fa4cb1165d81
parent9bd88ef61241d6417c4835c97bf4617cc0a71a80 (diff)
parent64dda8c8378d985136dea2839bbb91c390aba356 (diff)
downloadrust-af69f4c48c1e1cfbb9ba43b376edcfbdd8cfbca4.tar.gz
rust-af69f4c48c1e1cfbb9ba43b376edcfbdd8cfbca4.zip
Auto merge of #121561 - jieyouxu:compiletest-directive-typo-check, r=onur-ozkan
Detect typos for compiletest test directives

Checks directives against a known list of compiletest directives collected during migration from legacy-style compiletest directives. A suggestion for the best matching known directive will be made if an invalid directive is found.

This PR does not attempt to implement checks for Makefile directives because they still have the problem of regular comments and directives sharing the same comment prefix `#`.

Closes #83551.
-rw-r--r--src/tools/compiletest/src/header.rs128
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/error_annotation.rs6
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/known_directive.rs4
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs1
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile1
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs1
-rw-r--r--src/tools/compiletest/src/header/tests.rs62
-rw-r--r--tests/ui/borrowck/two-phase-reservation-sharing-interference.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.rs6
10 files changed, 180 insertions, 43 deletions
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index f15761354f7..213e2a63517 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -680,7 +680,8 @@ pub fn line_directive<'line>(
 /// 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] = &[
+const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
+    // tidy-alphabetical-start
     "assembly-output",
     "aux-build",
     "aux-crate",
@@ -693,6 +694,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "check-stdout",
     "check-test-line-numbers-match",
     "compile-flags",
+    "count",
     "dont-check-compiler-stderr",
     "dont-check-compiler-stdout",
     "dont-check-failure-status",
@@ -700,6 +702,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "error-pattern",
     "exec-env",
     "failure-status",
+    "filecheck-flags",
     "forbid-output",
     "force-host",
     "ignore-16bit",
@@ -716,6 +719,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-compare-mode-polonius",
     "ignore-cross-compile",
     "ignore-debug",
+    "ignore-eabi",
     "ignore-emscripten",
     "ignore-endian-big",
     "ignore-freebsd",
@@ -731,14 +735,30 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-lldb",
     "ignore-llvm-version",
     "ignore-loongarch64",
+    "ignore-macabi",
     "ignore-macos",
+    "ignore-mode-assembly",
+    "ignore-mode-codegen",
+    "ignore-mode-codegen-units",
     "ignore-mode-coverage-map",
     "ignore-mode-coverage-run",
+    "ignore-mode-debuginfo",
+    "ignore-mode-incremental",
+    "ignore-mode-js-doc-test",
+    "ignore-mode-mir-opt",
+    "ignore-mode-pretty",
+    "ignore-mode-run-make",
+    "ignore-mode-run-pass-valgrind",
+    "ignore-mode-rustdoc",
+    "ignore-mode-rustdoc-json",
+    "ignore-mode-ui",
+    "ignore-mode-ui-fulldeps",
     "ignore-msp430",
     "ignore-msvc",
     "ignore-musl",
     "ignore-netbsd",
     "ignore-nightly",
+    "ignore-none",
     "ignore-nto",
     "ignore-nvptx64",
     "ignore-openbsd",
@@ -750,18 +770,27 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-spirv",
     "ignore-stable",
     "ignore-stage1",
+    "ignore-stage2",
     "ignore-test",
+    "ignore-thumb",
     "ignore-thumbv8m.base-none-eabi",
     "ignore-thumbv8m.main-none-eabi",
+    "ignore-unix",
+    "ignore-unknown",
     "ignore-uwp",
     "ignore-vxworks",
+    "ignore-wasi",
     "ignore-wasm",
     "ignore-wasm32",
     "ignore-wasm32-bare",
+    "ignore-wasm64",
     "ignore-windows",
     "ignore-windows-gnu",
+    "ignore-x32",
     "ignore-x86",
+    "ignore-x86_64",
     "ignore-x86_64-apple-darwin",
+    "ignore-x86_64-unknown-linux-gnu",
     "incremental",
     "known-bug",
     "llvm-cov-flags",
@@ -769,9 +798,11 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "min-gdb-version",
     "min-lldb-version",
     "min-llvm-version",
+    "min-system-llvm-version",
     "needs-asm-support",
     "needs-dlltool",
     "needs-dynamic-linking",
+    "needs-git-hash",
     "needs-llvm-components",
     "needs-profiler-support",
     "needs-relocation-model-pic",
@@ -779,6 +810,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "needs-rust-lldb",
     "needs-sanitizer-address",
     "needs-sanitizer-cfi",
+    "needs-sanitizer-dataflow",
     "needs-sanitizer-hwaddress",
     "needs-sanitizer-leak",
     "needs-sanitizer-memory",
@@ -801,6 +833,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "only-aarch64",
     "only-arm",
     "only-avr",
+    "only-beta",
     "only-bpf",
     "only-cdb",
     "only-gnu",
@@ -818,6 +851,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "only-riscv64",
     "only-sparc",
     "only-sparc64",
+    "only-stable",
     "only-thumb",
     "only-wasm32",
     "only-wasm32-bare",
@@ -825,6 +859,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "only-x86",
     "only-x86_64",
     "only-x86_64-fortanix-unknown-sgx",
+    "only-x86_64-pc-windows-gnu",
     "only-x86_64-pc-windows-msvc",
     "only-x86_64-unknown-linux-gnu",
     "pp-exact",
@@ -846,6 +881,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "unit-test",
     "unset-exec-env",
     "unset-rustc-env",
+    // tidy-alphabetical-end
 ];
 
 /// The broken-down contents of a line containing a test header directive,
@@ -876,6 +912,22 @@ struct HeaderLine<'ln> {
     directive: &'ln str,
 }
 
+pub(crate) struct CheckDirectiveResult<'ln> {
+    is_known_directive: bool,
+    directive_name: &'ln str,
+}
+
+// Returns `(is_known_directive, directive_name)`.
+pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> {
+    let directive_name =
+        directive_ln.split_once([':', ' ']).map(|(pre, _)| pre).unwrap_or(directive_ln);
+
+    CheckDirectiveResult {
+        is_known_directive: KNOWN_DIRECTIVE_NAMES.contains(&directive_name),
+        directive_name: directive_ln,
+    }
+}
+
 fn iter_header(
     mode: Mode,
     _suite: &str,
@@ -915,6 +967,7 @@ fn iter_header(
     let mut ln = String::new();
     let mut line_number = 0;
 
+    // Match on error annotations like `//~ERROR`.
     static REVISION_MAGIC_COMMENT_RE: Lazy<Regex> =
         Lazy::new(|| Regex::new("//(\\[.*\\])?~.*").unwrap());
 
@@ -933,9 +986,38 @@ fn iter_header(
         if ln.starts_with("fn") || ln.starts_with("mod") {
             return;
 
-        // First try to accept `ui_test` style comments
-        } else if let Some((header_revision, directive)) = line_directive(comment, ln) {
-            it(HeaderLine { line_number, original_line, header_revision, directive });
+        // First try to accept `ui_test` style comments (`//@`)
+        } else if let Some((header_revision, non_revisioned_directive_line)) =
+            line_directive(comment, ln)
+        {
+            // Perform unknown directive check on Rust files.
+            if testfile.extension().map(|e| e == "rs").unwrap_or(false) {
+                let directive_ln = non_revisioned_directive_line.trim();
+
+                let CheckDirectiveResult { is_known_directive, .. } = check_directive(directive_ln);
+
+                if !is_known_directive {
+                    *poisoned = true;
+
+                    eprintln!(
+                        "error: detected unknown compiletest test directive `{}` in {}:{}",
+                        directive_ln,
+                        testfile.display(),
+                        line_number,
+                    );
+
+                    return;
+                }
+            }
+
+            it(HeaderLine {
+                line_number,
+                original_line,
+                header_revision,
+                directive: non_revisioned_directive_line,
+            });
+        // Then we try to check for legacy-style candidates, which are not the magic ~ERROR family
+        // error annotations.
         } else if !REVISION_MAGIC_COMMENT_RE.is_match(ln) {
             let Some((_, rest)) = line_directive("//", ln) else {
                 continue;
@@ -949,34 +1031,18 @@ fn iter_header(
 
             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 compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
-                            testfile.display(),
-                            line_number,
-                            line_directive("//", ln),
-                        );
-                        return;
-                    };
+            let CheckDirectiveResult { is_known_directive, directive_name } = check_directive(rest);
 
-                    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 compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
-                            testfile.display(),
-                            line_number,
-                            line_directive("//", ln),
-                        );
-                        return;
-                    }
-                }
+            if is_known_directive {
+                *poisoned = true;
+                eprintln!(
+                    "error: detected legacy-style directive {} in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead: {:#?}",
+                    directive_name,
+                    testfile.display(),
+                    line_number,
+                    line_directive("//", ln),
+                );
+                return;
             }
         }
     }
diff --git a/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs b/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs
new file mode 100644
index 00000000000..fea66a5e07b
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs
@@ -0,0 +1,6 @@
+//@ check-pass
+
+//~ HELP
+fn main() {} //~ERROR
+//~^ ERROR
+//~| ERROR
diff --git a/src/tools/compiletest/src/header/test-auxillary/known_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_directive.rs
new file mode 100644
index 00000000000..99834b14c1e
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/known_directive.rs
@@ -0,0 +1,4 @@
+//! ignore-wasm
+//@ ignore-wasm
+//@ check-pass
+// regular comment
diff --git a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs
new file mode 100644
index 00000000000..108ca432e13
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs
@@ -0,0 +1 @@
+// ignore-wasm
diff --git a/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile b/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile
new file mode 100644
index 00000000000..4b565e0e6df
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile
@@ -0,0 +1 @@
+# ignore-owo
diff --git a/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs b/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs
new file mode 100644
index 00000000000..d4406031043
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs
@@ -0,0 +1 @@
+//@ needs-headpat
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 815ac3839df..433f3e8b555 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -5,6 +5,8 @@ use std::str::FromStr;
 use crate::common::{Config, Debugger, Mode};
 use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
 
+use super::iter_header;
+
 fn make_test_description<R: Read>(
     config: &Config,
     name: test::TestName,
@@ -612,3 +614,63 @@ fn threads_support() {
         assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads)
     }
 }
+
+fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) {
+    let rdr = std::io::Cursor::new(&buf);
+    iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
+}
+
+#[test]
+fn test_unknown_directive_check() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/unknown_directive.rs"),
+    );
+    assert!(poisoned);
+}
+
+#[test]
+fn test_known_legacy_directive_check() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/known_legacy_directive.rs"),
+    );
+    assert!(poisoned);
+}
+
+#[test]
+fn test_known_directive_check_no_error() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/known_directive.rs"),
+    );
+    assert!(!poisoned);
+}
+
+#[test]
+fn test_error_annotation_no_error() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/error_annotation.rs"),
+    );
+    assert!(!poisoned);
+}
+
+#[test]
+fn test_non_rs_unknown_directive_not_checked() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.Makefile"),
+        include_bytes!("./test-auxillary/not_rs.Makefile"),
+    );
+    assert!(!poisoned);
+}
diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
index ac0d4f6e099..b6bcf7b6617 100644
--- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
+++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
@@ -2,7 +2,7 @@
 
 // The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs
 //@[nll_beyond]compile-flags: -Z two-phase-beyond-autoref
-//[nll_beyond]should-fail
+//@[nll_beyond]should-fail
 
 // This is a corner case that the current implementation is (probably)
 // treating more conservatively than is necessary. But it also does
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
index dd2737c706d..d9d5dd4ece3 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
@@ -5,25 +5,25 @@ LL |     fn define() -> Opaque {
    |                    ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:27:9
+  --> $DIR/normalize-hidden-types.rs:26:9
    |
 LL |         dyn_hoops::<_>(0)
    |         ^^^^^^^^^^^^^^^^^
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:34:22
+  --> $DIR/normalize-hidden-types.rs:33:22
    |
 LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
    |                      ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:34:31
+  --> $DIR/normalize-hidden-types.rs:33:31
    |
 LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
    |                               ^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/normalize-hidden-types.rs:44:25
+  --> $DIR/normalize-hidden-types.rs:42:25
    |
 LL |     type Opaque = impl Sized;
    |                   ---------- the expected opaque type
@@ -39,13 +39,13 @@ LL |         let _: Opaque = dyn_hoops::<u8>(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:54:25
+  --> $DIR/normalize-hidden-types.rs:51:25
    |
 LL |         let _: Opaque = dyn_hoops::<_>(0);
    |                         ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:56:9
+  --> $DIR/normalize-hidden-types.rs:52:9
    |
 LL |         None
    |         ^^^^
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
index e78e6cf7690..d6800694e51 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
@@ -3,7 +3,7 @@
 //@ revisions: current next
 //@ [next] compile-flags: -Znext-solver
 //@ [next] check-pass
-//@ [current]: known-bug: #112691
+//@ [current] known-bug: #112691
 
 #![feature(type_alias_impl_trait)]
 
@@ -23,7 +23,6 @@ mod typeof_1 {
     use super::*;
     type Opaque = impl Sized;
     fn define() -> Opaque {
-        //[current]~^ ERROR concrete type differs
         dyn_hoops::<_>(0)
     }
 }
@@ -32,7 +31,6 @@ mod typeof_2 {
     use super::*;
     type Opaque = impl Sized;
     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
-    //[current]~^ ERROR concrete type differs
     fn define_2() -> Opaque { dyn_hoops::<u8>(0) }
 }
 
@@ -42,7 +40,6 @@ mod typeck {
     fn define() -> Option<Opaque> {
         let _: Opaque = dyn_hoops::<_>(0);
         let _: Opaque = dyn_hoops::<u8>(0);
-        //[current]~^ ERROR mismatched types
         None
     }
 }
@@ -52,7 +49,6 @@ mod borrowck {
     type Opaque = impl Sized;
     fn define() -> Option<Opaque> {
         let _: Opaque = dyn_hoops::<_>(0);
-        //[current]~^ ERROR concrete type differs
         None
     }
 }