compiletest: Always preserve kind for compiler diagnostics

Those that didn't previously preserved kind are now marked as not requiring annotations to keep the previous behavior.

Also, do not lose diagnostics with an empty message.
This commit is contained in:
Vadim Petrochenkov 2025-04-07 14:45:53 +03:00
parent 42048ea122
commit b86b3fb640
5 changed files with 46 additions and 29 deletions

View file

@ -53,6 +53,10 @@ pub struct Error {
/// `None` if not specified or unknown message kind.
pub kind: Option<ErrorKind>,
pub msg: String,
/// For some `Error`s, like secondary lines of multi-line diagnostics, line annotations
/// are not mandatory, even if they would otherwise be mandatory for primary errors.
/// Only makes sense for "actual" errors, not for "expected" errors.
pub require_annotation: bool,
}
impl Error {
@ -182,7 +186,7 @@ fn parse_expected(
kind,
msg
);
Some((follow_prev, Error { line_num, kind, msg }))
Some((follow_prev, Error { line_num, kind, msg, require_annotation: true }))
}
#[cfg(test)]

View file

@ -231,36 +231,42 @@ fn push_actual_errors(
// We expect to replace these with something more structured anyhow.
let mut message_lines = diagnostic.message.lines();
let kind = ErrorKind::from_str(&diagnostic.level).ok();
if let Some(first_line) = message_lines.next() {
let ignore = |s| {
static RE: OnceLock<Regex> = OnceLock::new();
RE.get_or_init(|| {
Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap()
})
.is_match(s)
};
if primary_spans.is_empty() && !ignore(first_line) {
errors.push(Error { line_num: None, kind, msg: with_code(None, first_line) });
let first_line = message_lines.next().unwrap_or(&diagnostic.message);
if primary_spans.is_empty() {
static RE: OnceLock<Regex> = OnceLock::new();
let re_init =
|| Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap();
errors.push(Error {
line_num: None,
kind,
msg: with_code(None, first_line),
require_annotation: !RE.get_or_init(re_init).is_match(first_line),
});
} else {
for span in primary_spans {
errors.push(Error {
line_num: Some(span.line_start),
kind,
msg: with_code(Some(span), first_line),
require_annotation: true,
});
}
}
for next_line in message_lines {
if primary_spans.is_empty() {
errors.push(Error {
line_num: None,
kind,
msg: with_code(None, next_line),
require_annotation: false,
});
} else {
for span in primary_spans {
errors.push(Error {
line_num: Some(span.line_start),
kind,
msg: with_code(Some(span), first_line),
});
}
}
}
for next_line in message_lines {
if primary_spans.is_empty() {
errors.push(Error { line_num: None, kind: None, msg: with_code(None, next_line) });
} else {
for span in primary_spans {
errors.push(Error {
line_num: Some(span.line_start),
kind: None,
msg: with_code(Some(span), next_line),
require_annotation: false,
});
}
}
@ -274,6 +280,7 @@ fn push_actual_errors(
line_num: Some(span.line_start + index),
kind: Some(ErrorKind::Suggestion),
msg: line.to_string(),
require_annotation: true,
});
}
}
@ -292,6 +299,7 @@ fn push_actual_errors(
line_num: Some(span.line_start),
kind: Some(ErrorKind::Note),
msg: span.label.clone().unwrap(),
require_annotation: true,
});
}
@ -311,6 +319,7 @@ fn push_backtrace(
line_num: Some(expansion.span.line_start),
kind: Some(ErrorKind::Note),
msg: format!("in this expansion of {}", expansion.macro_decl_name),
require_annotation: true,
});
}

View file

@ -811,6 +811,7 @@ impl<'test> TestCx<'test> {
expect_note: bool,
) -> bool {
!actual_error.msg.is_empty()
&& actual_error.require_annotation
&& match actual_error.kind {
Some(ErrorKind::Help) => expect_help,
Some(ErrorKind::Note) => expect_note,