Rollup merge of #139618 - petrochenkov:virsugg, r=jieyouxu

compiletest: Make `SUGGESTION` annotations viral

If one of them is expected in a test file, then others should be annotated as well, in the same way as with `HELP`s and `NOTE`s.
This doesn't require much of an additional annotation burden, but simplifies the rules.

r? ```@jieyouxu```
This commit is contained in:
Chris Denton 2025-04-13 11:48:17 +00:00 committed by GitHub
commit 423e7b8286
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 109 additions and 98 deletions

View file

@ -1,4 +1,4 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::BufReader;
@ -198,7 +198,7 @@ pub struct TestProps {
/// that don't otherwise want/need `-Z build-std`.
pub add_core_stubs: bool,
/// Whether line annotatins are required for the given error kind.
pub require_annotations: HashMap<ErrorKind, bool>,
pub dont_require_annotations: HashSet<ErrorKind>,
}
mod directives {
@ -301,13 +301,7 @@ impl TestProps {
no_auto_check_cfg: false,
has_enzyme: false,
add_core_stubs: false,
require_annotations: HashMap::from([
(ErrorKind::Help, true),
(ErrorKind::Note, true),
(ErrorKind::Error, true),
(ErrorKind::Warning, true),
(ErrorKind::Suggestion, false),
]),
dont_require_annotations: Default::default(),
}
}
@ -593,8 +587,8 @@ impl TestProps {
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);
self.dont_require_annotations
.insert(ErrorKind::expect_from_user_str(err_kind.trim()));
}
},
);

View file

@ -22,7 +22,7 @@ use crate::common::{
output_base_dir, output_base_name, output_testname_unique,
};
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
use crate::errors::{self, Error, ErrorKind};
use crate::errors::{Error, ErrorKind};
use crate::header::TestProps;
use crate::read2::{Truncated, read2_abbreviated};
use crate::util::{PathBufExt, add_dylib_path, logv, static_regex};
@ -675,7 +675,7 @@ impl<'test> TestCx<'test> {
}
}
fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &ProcRes) {
fn check_expected_errors(&self, expected_errors: Vec<Error>, proc_res: &ProcRes) {
debug!(
"check_expected_errors: expected_errors={:?} proc_res.status={:?}",
expected_errors, proc_res.status
@ -710,8 +710,12 @@ impl<'test> TestCx<'test> {
self.testpaths.file.display().to_string()
};
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));
// Errors and warnings are always expected, other diagnostics are only expected
// if one of them actually occurs in the test.
let expected_kinds: HashSet<_> = [ErrorKind::Error, ErrorKind::Warning]
.into_iter()
.chain(expected_errors.iter().filter_map(|e| e.kind))
.collect();
// Parse the JSON output from the compiler and extract out the messages.
let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res);
@ -737,8 +741,11 @@ impl<'test> TestCx<'test> {
}
None => {
// If the test is a known bug, don't require that the error is annotated
if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note)
if actual_error.require_annotation
&& actual_error.kind.map_or(false, |kind| {
expected_kinds.contains(&kind)
&& !self.props.dont_require_annotations.contains(&kind)
})
{
self.error(&format!(
"{}:{}: unexpected {}: '{}'",
@ -796,27 +803,6 @@ impl<'test> TestCx<'test> {
}
}
/// Returns `true` if we should report an error about `actual_error`,
/// which did not match any of the expected error.
fn is_unexpected_compiler_message(
&self,
actual_error: &Error,
expect_help: bool,
expect_note: bool,
) -> bool {
actual_error.require_annotation
&& actual_error.kind.map_or(false, |err_kind| {
// If the test being checked doesn't contain any "help" or "note" annotations, then
// we don't require annotating "help" or "note" (respecively) diagnostics at all.
let default_require_annotations = self.props.require_annotations[&err_kind];
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 {
match (pm, self.props.fail_mode, self.config.mode) {
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata,