Skip to content

Commit cffc5c2

Browse files
committed
compiletest: Add directive dont-require-annotations
for making matching on specific diagnostic kinds non-exhaustive
1 parent c1b8b7e commit cffc5c2

File tree

4 files changed

+41
-15
lines changed

4 files changed

+41
-15
lines changed

Diff for: src/tools/compiletest/src/directive-list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
2222
"dont-check-compiler-stderr",
2323
"dont-check-compiler-stdout",
2424
"dont-check-failure-status",
25+
"dont-require-annotations",
2526
"edition",
2627
"error-pattern",
2728
"exact-llvm-major-version",

Diff for: src/tools/compiletest/src/errors.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::sync::OnceLock;
88
use regex::Regex;
99
use tracing::*;
1010

11-
#[derive(Copy, Clone, Debug, PartialEq)]
11+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1212
pub enum ErrorKind {
1313
Help,
1414
Error,
@@ -40,6 +40,15 @@ impl ErrorKind {
4040
_ => return None,
4141
})
4242
}
43+
44+
pub fn expect_from_user_str(s: &str) -> ErrorKind {
45+
ErrorKind::from_user_str(s).unwrap_or_else(|| {
46+
panic!(
47+
"unexpected diagnostic kind `{s}`, expected \
48+
`ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`"
49+
)
50+
})
51+
}
4352
}
4453

4554
impl fmt::Display for ErrorKind {

Diff for: src/tools/compiletest/src/header.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashSet;
1+
use std::collections::{HashMap, HashSet};
22
use std::env;
33
use std::fs::File;
44
use std::io::BufReader;
@@ -11,6 +11,7 @@ use tracing::*;
1111

1212
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
1313
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
14+
use crate::errors::ErrorKind;
1415
use crate::executor::{CollectedTestDesc, ShouldPanic};
1516
use crate::header::auxiliary::{AuxProps, parse_and_update_aux};
1617
use crate::header::needs::CachedNeedsConditions;
@@ -196,6 +197,8 @@ pub struct TestProps {
196197
/// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios
197198
/// that don't otherwise want/need `-Z build-std`.
198199
pub add_core_stubs: bool,
200+
/// Whether line annotatins are required for the given error kind.
201+
pub require_annotations: HashMap<ErrorKind, bool>,
199202
}
200203

201204
mod directives {
@@ -212,6 +215,7 @@ mod directives {
212215
pub const CHECK_RUN_RESULTS: &'static str = "check-run-results";
213216
pub const DONT_CHECK_COMPILER_STDOUT: &'static str = "dont-check-compiler-stdout";
214217
pub const DONT_CHECK_COMPILER_STDERR: &'static str = "dont-check-compiler-stderr";
218+
pub const DONT_REQUIRE_ANNOTATIONS: &'static str = "dont-require-annotations";
215219
pub const NO_PREFER_DYNAMIC: &'static str = "no-prefer-dynamic";
216220
pub const PRETTY_MODE: &'static str = "pretty-mode";
217221
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
@@ -297,6 +301,13 @@ impl TestProps {
297301
no_auto_check_cfg: false,
298302
has_enzyme: false,
299303
add_core_stubs: false,
304+
require_annotations: HashMap::from([
305+
(ErrorKind::Help, true),
306+
(ErrorKind::Note, true),
307+
(ErrorKind::Error, true),
308+
(ErrorKind::Warning, true),
309+
(ErrorKind::Suggestion, false),
310+
]),
300311
}
301312
}
302313

@@ -570,6 +581,13 @@ impl TestProps {
570581
config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg);
571582

572583
self.update_add_core_stubs(ln, config);
584+
585+
if let Some(err_kind) =
586+
config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
587+
{
588+
self.require_annotations
589+
.insert(ErrorKind::expect_from_user_str(&err_kind), false);
590+
}
573591
},
574592
);
575593

Diff for: src/tools/compiletest/src/runtest.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,6 @@ impl<'test> TestCx<'test> {
710710
self.testpaths.file.display().to_string()
711711
};
712712

713-
// If the testcase being checked contains at least one expected "help"
714-
// message, then we'll ensure that all "help" messages are expected.
715-
// Otherwise, all "help" messages reported by the compiler will be ignored.
716-
// This logic also applies to "note" messages.
717713
let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
718714
let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
719715

@@ -801,22 +797,24 @@ impl<'test> TestCx<'test> {
801797
}
802798

803799
/// Returns `true` if we should report an error about `actual_error`,
804-
/// which did not match any of the expected error. We always require
805-
/// errors/warnings to be explicitly listed, but only require
806-
/// helps/notes if there are explicit helps/notes given.
800+
/// which did not match any of the expected error.
807801
fn is_unexpected_compiler_message(
808802
&self,
809803
actual_error: &Error,
810804
expect_help: bool,
811805
expect_note: bool,
812806
) -> bool {
813807
actual_error.require_annotation
814-
&& match actual_error.kind {
815-
Some(ErrorKind::Help) => expect_help,
816-
Some(ErrorKind::Note) => expect_note,
817-
Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
818-
Some(ErrorKind::Suggestion) | None => false,
819-
}
808+
&& actual_error.kind.map_or(false, |err_kind| {
809+
// If the test being checked doesn't contain any "help" or "note" annotations, then
810+
// we don't require annotating "help" or "note" (respecively) diagnostics at all.
811+
let default_require_annotations = self.props.require_annotations[&err_kind];
812+
match err_kind {
813+
ErrorKind::Help => expect_help && default_require_annotations,
814+
ErrorKind::Note => expect_note && default_require_annotations,
815+
_ => default_require_annotations,
816+
}
817+
})
820818
}
821819

822820
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {

0 commit comments

Comments
 (0)