Skip to content

Commit 13e8790

Browse files
committed
Auto merge of rust-lang#140599 - petrochenkov:rawerann, r=jieyouxu
compiletest: Support matching on non-json lines in compiler output and migrate most of remaining `error-pattern`s to it. Such diagnostics use a new diagnostic kind `RAW`. Also emit an error for `error-pattern`s that can be replaced with line annotations. Also remove a number of conditions to check both line annotations and `error-pattern`s in more cases. Also respect `//@ check-stdout` when collecting "actual errors" for comparing against line annotations. (A couple of tiny refactorings is also included.) Continuation of rust-lang#139760. r? `@jieyouxu`
2 parents ab62d56 + 56d6b4e commit 13e8790

File tree

63 files changed

+208
-196
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+208
-196
lines changed

src/doc/rustc-dev-guide/src/tests/ui.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,7 @@ For checking runtime output, `//@ check-run-results` may be preferable.
344344

345345
Only use `error-pattern` if none of the above works.
346346

347-
Line annotations `//~` are still checked in tests using `error-pattern`.
348-
In exceptional cases, use `//@ compile-flags: --error-format=human` to opt out of these checks.
347+
Line annotations `//~` and `error-pattern` are compatible and can be used in the same test.
349348

350349
### Diagnostic kinds (error levels)
351350

@@ -356,9 +355,12 @@ The diagnostic kinds that you can have are:
356355
- `NOTE`
357356
- `HELP`
358357
- `SUGGESTION`
358+
- `RAW`
359359

360360
The `SUGGESTION` kind is used for specifying what the expected replacement text
361361
should be for a diagnostic suggestion.
362+
The `RAW` kind can be used for matching on lines from non-structured output sometimes emitted
363+
by the compiler instead of or in addition to structured json.
362364

363365
`ERROR` and `WARN` kinds are required to be exhaustively covered by line annotations
364366
`//~` by default.

src/tools/compiletest/src/errors.rs

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub enum ErrorKind {
1515
Note,
1616
Suggestion,
1717
Warning,
18+
Raw,
1819
}
1920

2021
impl ErrorKind {
@@ -39,6 +40,7 @@ impl ErrorKind {
3940
"NOTE" | "note" | "MONO_ITEM" => ErrorKind::Note,
4041
"SUGGESTION" => ErrorKind::Suggestion,
4142
"WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning,
43+
"RAW" => ErrorKind::Raw,
4244
_ => panic!(
4345
"unexpected diagnostic kind `{s}`, expected \
4446
`ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`"
@@ -55,6 +57,7 @@ impl fmt::Display for ErrorKind {
5557
ErrorKind::Note => write!(f, "NOTE"),
5658
ErrorKind::Suggestion => write!(f, "SUGGESTION"),
5759
ErrorKind::Warning => write!(f, "WARN"),
60+
ErrorKind::Raw => write!(f, "RAW"),
5861
}
5962
}
6063
}

src/tools/compiletest/src/json.rs

+11-21
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use regex::Regex;
77
use serde::Deserialize;
88

99
use crate::errors::{Error, ErrorKind};
10-
use crate::runtest::ProcRes;
1110

1211
#[derive(Deserialize)]
1312
struct Diagnostic {
@@ -140,28 +139,19 @@ pub fn extract_rendered(output: &str) -> String {
140139
.collect()
141140
}
142141

143-
pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
142+
pub fn parse_output(file_name: &str, output: &str) -> Vec<Error> {
144143
let mut errors = Vec::new();
145144
for line in output.lines() {
146-
// The compiler sometimes intermingles non-JSON stuff into the
147-
// output. This hack just skips over such lines. Yuck.
148-
if line.starts_with('{') {
149-
match serde_json::from_str::<Diagnostic>(line) {
150-
Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name),
151-
Err(error) => {
152-
// Ignore the future compat report message - this is handled
153-
// by `extract_rendered`
154-
if serde_json::from_str::<FutureIncompatReport>(line).is_err() {
155-
proc_res.fatal(
156-
Some(&format!(
157-
"failed to decode compiler output as json: `{}`\nline: {}\noutput: {}",
158-
error, line, output
159-
)),
160-
|| (),
161-
);
162-
}
163-
}
164-
}
145+
// Compiler can emit non-json lines in non-`--error-format=json` modes,
146+
// and in some situations even in json mode.
147+
match serde_json::from_str::<Diagnostic>(line) {
148+
Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name),
149+
Err(_) => errors.push(Error {
150+
line_num: None,
151+
kind: ErrorKind::Raw,
152+
msg: line.to_string(),
153+
require_annotation: false,
154+
}),
165155
}
166156
}
167157
errors

src/tools/compiletest/src/runtest.rs

+22-21
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::common::{
2323
output_base_dir, output_base_name, output_testname_unique,
2424
};
2525
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
26-
use crate::errors::{Error, ErrorKind};
26+
use crate::errors::{Error, ErrorKind, load_errors};
2727
use crate::header::TestProps;
2828
use crate::read2::{Truncated, read2_abbreviated};
2929
use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex};
@@ -577,23 +577,9 @@ impl<'test> TestCx<'test> {
577577
}
578578
}
579579

580-
fn check_all_error_patterns(
581-
&self,
582-
output_to_check: &str,
583-
proc_res: &ProcRes,
584-
pm: Option<PassMode>,
585-
) {
586-
if self.props.error_patterns.is_empty() && self.props.regex_error_patterns.is_empty() {
587-
if pm.is_some() {
588-
// FIXME(#65865)
589-
return;
590-
} else {
591-
self.fatal(&format!("no error pattern specified in {}", self.testpaths.file));
592-
}
593-
}
594-
580+
/// Check `error-pattern` and `regex-error-pattern` directives.
581+
fn check_all_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) {
595582
let mut missing_patterns: Vec<String> = Vec::new();
596-
597583
self.check_error_patterns(output_to_check, &mut missing_patterns);
598584
self.check_regex_error_patterns(output_to_check, proc_res, &mut missing_patterns);
599585

@@ -670,7 +656,9 @@ impl<'test> TestCx<'test> {
670656
}
671657
}
672658

673-
fn check_expected_errors(&self, expected_errors: Vec<Error>, proc_res: &ProcRes) {
659+
/// Check `//~ KIND message` annotations.
660+
fn check_expected_errors(&self, proc_res: &ProcRes) {
661+
let expected_errors = load_errors(&self.testpaths.file, self.revision);
674662
debug!(
675663
"check_expected_errors: expected_errors={:?} proc_res.status={:?}",
676664
expected_errors, proc_res.status
@@ -711,11 +699,24 @@ impl<'test> TestCx<'test> {
711699
.collect();
712700

713701
// Parse the JSON output from the compiler and extract out the messages.
714-
let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res);
702+
let actual_errors = json::parse_output(&diagnostic_file_name, &self.get_output(proc_res))
703+
.into_iter()
704+
.map(|e| Error { msg: self.normalize_output(&e.msg, &[]), ..e });
705+
715706
let mut unexpected = Vec::new();
716707
let mut found = vec![false; expected_errors.len()];
717-
for mut actual_error in actual_errors {
718-
actual_error.msg = self.normalize_output(&actual_error.msg, &[]);
708+
for actual_error in actual_errors {
709+
for pattern in &self.props.error_patterns {
710+
let pattern = pattern.trim();
711+
if actual_error.msg.contains(pattern) {
712+
let q = if actual_error.line_num.is_none() { "?" } else { "" };
713+
self.fatal(&format!(
714+
"error pattern '{pattern}' is found in structured \
715+
diagnostics, use `//~{q} {} {pattern}` instead",
716+
actual_error.kind,
717+
));
718+
}
719+
}
719720

720721
let opt_index =
721722
expected_errors.iter().enumerate().position(|(index, expected_error)| {

src/tools/compiletest/src/runtest/incremental.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,8 @@ impl TestCx<'_> {
100100
self.check_no_compiler_crash(&proc_res, self.props.should_ice);
101101

102102
let output_to_check = self.get_output(&proc_res);
103-
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
104-
if !expected_errors.is_empty() {
105-
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
106-
{
107-
self.fatal("both error pattern and expected errors specified");
108-
}
109-
self.check_expected_errors(expected_errors, &proc_res);
110-
} else {
111-
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
112-
}
103+
self.check_expected_errors(&proc_res);
104+
self.check_all_error_patterns(&output_to_check, &proc_res);
113105
if self.props.should_ice {
114106
match proc_res.status.code() {
115107
Some(101) => (),
@@ -137,6 +129,6 @@ impl TestCx<'_> {
137129

138130
let output_to_check = self.get_output(&proc_res);
139131
self.check_correct_failure_status(&proc_res);
140-
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
132+
self.check_all_error_patterns(&output_to_check, &proc_res);
141133
}
142134
}

src/tools/compiletest/src/runtest/ui.rs

+10-37
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::{
99
AllowUnused, Emit, FailMode, LinkToAux, PassMode, TargetLocation, TestCx, TestOutput,
1010
Truncated, UI_FIXED, WillExecute,
1111
};
12-
use crate::{errors, json};
12+
use crate::json;
1313

1414
impl TestCx<'_> {
1515
pub(super) fn run_ui_test(&self) {
@@ -127,9 +127,7 @@ impl TestCx<'_> {
127127
);
128128
}
129129

130-
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
131-
132-
if let WillExecute::Yes = should_run {
130+
let output_to_check = if let WillExecute::Yes = should_run {
133131
let proc_res = self.exec_compiled_test();
134132
let run_output_errors = if self.props.check_run_results {
135133
self.load_compare_outputs(&proc_res, TestOutput::Run, explicit)
@@ -150,44 +148,19 @@ impl TestCx<'_> {
150148
self.fatal_proc_rec("test run succeeded!", &proc_res);
151149
}
152150

153-
let output_to_check = self.get_output(&proc_res);
154-
if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
155-
{
156-
// "// error-pattern" comments
157-
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
158-
}
159-
self.check_forbid_output(&output_to_check, &proc_res)
160-
}
151+
self.get_output(&proc_res)
152+
} else {
153+
self.get_output(&proc_res)
154+
};
161155

162156
debug!(
163-
"run_ui_test: explicit={:?} config.compare_mode={:?} expected_errors={:?} \
157+
"run_ui_test: explicit={:?} config.compare_mode={:?} \
164158
proc_res.status={:?} props.error_patterns={:?}",
165-
explicit,
166-
self.config.compare_mode,
167-
expected_errors,
168-
proc_res.status,
169-
self.props.error_patterns
159+
explicit, self.config.compare_mode, proc_res.status, self.props.error_patterns
170160
);
171161

172-
if !explicit && self.config.compare_mode.is_none() {
173-
// "//~ERROR comments"
174-
self.check_expected_errors(expected_errors, &proc_res);
175-
} else if explicit && !expected_errors.is_empty() {
176-
let msg = format!(
177-
"line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
178-
expected_errors[0].line_num_str(),
179-
expected_errors[0].kind,
180-
);
181-
self.fatal(&msg);
182-
}
183-
let output_to_check = self.get_output(&proc_res);
184-
if should_run == WillExecute::No
185-
&& (!self.props.error_patterns.is_empty()
186-
|| !self.props.regex_error_patterns.is_empty())
187-
{
188-
// "// error-pattern" comments
189-
self.check_all_error_patterns(&output_to_check, &proc_res, pm);
190-
}
162+
self.check_expected_errors(&proc_res);
163+
self.check_all_error_patterns(&output_to_check, &proc_res);
191164
self.check_forbid_output(&output_to_check, &proc_res);
192165

193166
if self.props.run_rustfix && self.config.compare_mode.is_none() {

tests/incremental/ich_nested_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#![crate_type = "rlib"]
99
#![feature(rustc_attrs)]
10+
#![allow(dead_code)]
1011

1112
#[rustc_clean(except = "opt_hir_owner_nodes", cfg = "cfail2")]
1213
pub fn foo() {

tests/incremental/incremental_proc_macro.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ extern crate incremental_proc_macro_aux;
1212

1313
#[derive(IncrementalMacro)]
1414
pub struct Foo {
15-
x: u32
15+
_x: u32
1616
}

tests/incremental/issue-49595/issue-49595.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
mod tests {
1212
#[cfg_attr(not(cfail1), test)]
13-
fn test() {
13+
fn _test() {
1414
}
1515
}
1616

tests/incremental/issue-84252-global-alloc.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ revisions: cfail1 cfail2
22
//@ build-pass
3+
//@ needs-crate-type: cdylib
34

45
#![crate_type="lib"]
56
#![crate_type="cdylib"]

tests/incremental/issue-85360-eval-obligation-ice.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//@ edition: 2021
55
//@ build-pass
66

7+
#![allow(dead_code)]
8+
79
use core::any::Any;
810
use core::marker::PhantomData;
911

tests/incremental/no_mangle.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//@ revisions:cfail1 cfail2
22
//@ check-pass
33
//@ compile-flags: --crate-type cdylib
4+
//@ needs-crate-type: cdylib
45

56
#![deny(unused_attributes)]
67

tests/incremental/thinlto/cgu_keeps_identical_fn.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333
mod foo {
3434

3535
// Trivial functions like this one are imported very reliably by ThinLTO.
36-
#[cfg(any(cfail1, cfail4))]
36+
#[cfg(cfail1)]
3737
pub fn inlined_fn() -> u32 {
3838
1234
3939
}
4040

41-
#[cfg(not(any(cfail1, cfail4)))]
41+
#[cfg(not(cfail1))]
4242
pub fn inlined_fn() -> u32 {
4343
1234
4444
}

tests/incremental/unrecoverable_query.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
//@ compile-flags: --crate-type=lib
99
//@ build-pass
1010

11+
#![allow(dead_code)]
12+
1113
pub trait P {
1214
type A;
1315
}

tests/rustdoc-ui/ice-bug-report-url.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//@ compile-flags: -Ztreat-err-as-bug
22
//@ rustc-env:RUSTC_ICE=0
33
//@ failure-status: 101
4-
//@ error-pattern: aborting due to
5-
//@ error-pattern: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md
64

75
//@ normalize-stderr: "note: compiler flags.*\n\n" -> ""
86
//@ normalize-stderr: "note: rustc.*running on.*" -> "note: rustc {version} running on {platform}"
@@ -13,3 +11,6 @@
1311

1412
fn wrong()
1513
//~^ ERROR expected one of
14+
15+
//~? RAW aborting due to
16+
//~? RAW we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md

tests/rustdoc-ui/ice-bug-report-url.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: internal compiler error: expected one of `->`, `where`, or `{`, found `<eof>`
2-
--> $DIR/ice-bug-report-url.rs:14:10
2+
--> $DIR/ice-bug-report-url.rs:12:10
33
|
44
LL | fn wrong()
55
| ^ expected one of `->`, `where`, or `{`

tests/rustdoc-ui/issues/issue-81662-shortness.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//@ compile-flags:--test --error-format=short
22
//@ check-stdout
3-
//@ error-pattern:cannot find function `foo`
43
//@ normalize-stdout: "tests/rustdoc-ui/issues" -> "$$DIR"
54
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
65
//@ failure-status: 101
@@ -11,3 +10,5 @@
1110
fn foo() {
1211
println!("Hello, world!");
1312
}
13+
14+
//~? RAW cannot find function `foo`
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11

22
running 1 test
3-
test $DIR/issue-81662-shortness.rs - foo (line 8) ... FAILED
3+
test $DIR/issue-81662-shortness.rs - foo (line 7) ... FAILED
44

55
failures:
66

7-
---- $DIR/issue-81662-shortness.rs - foo (line 8) stdout ----
8-
$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope: not found in this scope
7+
---- $DIR/issue-81662-shortness.rs - foo (line 7) stdout ----
8+
$DIR/issue-81662-shortness.rs:8:1: error[E0425]: cannot find function `foo` in this scope: not found in this scope
99
error: aborting due to 1 previous error
1010
Couldn't compile the test.
1111

1212
failures:
13-
$DIR/issue-81662-shortness.rs - foo (line 8)
13+
$DIR/issue-81662-shortness.rs - foo (line 7)
1414

1515
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
1616

0 commit comments

Comments
 (0)