Rollup merge of #139489 - petrochenkov:noreqann, r=jieyouxu
compiletest: Add directive `dont-require-annotations` for making matching on specific diagnostic kinds non-exhaustive. E.g. `//@ dont-require-annotations:ERROR`, like in the examples in this PR. cc https://github.com/rust-lang/rust/pull/139427#issuecomment-2782827583 Closes #132647 FYI `@BoxyUwU` since you've wanted this. r? `@jieyouxu`
This commit is contained in:
@@ -22,6 +22,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
|||||||
"dont-check-compiler-stderr",
|
"dont-check-compiler-stderr",
|
||||||
"dont-check-compiler-stdout",
|
"dont-check-compiler-stdout",
|
||||||
"dont-check-failure-status",
|
"dont-check-failure-status",
|
||||||
|
"dont-require-annotations",
|
||||||
"edition",
|
"edition",
|
||||||
"error-pattern",
|
"error-pattern",
|
||||||
"exact-llvm-major-version",
|
"exact-llvm-major-version",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::sync::OnceLock;
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum ErrorKind {
|
pub enum ErrorKind {
|
||||||
Help,
|
Help,
|
||||||
Error,
|
Error,
|
||||||
@@ -40,6 +40,15 @@ impl ErrorKind {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expect_from_user_str(s: &str) -> ErrorKind {
|
||||||
|
ErrorKind::from_user_str(s).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"unexpected diagnostic kind `{s}`, expected \
|
||||||
|
`ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ErrorKind {
|
impl fmt::Display for ErrorKind {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
@@ -11,6 +11,7 @@ use tracing::*;
|
|||||||
|
|
||||||
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
||||||
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
|
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
|
||||||
|
use crate::errors::ErrorKind;
|
||||||
use crate::executor::{CollectedTestDesc, ShouldPanic};
|
use crate::executor::{CollectedTestDesc, ShouldPanic};
|
||||||
use crate::header::auxiliary::{AuxProps, parse_and_update_aux};
|
use crate::header::auxiliary::{AuxProps, parse_and_update_aux};
|
||||||
use crate::header::needs::CachedNeedsConditions;
|
use crate::header::needs::CachedNeedsConditions;
|
||||||
@@ -196,6 +197,8 @@ pub struct TestProps {
|
|||||||
/// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios
|
/// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios
|
||||||
/// that don't otherwise want/need `-Z build-std`.
|
/// that don't otherwise want/need `-Z build-std`.
|
||||||
pub add_core_stubs: bool,
|
pub add_core_stubs: bool,
|
||||||
|
/// Whether line annotatins are required for the given error kind.
|
||||||
|
pub require_annotations: HashMap<ErrorKind, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod directives {
|
mod directives {
|
||||||
@@ -212,6 +215,7 @@ mod directives {
|
|||||||
pub const CHECK_RUN_RESULTS: &'static str = "check-run-results";
|
pub const CHECK_RUN_RESULTS: &'static str = "check-run-results";
|
||||||
pub const DONT_CHECK_COMPILER_STDOUT: &'static str = "dont-check-compiler-stdout";
|
pub const DONT_CHECK_COMPILER_STDOUT: &'static str = "dont-check-compiler-stdout";
|
||||||
pub const DONT_CHECK_COMPILER_STDERR: &'static str = "dont-check-compiler-stderr";
|
pub const DONT_CHECK_COMPILER_STDERR: &'static str = "dont-check-compiler-stderr";
|
||||||
|
pub const DONT_REQUIRE_ANNOTATIONS: &'static str = "dont-require-annotations";
|
||||||
pub const NO_PREFER_DYNAMIC: &'static str = "no-prefer-dynamic";
|
pub const NO_PREFER_DYNAMIC: &'static str = "no-prefer-dynamic";
|
||||||
pub const PRETTY_MODE: &'static str = "pretty-mode";
|
pub const PRETTY_MODE: &'static str = "pretty-mode";
|
||||||
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
|
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
|
||||||
@@ -297,6 +301,13 @@ impl TestProps {
|
|||||||
no_auto_check_cfg: false,
|
no_auto_check_cfg: false,
|
||||||
has_enzyme: false,
|
has_enzyme: false,
|
||||||
add_core_stubs: false,
|
add_core_stubs: false,
|
||||||
|
require_annotations: HashMap::from([
|
||||||
|
(ErrorKind::Help, true),
|
||||||
|
(ErrorKind::Note, true),
|
||||||
|
(ErrorKind::Error, true),
|
||||||
|
(ErrorKind::Warning, true),
|
||||||
|
(ErrorKind::Suggestion, false),
|
||||||
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,6 +581,13 @@ impl TestProps {
|
|||||||
config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg);
|
config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg);
|
||||||
|
|
||||||
self.update_add_core_stubs(ln, config);
|
self.update_add_core_stubs(ln, config);
|
||||||
|
|
||||||
|
if let Some(err_kind) =
|
||||||
|
config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
|
||||||
|
{
|
||||||
|
self.require_annotations
|
||||||
|
.insert(ErrorKind::expect_from_user_str(&err_kind), false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -709,10 +709,6 @@ impl<'test> TestCx<'test> {
|
|||||||
self.testpaths.file.display().to_string()
|
self.testpaths.file.display().to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the testcase being checked contains at least one expected "help"
|
|
||||||
// message, then we'll ensure that all "help" messages are expected.
|
|
||||||
// Otherwise, all "help" messages reported by the compiler will be ignored.
|
|
||||||
// This logic also applies to "note" messages.
|
|
||||||
let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
|
let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
|
||||||
let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
|
let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
|
||||||
|
|
||||||
@@ -800,9 +796,7 @@ impl<'test> TestCx<'test> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if we should report an error about `actual_error`,
|
/// Returns `true` if we should report an error about `actual_error`,
|
||||||
/// which did not match any of the expected error. We always require
|
/// which did not match any of the expected error.
|
||||||
/// errors/warnings to be explicitly listed, but only require
|
|
||||||
/// helps/notes if there are explicit helps/notes given.
|
|
||||||
fn is_unexpected_compiler_message(
|
fn is_unexpected_compiler_message(
|
||||||
&self,
|
&self,
|
||||||
actual_error: &Error,
|
actual_error: &Error,
|
||||||
@@ -810,12 +804,16 @@ impl<'test> TestCx<'test> {
|
|||||||
expect_note: bool,
|
expect_note: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
actual_error.require_annotation
|
actual_error.require_annotation
|
||||||
&& match actual_error.kind {
|
&& actual_error.kind.map_or(false, |err_kind| {
|
||||||
Some(ErrorKind::Help) => expect_help,
|
// If the test being checked doesn't contain any "help" or "note" annotations, then
|
||||||
Some(ErrorKind::Note) => expect_note,
|
// we don't require annotating "help" or "note" (respecively) diagnostics at all.
|
||||||
Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
|
let default_require_annotations = self.props.require_annotations[&err_kind];
|
||||||
Some(ErrorKind::Suggestion) | None => false,
|
match err_kind {
|
||||||
}
|
ErrorKind::Help => expect_help && default_require_annotations,
|
||||||
|
ErrorKind::Note => expect_note && default_require_annotations,
|
||||||
|
_ => default_require_annotations,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
|
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Error, the linked empty library is `no_std` and doesn't provide a panic handler.
|
// Error, the linked empty library is `no_std` and doesn't provide a panic handler.
|
||||||
|
|
||||||
//@ compile-flags: --error-format=human
|
//@ dont-require-annotations:ERROR
|
||||||
//@ error-pattern: `#[panic_handler]` function required, but not found
|
|
||||||
//@ dont-check-compiler-stderr
|
//@ dont-check-compiler-stderr
|
||||||
//@ aux-build: cfg_false_lib_no_std_before.rs
|
//@ aux-build: cfg_false_lib_no_std_before.rs
|
||||||
|
|
||||||
@@ -11,6 +10,7 @@ extern crate cfg_false_lib_no_std_before as _;
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// FIXME: The second error is target-dependent.
|
//~? ERROR `#[panic_handler]` function required, but not found
|
||||||
//FIXME~? ERROR `#[panic_handler]` function required, but not found
|
// FIXME: This error is target-dependent, could be served by some "optional error" annotation
|
||||||
|
// instead of `dont-require-annotations`.
|
||||||
//FIXME~? ERROR unwinding panics are not supported without std
|
//FIXME~? ERROR unwinding panics are not supported without std
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
//@ build-fail
|
//@ build-fail
|
||||||
//@ compile-flags: --error-format=human
|
//@ dont-require-annotations:ERROR
|
||||||
//@ error-pattern: cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2
|
|
||||||
//@ dont-check-compiler-stderr
|
//@ dont-check-compiler-stderr
|
||||||
//@ aux-build:panic-runtime-unwind.rs
|
//@ aux-build:panic-runtime-unwind.rs
|
||||||
//@ aux-build:panic-runtime-unwind2.rs
|
//@ aux-build:panic-runtime-unwind2.rs
|
||||||
@@ -16,7 +15,8 @@ extern crate panic_runtime_lang_items;
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// FIXME: The second and third errors are target-dependent.
|
//~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2
|
||||||
//FIXME~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2
|
// FIXME: These errors are target-dependent, could be served by some "optional error" annotation
|
||||||
|
// instead of `dont-require-annotations`.
|
||||||
//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind2` is not compiled with this crate's panic strategy `abort`
|
//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind2` is not compiled with this crate's panic strategy `abort`
|
||||||
//FIXME~? ERROR the crate `panic_runtime_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort`
|
//FIXME~? ERROR the crate `panic_runtime_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort`
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
//@ build-fail
|
//@ build-fail
|
||||||
//@ compile-flags: --error-format=human
|
//@ dont-require-annotations:ERROR
|
||||||
//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort`
|
|
||||||
//@ dont-check-compiler-stderr
|
//@ dont-check-compiler-stderr
|
||||||
//@ aux-build:panic-runtime-unwind.rs
|
//@ aux-build:panic-runtime-unwind.rs
|
||||||
//@ compile-flags:-C panic=abort
|
//@ compile-flags:-C panic=abort
|
||||||
@@ -10,7 +9,8 @@ extern crate panic_runtime_unwind;
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// FIXME: The first and third errors are target-dependent.
|
//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort`
|
||||||
|
// FIXME: These errors are target-dependent, could be served by some "optional error" annotation
|
||||||
|
// instead of `dont-require-annotations`.
|
||||||
//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind
|
//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind
|
||||||
//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort`
|
|
||||||
//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort`
|
//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort`
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
//@ build-fail
|
//@ build-fail
|
||||||
//@ compile-flags: --error-format=human
|
//@ dont-require-annotations:ERROR
|
||||||
//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort`
|
|
||||||
//@ dont-check-compiler-stderr
|
//@ dont-check-compiler-stderr
|
||||||
//@ aux-build:panic-runtime-unwind.rs
|
//@ aux-build:panic-runtime-unwind.rs
|
||||||
//@ aux-build:wants-panic-runtime-unwind.rs
|
//@ aux-build:wants-panic-runtime-unwind.rs
|
||||||
@@ -11,7 +10,8 @@ extern crate wants_panic_runtime_unwind;
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// FIXME: The first and third errors are target-dependent.
|
//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort`
|
||||||
|
// FIXME: These errors are target-dependent, could be served by some "optional error" annotation
|
||||||
|
// instead of `dont-require-annotations`.
|
||||||
//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind
|
//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind
|
||||||
//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort`
|
|
||||||
//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort`
|
//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort`
|
||||||
|
|||||||
Reference in New Issue
Block a user